I've been struggling for hours with this so hopefully someone can point me in the right direction.
I've got a XamDataGrid with a datasource of a standard .net DataTable.
The XamDataGrid has AutoGenerateFields set to true (since I won't know all the columns until runtime and the number of columns will change over time) and the following *design-time* field layout defined:
<igDP:XamDataGrid.FieldLayouts> <igDP:FieldLayout IsDefault="True"> <igDP:Field Name="First Name"> <igDP:Field.Settings> <igDP:FieldSettings CellClickAction="SelectRecord" AllowEdit="False" /> </igDP:Field.Settings> </igDP:Field> <igDP:Field Name="Last Name"> <igDP:Field.Settings> <igDP:FieldSettings CellClickAction="SelectRecord" AllowEdit="False" /> </igDP:Field.Settings> </igDP:Field> <igDP:Field Name="User" Visibility="Collapsed"> </igDP:Field> </igDP:FieldLayout> </igDP:XamDataGrid.FieldLayouts>
The first time I generate my datasource DataTable, everything looks great. However, when I then add or remove a column in my DataTable, the XamDataGrid creates a new FieldLayout (which I've read is the expected behavior because the AutoGenerateFields property is set to true). When this new Field Layout is created, however, it does not maintain any of the settings I originally set above in design-time, i.e. my User column is visible (which I don't want) and my two name columns can be edited (which they should not).
I've read on these forums that I can hook into the AssigningFieldLayoutToItem event and use the EventArgs Item property to get the dataitem being assigned to the item and then generate my own FieldLayout but I'm extending the XamDataGrid and this extended class may not always be bound to a DataTable so I don't want to write logic assuming that the Item Property always points to a DataRowView.
Ideally, I'd like to just use the original FieldLayout that works the first time and add/remove fields in the FieldLayoutInitialized event to this original FieldLayout and then use this original FieldLayout in the AssigningFieldLayoutToItem.
This "appears" to work the first time but on consecutive changes to the DataTable the FieldLayoutInitialized event fails to fire and I'm unable to modify the original FieldLayout as desired.
I've attached two screen shots to show the first time I load data into the grid and what happens when I modify the DataTable and a new FieldLayout is generated.
I also thought about moving the original design-time fields into the new FieldLayout collection but you can't move Fields from one collection to another and I also don't think it's good design to "copy" all the original Field values and settings to the new Fields generated in the new layout but I guess I can go that route if there's no other solutions.
Ben -
1) I worked on this code over 3 years ago. Anything I share may be outdated or no longer compatible with latest XamDataGrid.
2) Although I didn't want to, the only solution I found that consistently worked was to make deep copies of all the fields in the original field layout and copy them into a new field layout.
3) This code may not be efficient or optimized. Use at your own risk. I'm sharing it to give you an idea of what I did to get things to "work".
Because I wanted a bindable XamDataGrid (I was using Caliburn Micro and wanted two-way data binding), I extended XamDataGrid. I then created a MaintainDefaultFieldLayout XAML property. Finally, I overrode OnFieldLayoutInitializing.
Attached is the code for BindableXamDataGrid (note other methods used to help two-way data bind data, note I also think there was an issue with Tooltips which explains some of the other Tooltip override logic). You will need to add in the correct using statements and there may be some "application" specific code from my app that you will need to remove because it won't exist in your app and you won't have the projects or DLLs.
To use it in XAML, just define the grid as a normal XamDataGrid but set the MaintainDefaultFieldLayout to true and define the FieldLayouts property:
<local:BindableXamDataGrid x:Name="TestUsersGrid" Theme="Office2k7Black" Grid.Row="1" Grid.Column="2" Grid.RowSpan="3" MinWidth="250" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MaintainDefaultFieldLayout="True" DataSource="{Binding RoleUsersMatrix}" SelectedRecordsDataItems="{Binding SelectedAssignedUsers}" UseFieldLabelsForToolTips="True">
Also, in the BindableXamDataGrid, I use an extension method CloneWithNetDataSerializer. Here is that definiton which creates a clone of an object using the built-in .Net Data Serializer to ensure the "copied" LayoutFields exactly match the properties of the fields defined in XAML:
/// <summary> /// Perform a deep Copy of the object using standard serialization. Object being /// cloned must be ISerializable /// </summary> /// <typeparam name="T">The type of object being copied.</typeparam> /// <param name="source">The object instance to copy.</param> /// <returns>The copied object.</returns> public static T CloneWithNetDataSerializer<T>(this T source) { // Don't serialize a null object, simply return the default for that object if (Object.ReferenceEquals(source, null)) { return default(T); }
string obj = CloneExtensions.NetDataSerializeObject<T>(source);
if (Object.ReferenceEquals(obj, null)) return default(T); else return CloneExtensions.NetDataDeserializeObject<T>(obj); }
Hope this helps,
Nate
Hi,
I'm having the same problem and the sample solution doesn't work for me. I have a xamdatagrid whose underlying datasource type changes dynamically at run time. The fields will change but I need to keep the same FieldLayout (they are in the same hierarchy and I need to hide some common fields that would be of no interest to the user.) I have a fieldlayout set as per the sample project but this is unfortunately only used the first time the grid is rendered and never again. I need to apply the FieldLayout every time the grid renders, but am struggling. Any help would be greatly appreciated!
Thanks,
Ben
Hello ,
It has been a while since you have made your post, in case you still need support I will be glad to assist you further. I suppose the other community members can benefit from this answer as well. I have been looking through your post, but I wasn’t able to reproduce your behavior, so I created a sample project for you. If my it doesn’t satisfies all your needs feel free to modify it, so it reproduces your behavior and send it back to me for further investigation.
Feel free to write me if you have further questions.