DataGrid DisplayIndex Binding Problem

Apr 15, 2009 at 8:47 AM
Edited Apr 15, 2009 at 8:52 AM
I am trying to save user settings into our database. These user settings are made for special views in our application. I made a Settings class and a SettingItem class to be able to use an ObjectDataProvider to bind the DatagridColumns to these values. Loading and saving default values (without any changes to the default DisplayIndex) works very fine, but when a user changes the DisplayIndex of a column by reordering columns and the settings are saved, the next time I am trying to load the settings I am getting the error, that the DisplayIndex is already used.
I am not sure if this is  the bug reproted here:
Or if it is my implementation. For better understanding what I am doing, here is some code:
We have got two similar DataGrids, defining 33 columns. Only the ItemsSource is different.



TK:DataGrid Name="_buchungGrid" ItemsSource="{Binding SortedSet}"
AutoGenerateColumns="False" CanUserAddRows="False"
HeadersVisibility="All" CanUserSortColumns="True" 
RowDetailsTemplate="{StaticResource RowDetailsTemplate}"
    SelectionMode="Extended" RowStyle="{StaticResource Rowstyle}"
ColumnHeaderStyle="{StaticResource ColumnHeaderStyle}"
Sorting="_buchungGrid_Sorting" Visibility="Visible">



<TK:DataGridTemplateColumn Header="" IsReadOnly="False"
    Width="{Binding Source={StaticResource Settings}, Path=SplitInGrid.Width, Mode=TwoWay}"
    Visibility="{Binding Source={StaticResource Settings}, Path=SplitInGrid.Visible}"
DisplayIndex="{Binding Source={StaticResource Settings}, Path=SplitInGrid.DisplayIndex, Mode=TwoWay}">
<Button Content="+" Width="16" Height="16"
Visibility="{Binding HasSplitbuchungen}"

<TK:DataGridTextColumn Header="Wertstellung" IsReadOnly="True" 
Width="{Binding Source={StaticResource Settings}, Path=Wertstellung.Width, Mode=TwoWay}"
Binding="{Binding Valuta, Converter={StaticResource DateToFormatedStringConverter},ConverterParameter=true}"
Visibility="{Binding Source={StaticResource Settings}, Path=Wertstellung.Visible}"
DisplayIndex="{Binding Source={StaticResource Settings}, Path=Wertstellung.DisplayIndex, Mode=TwoWay}"/>


<TK:DataGridTextColumn Header="Empf„nger/Auftraggeber" IsReadOnly="True" 
Width="{Binding Source={StaticResource Settings}, Path=Empfaenger.Width, Mode=TwoWay}"
Binding="{Binding Empfaenger}"
Visibility="{Binding Source={StaticResource Settings}, Path=Empfaenger.Visible}"
DisplayIndex="{Binding Source={StaticResource Settings}, Path=Empfaenger.DisplayIndex, Mode=TwoWay}"/>

The ObjectDataProvider holds the instance of my Settings class (It's a singleton). Width, Visibility and DisplayIndex are bound to the Properties of the Settings class, which are instances of my class SettingItem.
I am mapping the Settings from a Database Object (e) to my Settings like this:



[] sort = e.Sortierung.Split(',');
settings.Sorting =
new KeyValuePair<int, int>(Int32.Parse(sort[0]), Int32.Parse(sort[1]));  



string[] felder = e.Felder.Split(',');
string[] feldbreiten = e.Feldbreite.Split(',');
string[] feldreihenfolge = e.Feldreihenfolge.Split(','); 


settings.SplitInGrid =

new SettingItem("SplitInGrid", "HasSplitbuchungen", 0,
Int32.Parse(felder[0]), Int32.Parse(feldreihenfolge[0]), Int32.Parse(feldbreiten[0]));
settings.Wertstellung =
new SettingItem("Wertstellung", "Valuta", 1,
Int32.Parse(felder[1]), Int32.Parse(feldreihenfolge[1]), Int32.Parse(feldbreiten[1]));
settings.Empfaenger =
new SettingItem("Empf„nger/Auftraggeber", "Empfaenger", 2,
Int32.Parse(felder[2]), Int32.Parse(feldreihenfolge[2]), Int32.Parse(feldbreiten[2]));

This is how the displayIndex is saved into the database (exactly the case when I am getting errors):



Now the big Problem is, that this mapping is called several times when the application gets initialised (because we are using prism and a ViewModel which at first gets initialised with an empty model and then with the Model). The first time this mapping is called everything is working fine. But the second time it is not working any longer. When the mapping is called the first time the default settings are applied. When it is called the second time the settings the user made are applied. But at this point the DataGrid is already initialized and the Columns are bound to the values in the single SettingItems. When I am trying to set the DisplayIndex again the application crashes and tells me that the DisplayIndex is already used for another column.
Another strange behaviour: The second DataGrid mentioned above is bound to these values too. When the user is reordering the columns the two Grids doo not behave in the same way... Sometimes the upper grid gets reordered and the other one not or the columns are not put in the same sequence...
I wanted to solve this with simple DataBinding as you can see... It would be great if someone can have a look at my problem, because I really don't know how to solve this problem alone. I tried several things but everything ended up causing more errors..
Thanks in advance!



May 19, 2009 at 11:30 PM

I believe the problem you're hitting is that DataGrid’s DisplayIndex conflict resolution mechanism only works after the first Measure pass happens.  In your application, it appears that the DisplayIndexes contain a conflict and since they are being set before the Measure pass happens, DataGrid does not know how to handle the conflict.  You have a few options to work around this:


1.       Make sure that whenever the DisplayIndexes do not contain any conflicts before you set them,

2.       OR, make sure that the DisplayIndexes aren’t set until after DataGrid’s Measure pass happens (and it doesn’t matter if there are conflicts because DataGrid should be able to handle them at this point)


We agree that this is a bug and should be fixed in a future release, and we’ve filed a bug to track this internally.