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 would like to propose a workaround for this. It is working fine if you replace the ObservableCollection<ObservableCollection<String>> with ObservableCollection<WorkaroundClass> where the WorkaroundClass has a public property of type ObservableCollection :
public class WorkAround { public ObservableCollection<String> obs { get; set; } public WorkAround() { obs = new ObservableCollection<string>(); obs.Add("string1"); obs.Add("string2"); obs.Add("string3"); } }
Hope this helps.
Hi Alex,
Thanks for the suggestion. We have worked around this problem in a similar way by implementing model wrappers around our data classes in the UI (for more reasons than just solving this problem). It's good to know there's a c# only solution though.
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.
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.
Please suggest how can I use ObservableCollection<ObservableCollection<string>> for tableValues for Hierarchical Data ? How can I specify relationship between 2 levels?
Regards,
For resolving the performance issue, I would recommend starting with going through the suggestions in Optimizing Infragistics XamDataGrid Performance.
If you have been through that and are still seeing performance issues then it would be best to get a sample from you demonstrating the issue so we can see what is causing the decrease in performance.
I have Hierarchical xamDataGrid, with 4 levels, each level with 2000+ rows. I need to keep updating whole Grid (all rows) in every 3 sec. Since I need to support Dynamic Columns, I am using DataSet with 4 DataTables, and DataRelation for Hierarchical Data. I finish updating DataSet in 1 sec. But When I try to update UI (xamDataGrid) using the INotifyPropertyChanged RaisePropertyChangedEvent('xamDataGrid') from ViewModel, it freezes screen for 5-20 seconds or more. If all 4 levels are collapsed, it works fine, but if all 4 levels are expanded then it freezes for 20 seconds or more.
Thanks,Shakti