WPF DataGrid MultiColumn sort without shift key
The WPF DataGrid has a default behavior of allowing multicolumn sorts when the user shift-clicks on multiple column headers. Is there a way to change this behavior so that the Shift key is not required? I have already handled the sorting event on the datagrid so that each column will cycle between the three sorting states (Ascending, Descending, and No Sort) and this is all working as expected as long as the shift key is held down, but I would like to make it so that the DataGrid does not reset the sorting on all other columns if开发者_JAVA百科 the user clicks a column header to add a sort without pressing shift.
I have found a solution that seems to be a bit of a hack, but it works. This article got me pointed in the right direction: http://blogs.msdn.com/b/vinsibal/archive/2008/08/29/wpf-datagrid-tri-state-sorting-sample.aspx?PageIndex=2. That brought me to the understanding the the SortDirection of each column is not really tied to the ItemsSource SortDescriptions in any way. So what I did was subscribe to the Sorting event of the Datagrid and reset the SortDirection of each column that is referenced in the ItemsSource SortDescriptions collection. Apparently, not pressing shift clears the sortdirection of each column, but doesn't reset the SortDescriptions.
I was dealing with the same problem, but no one showed the code that can solve this it. The question is old, but I hope the solution will be useful for seekers.
(DataGrid.Items.SortDescriptions as INotifyCollectionChanged).CollectionChanged += OnGridCollectionChanged;
private void OnGridCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
{
var sortingCollection = (SortDescriptionCollection)sender;
foreach (var sortDesc in sortingCollection)
{
foreach (var column in SignaturesInImagingGrid.Columns)
{
if (column.SortMemberPath.Equals(sortDesc.PropertyName))
{
column.SortDirection = sortDesc.Direction;
}
}
}
}
<DataGrid Sorting="GridMultiColumnSortingEvent">
public static void GridMultiColumnSortingEvent(object sender, DataGridSortingEventArgs e)
{
var dgSender = (DataGrid)sender;
var cView = CollectionViewSource.GetDefaultView(dgSender.ItemsSource);
ListSortDirection direction = ListSortDirection.Ascending;
if (ContainsSortColumn((DataGrid)sender, e.Column.SortMemberPath))
{
if (e.Column.SortDirection == null)
{
direction = ListSortDirection.Ascending;
ChangeSortColumn((DataGrid)sender, e.Column, direction);
}
else if (DirectionForColumn(cView, e.Column) == ListSortDirection.Ascending)
{
direction = ListSortDirection.Descending;
ChangeSortColumn((DataGrid)sender, e.Column, direction);
}
else if (DirectionForColumn(cView, e.Column) == ListSortDirection.Descending)
{
e.Column.SortDirection = null;
cView.SortDescriptions.Remove(cView.SortDescriptions.Where(item => item.PropertyName.Equals(e.Column.SortMemberPath)).FirstOrDefault());
cView.Refresh();
}
}
else
{
AddSortColumn((DataGrid)sender, e.Column.SortMemberPath, direction);
cView.Refresh();
}
e.Handled = true;
}
private static ListSortDirection DirectionForColumn(ICollectionView cView, DataGridColumn column) =>
cView.SortDescriptions.Where(item => item.PropertyName.Equals(column.SortMemberPath))
.FirstOrDefault()
.Direction;
private static void AddSortColumn(DataGrid sender, string sortColumn, ListSortDirection direction)
{
var cView = CollectionViewSource.GetDefaultView(sender.ItemsSource);
cView.SortDescriptions.Add(new SortDescription(sortColumn, direction));
foreach (var col in sender.Columns.Where(x => x.SortMemberPath == sortColumn))
{
col.SortDirection = direction;
}
}
private static void ChangeSortColumn(DataGrid sender, DataGridColumn column, ListSortDirection direction)
{
var cView = CollectionViewSource.GetDefaultView(sender.ItemsSource);
string sortColumn = column.SortMemberPath;
foreach (var sortDesc in cView.SortDescriptions.ToList())
{
if (sortDesc.PropertyName.Equals(sortColumn))
{
cView.SortDescriptions.Remove(sortDesc);
break;
}
}
AddSortColumn(sender, sortColumn, direction);
}
private static bool ContainsSortColumn(DataGrid sender, string sortColumn)
{
var cView = CollectionViewSource.GetDefaultView(sender.ItemsSource);
foreach (var sortDesc in cView.SortDescriptions.ToList())
{
if (sortDesc.PropertyName.Equals(sortColumn))
return true;
}
return false;
}
精彩评论