Reputation: 66390
After drag and droping some columns within a datagrid, how do I pass the new order in an MVVM fashion to the Viewmodel?
The EventArgs are extremely weird.
DataGrid_Reordered passes a DataGridColumnEventArgs that contains only a single Column. What am I supposed to do with it? How do i know the new order of columns?
Apparently the order of the columns is determined by the DisplayIndex, but how do I know what the old value was and what the new value is and how does this relate to the whole set of the columns?
Many Thanks,
Upvotes: 3
Views: 3793
Reputation: 477
In my page I set up the DataGrid with an event for Loaded
and ColumnDisplayedIndexChanged
. This is important to have both, I'll explain a the bottom.
<DataGrid x:Name="dataGrid"
Loaded="dataGrid_Loaded"
ColumnDisplayIndexChanged="dataGrid_ColumnDisplayIndexChanged"
ItemsSource="{Binding modulecollection,
Source={StaticResource viewmodel}}"/>
Once either event fires I take the sender and cast to DataGrid
. Then access DataGrid.Columns
for all the column objects.
I send this to another function which creates a quick array of the column names from DataGridColumn
class. The array's index is kept in sync with the order of the columns reference elsewhere. You can create whatever you want, keyvaluepair, another class, and utilize whatever object from the DataGridColumn
class you want. Just depends on how it is set up.
string [] displayedColumnOrder;
private void dataGrid_ColumnDisplayIndexChanged( object sender , DataGridColumnEventArgs e )
{
DataGrid _dataGrid = ( DataGrid ) sender;
_getColumnOrder( _dataGrid.Columns );
}
private void dataGrid_Loaded( object sender , RoutedEventArgs e )
{
DataGrid _datagrid = ( DataGrid ) sender;
_getColumnOrder( _datagrid.Columns );
}
void _getColumnOrder( IEnumerable<DataGridColumn> columnCollection )
{
DataGridColumn [] columnArray;
int columnIndexWorking;
displayedColumnOrder = new string [columnCollection.Count() ];
columnArray = columnCollection.ToArray();
foreach( var item_Column in columnCollection )
{
columnIndexWorking = item_Column.DisplayIndex;
displayedColumnOrder [ columnIndexWorking ] = item_Column.Header.ToString();
}
}
OK, you need the event from Loaded
to get a base line. Here my DataGrid
loads from a binding source, so I wont have a baseline of my column order unless I capture it when the grid is loaded.
You need ColumnDisplayedIndexChanged
because you want to track the change of the column order.
One important thing I found, when the user moves the column over a few rows, ColumnDisplayedIndexChanged
fires for each index it is moved over. As you can see below, because one column is moved, the event will fire for each space it is shifted over. Also the Header object for the DataGridColumn
goes null. So if you utilize this approach be careful, you may need to add in some additional handling. Or utilize this to keep track of responding to a change. example: Dont recalculate something in a background thread unless the headervalue is not null.
Original:
A|B|C <- Column Name
0|1|2 <- Column Index
User Changes To:
B|C|A
0|1|2
User Moves a column over and ColumnDisplayedIndexChanged
Event Fires Like This:
1st event:
null | B | C
0 | 1 | 2
2nd event:
B | null | C
0 | 1 | 2
3rd event:
B | C | A
0 | 1 | 2
Upvotes: 2
Reputation: 11805
Nice problem :-) I'm guessing you're after persistence of the column order after a restart of the app.
I'm not much of a fan of grids so I don't have any concrete advice but it sounds to me like you're going to end up with a bunch of properties in your view model (or a new view model) which model the columns and their order.
I guess you'd have to turn off AutoGenerateColumns, define the columns you need in Xaml and use a two way binding on the Header and DisplayIndex property of each column to bind to appropriate values in the VM.
That way you could use an EventToCommand behaviour from MVVM Light, bind it to the ColumnReordering event of the grid and to a RelayCommand in your viewmodel. Since the VM is responsible for holding the order of the columns you'll have it there when the event fires.
HTH
Upvotes: 1