I mean i need to bind unbound fields programmatically but i cannot manage to bind to a DataSource of type ObservableCollection<ObservableCollection<String>> sCol :
<igDP:XamDataGrid x:Name="xamDataGrid" DataSource="{Binding sCol}"> <igDP:XamDataGrid.FieldLayoutSettings> <igDP:FieldLayoutSettings AutoGenerateFields="False" /> </igDP:XamDataGrid.FieldLayoutSettings> <igDP:XamDataGrid.FieldLayouts> <igDP:FieldLayout> <igDP:FieldLayout.Fields> <igDP:UnboundField Label="Col1" BindingPath="[0]" BindingMode="TwoWay" DataType="sys:String" /> <igDP:UnboundField Label="Col2" BindingPath="[1]" BindingMode="TwoWay" DataType="sys:String"/> </igDP:FieldLayout.Fields> </igDP:FieldLayout> </igDP:XamDataGrid.FieldLayouts> </igDP:XamDataGrid>
Ouput traces say :
System.Windows.Data Error: 39 : BindingExpression path error: '[' property not found on 'object' ''EnumerableObjectWrapper' (HashCode=14407208)'. BindingExpression:Path=[1]; DataItem='EnumerableObjectWrapper' (HashCode=14407208); target element is 'a' (HashCode=44344604); target property is 'Value' (type 'Object')
I can achive a correct binding through a regular listView though :
<ListView ItemsSource="{Binding sCol}"> <ListView.View> <GridView> <GridViewColumn Header="Col1" DisplayMemberBinding="{Binding [0]}"/> <GridViewColumn Header="Col2" DisplayMemberBinding="{Binding [1]}"/> </GridView> </ListView.View> </ListView>
It seems that the grid DataSource property does not behave like the list ItemsSource property.
What am I missing ?
Cheers.
Just to let you know that I also managed to make the Xceed grid works in the same context :
<xcdg:DataGridControl Name="xtraGrid" ItemsSource="{Binding Source={StaticResource xtraGridView}}" AutoCreateColumns="False" > <xcdg:DataGridControl.Columns> <xcdg:Column FieldName="[0]" Title="Col1" /> <xcdg:Column FieldName="[1]" Title="Col2" /> </xcdg:DataGridControl.Columns> </xcdg:DataGridControl>
We are actually trying various WPF datagrids on the market to make our choice for my job. I would be very disappointed if we could not go further with your grid. I m sure it's just my mistake and not an issue with your design.
Please help :-)
Hi,
Has anyone found a solution to this problem?
We are experiencing exactly the same thing. In C# only an indexer can take a parameter so you have to be able to specify a parameter without a property as this post describes, i.e. FieldName="[0]".
Cheers,
Dave
Hello,
I am following up on this post to provide additional details. Internally an EnumerableObjectWrapper gets used to wrap lists of lists when the XamDataGrid is bound to them and this is why the BindingPath of "[0]" will fail. The EnumerableObjectWrapper does expose an Items collection that you can use in the BindingPath: "Items[0]"
Here is a code snippet that demonstrates this:
XamDataGrid xamDataGrid1 = new XamDataGrid(); this.Content = xamDataGrid1; xamDataGrid1.FieldLayoutSettings.AutoGenerateFields = false; ObservableCollection<string> headers = new ObservableCollection<string> { "FirstName", "LastName", "Age" }; ObservableCollection<string> row1 = new ObservableCollection<string> { "John", "Doe", "19" }; ObservableCollection<string> row2 = new ObservableCollection<string> { "Jane", "Doe", "21" }; ObservableCollection<string> row3 = new ObservableCollection<string> { "Suzie", "Q", "52" }; ObservableCollection<string> row4 = new ObservableCollection<string> { "No", "Body", "48" }; ObservableCollection<ObservableCollection<string>> tableValues = new ObservableCollection<ObservableCollection<string>> { row1, row2, row3, row4 }; FieldLayout fldLayout = new FieldLayout(); for (int i = 0; i < headers.Count; i++) { string s = headers[i]; UnboundField uf = new UnboundField(); uf.Name = s; uf.Label = s; uf.BindingPath = new PropertyPath("Items[" + i.ToString() + "]",null); fldLayout.Fields.Add(uf); } xamDataGrid1.FieldLayouts.Add(fldLayout); xamDataGrid1.DataSource = tableValues;
Hi Alan,
Please suggest the changes in above code for Hierarchial Data with 2 layers.
Thanks,
Shakti
Shakti,
Please provide more details on what you are looking for. If you are looking for a dynamic data structure, it would be simpler to use a DataSet than to use the code that I provided above. The code that I have provided above was meant as an example of how you could use unbound Fields to show items from a collection. Note that the simplified example has many limitations including that there are no change notifications for when changes are made to the data.
Let me know if you have any questions with this matter.
Please suggest how can I use ObservableCollection<ObservableCollection<string>> for tableValues for Hierarchical Data ? How can I specify relationship between 2 levels?
Regards,
You would need an IEnumerable exposed by a data item. See the following example:
XamDataGrid xamDataGrid1 = new XamDataGrid(); xamDataGrid1.PreviewMouseDoubleClick += new MouseButtonEventHandler(xamDataGrid1_PreviewMouseDoubleClick); this.Content = xamDataGrid1; xamDataGrid1.FieldLayoutSettings.AutoGenerateFields = false; ObservableCollection<string> headers = new ObservableCollection<string> { "FirstName", "LastName", "Age" }; ObservableCollection<string> childHeaders = new ObservableCollection<string> { "ChildField1", "ChildField2", "ChildField3" }; ObservableCollection<string> childRow1 = new ObservableCollection<string> { "One", "Two", "Three" }; ObservableCollection<string> childRow2 = new ObservableCollection<string> { "One", "Two", "Three" }; ObservableCollection<string> childRow3 = new ObservableCollection<string> { "One", "Two", "Three" }; ObservableCollection<ObservableCollection<string>> childTableValues = new ObservableCollection<ObservableCollection<string>> { childRow1, childRow2, childRow3 }; ObservableCollection<string> row1 = new ObservableCollection<string> { "John", "Doe", "19" }; ObservableCollection<string> row2 = new ObservableCollection<string> { "Jane", "Doe", "21" }; ObservableCollection<string> row3 = new ObservableCollection<string> { "Suzie", "Q", "52" }; ObservableCollection<string> row4 = new ObservableCollection<string> { "No", "Body", "48" }; ObservableCollection<DataRow> tableValues = new ObservableCollection<DataRow>(); tableValues.Add(new DataRow() {Values=row1, Children = childTableValues}); tableValues.Add(new DataRow() { Values = row2 }); tableValues.Add(new DataRow() { Values = row3 }); tableValues.Add(new DataRow() { Values = row4 }); FieldLayout fldLayout = new FieldLayout(); Field f = new Field(); f.Name = "Children"; fldLayout.Fields.Add(f); for (int i = 0; i < headers.Count; i++) { string s = headers[i]; UnboundField uf = new UnboundField(); uf.Name = s; uf.Label = s; uf.BindingPath = new PropertyPath("Values[" + i.ToString() + "]", null); fldLayout.Fields.Add(uf); } FieldLayout childLayout = new FieldLayout(); for (int i = 0; i < childHeaders.Count; i++) { string s = childHeaders[i]; UnboundField uf = new UnboundField(); uf.Name = s; uf.Label = s; uf.BindingPath = new PropertyPath("[" + i.ToString() + "]", null); childLayout.Fields.Add(uf); } xamDataGrid1.FieldLayouts.Add(fldLayout); xamDataGrid1.FieldLayouts.Add(childLayout); xamDataGrid1.DataSource = tableValues;
The above will require the following additional class:
public class DataRow { private ObservableCollection<string> values = new ObservableCollection<string>(); public ObservableCollection<string> Values { get { return this.values; } set { this.values = value; } } private ObservableCollection<ObservableCollection<string>> children = new ObservableCollection<ObservableCollection<string>>(); public ObservableCollection<ObservableCollection<string>> Children { get { return this.children; } set { this.children = value; } } }
I would still recommend using a DataTable over this approach and if you are seeing performance issues when using the DataTable I would like to see a sample demonstrating the issue so that I can look into how to improve the performance.