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

gra*_*ant 6 c# vb.net sorting wpf listview

我有一个ListView(GridView),我想按2列排序,所以如果2列中的2个项目具有相同的值,则按列2排序.非常简单.但排序AZ时,空字符串会显示在顶部.我想把它们移到最底层.我做了一个比较器(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
Run Code Online (Sandbox Code Playgroud)

问题是我的比较器被赋予了我的类的类型,而不是被排序的属性/列的值.因此,如果该类是Foo并且我按Foo.Bar排序,那么我得到整个Foo类,而不仅仅是Bar的值(实际上它应该关注它,因为它就是它的排序).

我的比较器将如何知道要比较哪个属性?也许我在这里做错了,因为这没有任何意义.我期望获得x和y的String(属性类型)...

有谁知道如何做到这一点?

Jos*_*ose 7

您的IComparer实现将被赋予整个对象,您需要确定单击哪个列,可能通过执行以下操作:

this.AddHandler(GridViewColumnHeader.ClickEvent, 
                new RoutedEventHandler(Column_Sort));
Run Code Online (Sandbox Code Playgroud)

然后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;
}
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

编辑: 您只需要自定义您IComparer的支持多列排序,我google搜索并找到这个比较器实现,您可以为它提供几个以逗号分隔的属性路径,并以ASC/DESC为后缀,如下所示:

User.LastName DESC, User.FirstName DESC
Run Code Online (Sandbox Code Playgroud)

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