WPF - 按多列排序时使用自定义比较器

时间:2011-04-07 22:20:40

标签: c# wpf vb.net sorting listview

我有一个ListView(GridView),我想按2列排序,所以如果2列中的2个项目具有相同的值,则按列2进行排序。非常简单。但是在排序A-Z时,空字符串显示在顶部。我想将它们移到最底层。我制作了一个比较器(IComparer)来处理这个问题,但我不确定如何使用它。

这是我尝试过的代码:

 Dim view As ListCollectionView = CollectionViewSource.GetDefaultView(myCollection)
 Using view.DeferRefresh
    view.SortDescriptions.Clear()
    view.SortDescriptions.Add(New SortDescription(sortHeader.Header, direction))
    view.SortDescriptions.Add(New SortDescription(otherColumn, direction))
    view.CustomSort = New MyComparer()
 End Using

问题是我的比较器被赋予了我的类的类型,而不是被排序的属性/列的值。因此,如果这个类是Foo而我是按Foo.Bar排序的话,我会得到整个Foo类,而不仅仅是Bar的值(这真的是它应该关注的全部,因为它是什么&它#39;按...排序。

我的比较器如何知道要比较哪个属性?也许我在这里做错了,因为这没有任何意义。我希望得到x和y的字符串(属性类型)

有谁知道怎么做?

1 个答案:

答案 0 :(得分:7)

您的IComparer实现将被赋予整个对象,您需要确定哪个列被点击,可能通过这样做:

this.AddHandler(GridViewColumnHeader.ClickEvent, 
                new RoutedEventHandler(Column_Sort));

然后可能通过修改构造函数将其输入到MyComparer中以获取属性路径。

Column_Sort中,您可以获得类似的属性路径(我在vb上有点生疏,但c#会这样做:

void Column_Sort(object sender, RoutedEventArgs e)
{
  var memberBinding= ((GridViewColumnHeader)e.OriginalSource).Column.DisplayMemberBinding;
  var path = ((Binding)memberBinding).Path.Path;
}

然后将其提供给您的排序逻辑。

Dim view As ListCollectionView = CollectionViewSource.GetDefaultView(myCollection)
 Using view.DeferRefresh
    view.SortDescriptions.Clear()
    view.SortDescriptions.Add(New SortDescription(sortHeader.Header, direction))
    view.SortDescriptions.Add(New SortDescription(otherColumn, direction))
    view.CustomSort = New MyComparer(PropertyPath)
 End Using

修改 您只需要自定义IComparer以支持多列排序,我用Google搜索并找到this comparer implementation,您可以为其提供几个以逗号分隔的属性路径,并以ASC / DESC为后缀,如下所示:

User.LastName DESC, User.FirstName DESC

我认为就UI而言,多列排序的惯例是你需要保持Ctrl按钮。因此,继承ListView类并将其绑定到GridViewColumnHeader单击事件和KeyDown事件,以了解哪些列已连续单击,然后使用IComparer实现将其输入。