Tar*_*aal 8 c# sorting wpf datagrid
我有一个WPF DataGrid,我已经得到它,以便您可以通过单击列标题对其进行排序.它有效,但它不稳定.如何让它做稳定的排序?
我的意思是,如果我有这张桌子:
Class | Student | Grade
-----------------------------
Art | James | A
Art | Amy | B
Art | Charlie | A
Science | James | D
Science | Amy | A
Science | Charlie | C
History | James | B
History | Amy | A
History | Charlie | C
Run Code Online (Sandbox Code Playgroud)
如果我按学生排序,它会像你期望的那样工作:
Class | Student | Grade
-----------------------------
Art | Amy | B
Science | Amy | A
History | Amy | A
Art | Charlie | A
Science | Charlie | C
History | Charlie | C
Art | James | A
Science | James | D
History | James | B
Run Code Online (Sandbox Code Playgroud)
但是,如果我现在按类排序:
Class | Student | Grade
-----------------------------
Art | James | A
Art | Amy | B
Art | Charlie | A
History | James | B
History | Amy | A
History | Charlie | C
Science | James | D
Science | Amy | A
Science | Charlie | C
Run Code Online (Sandbox Code Playgroud)
它破坏了学生的排序(不稳定排序).我想要的是稳定排序,它保留了订单:
Class | Student | Grade
-----------------------------
Art | Amy | B
Art | Charlie | A
Art | James | A
History | Amy | A
History | Charlie | C
History | James | B
Science | Amy | A
Science | Charlie | C
Science | James | D
Run Code Online (Sandbox Code Playgroud)
似乎默认情况下应该像这样工作,或者至少是切换.有没有人有什么建议?@ Eirik关于shift-click工作的想法,这表明行为存在.但是,我真正喜欢的是在没有任何修改器的情况下工作.它不应该是"按此排序,然后是这个,然后是这个"的原因,它应该是将算法交换为另一个算法的情况.
请参阅:http://en.wikipedia.org/wiki/Sorting_algorithm#Stability
您可以通过在单击列时按住shift来按多列排序.尝试单击类列,然后按住shift并单击学生列.
这是一个在代码中添加排序的解决方案:
private void myDataGridPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
DependencyObject dep = (DependencyObject)e.OriginalSource;
while ((dep != null) && !(dep is DataGridColumnHeader))
{
dep = VisualTreeHelper.GetParent(dep);
}
if (dep == null)
return;
if (dep is DataGridColumnHeader)
{
DataGridColumnHeader columnHeader = dep as DataGridColumnHeader;
ICollectionView view = CollectionViewSource.GetDefaultView((sender as DataGrid).ItemsSource);
if (columnHeader.Content.Equals("Class") || columnHeader.Content.Equals("Student"))
{
view.SortDescriptions.Clear();
view.SortDescriptions.Add(new SortDescription("Class", ListSortDirection.Ascending));
view.SortDescriptions.Add(new SortDescription("Student", ListSortDirection.Ascending));
}
}
}
Run Code Online (Sandbox Code Playgroud)
为此,您必须禁用标准排序.一种方法是停止Sorting事件,如下所示:
private void myDataGridSorting(object sender, DataGridSortingEventArgs e)
{
e.Handled = true;
}
Run Code Online (Sandbox Code Playgroud)
编辑:在阅读hbarck的评论后,我再次阅读了你的问题,似乎我错过了一些部分.如果您更改此代码:
if (columnHeader.Content.Equals("Class") || columnHeader.Content.Equals("Student"))
{
view.SortDescriptions.Clear();
view.SortDescriptions.Add(new SortDescription("Class", ListSortDirection.Ascending));
view.SortDescriptions.Add(new SortDescription("Student", ListSortDirection.Ascending));
}
Run Code Online (Sandbox Code Playgroud)
对此:
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
{
view.SortDescriptions.Clear();
}
view.SortDescriptions.Insert(0, new SortDescription(columnHeader.Content.ToString(), ListSortDirection.Ascending));
Run Code Online (Sandbox Code Playgroud)
你将有稳定的排序.单击学生按学生排序,然后单击班级按班级排序,学生.如果在单击时按住ctrl,则在按照单击的列排序之前清除先前的排序.
我已经设法使用自定义比较器获得稳定的排序,但这有点像一个大黑客......
我使用 ListCollectionView 的 CustomSort 属性来设置我的自定义比较器,这需要我在实例化它时将集合传递给它。
private void Sorting(IEnumerable collection)
{
var view = CollectionViewSource.GetDefaultView(collection) as ListCollectionView;
if (view != null)
{
view.CustomSort = new StableComparer(collection);
}
}
Run Code Online (Sandbox Code Playgroud)
在我的自定义比较器中,我在 Compare 方法期间使用集合,只是为了在常规比较返回零(它们相同或具有相同值)时回退到项目索引。
public class StableComparer : IComparer
{
public IEnumerable Collection { get; set; }
public StableComparer(IEnumerable collection)
{
Collection = collection;
}
public int Compare(object x, object y)
{
IComparable x_Comparable = x as IComparable;
IComparable y_Comparable = y as IComparable;
if (x_Comparable != null && y_Comparable != null)
{
var comparison = x_Comparable.CompareTo(y_Comparable);
// A zero value means x and y are equivalent for sorting, and they could
// be rearranged by an unstable sorting algorithm
if (comparison == 0 && Collection != null)
{
// IndexOf is an extension method for IEnumerable (not included)
var x_Index = Collection.IndexOf(x);
var y_Index = Collection.IndexOf(y);
// By comparing their indexes in the original collection, we get to
// preserve their relative order
if (x_Index != -1 && y_Index != -1)
comparison = x_Index.CompareTo(y_Index);
}
return comparison;
}
return 0;
}
}
Run Code Online (Sandbox Code Playgroud)
我仍在测试这一点,所以我不能保证这会一直有效...例如,一个问题是保持比较器内的 Collection 属性更新。或者支持两种排序方向(现在就开始工作,应该不难)。或者检查它是如何工作的,性能方面的。
但我认为这个想法很明确;虽然很老套,就像我说的。
| 归档时间: |
|
| 查看次数: |
1551 次 |
| 最近记录: |