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.
Prasanna,
It isn't possible to have a binding on the FieldLayout because it isn't actually part of the visual or logical trees. Assuming that the number of fields will still change dynamically you would be best off creating a UserControl that contains the XamDataGrid that exposes a property that you can set for the DataSource and Headers and then when those properties change update your FieldLayout accordingly. While this would require writing code in the UserControl, when you consume the UserControl you could still use MVVM.
Let me know if you have any questions with this matter.
Hi Alan,
Is there any MVVM solution for the above where we can change the FieldLayout in the ViewModel?
Regards,
Prasanna
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 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.
Dave
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.