【问题标题】:Exception when trying to sort DataGrid Column尝试对 DataGrid 列进行排序时出现异常
【发布时间】:2017-03-05 00:23:10
【问题描述】:

注意:修正了 SummeryName 的错字以避免混淆。

我正在尝试将一个简单的 DataGrid 绑定到可按列排序的 ObservableCollection。这是一个简单的设置:

<DataGrid ItemsSource="{Binding Path=DocuObjects}" CanUserSortColumns="True" SelectedItem="{Binding Path=SelectedDocu}" AutoGenerateColumns="false">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Name" SortMemberPath="SummaryName" Width="*" Binding="{Binding SummaryName}" />
    </DataGrid.Columns>
</DataGrid>

绑定源是一个简单的集合:

public ObservableCollection<DocuObject> DocuObjects
{
    get { return m_Docus; }
    set
    {
        m_Docus= value;
        RaisePropertyChanged("DocuObjects");                
    }               
}

每次单击列标题时,都会出现异常:

System.Windows.Data 错误:55:无法按“SummaryName”排序 InvalidOperationException:'System.InvalidOperationException: 失败 比较数组中的两个元素。 ---> System.ArgumentException:在 至少一个对象必须实现 IComparable。

很明显,下一步我将在 DocuObject 类中实现 IComparable,正如异常所暗示的那样。但这似乎没有任何作用,无论我添加 IComparable 还是 IComparable。异常仍然发生,当我添加断点时,我的 CompareTo() 代码没有受到影响。

出于测试目的,我已将代码简化为 this - 但 NotImplementedException 甚至没有受到影响。

public class DocuObject: INotifyPropertyChanged, IEquatable<DocuObject>, IComparable<DocuObject>
{
...
    public int CompareTo(DocuObject other)
    {
        throw new NotImplementedException();
    }
}

我犯了什么根本性错误? SummaryName 本身是一个字符串,CompareTo 应该在其中工作

【问题讨论】:

  • 显示DocuObject的结构
  • 我刚做了。但是没什么可看的:-/
  • 请提供有关 DocuObject 类的更多信息。 SummeryName 是什么类型的?这是 SummaryName 的错字吗?
  • 请出示DocuObject的代码
  • SummaryName 不是字符串对象。 (不再 - 它曾经是一个。)所以听起来我需要在该自定义类上实现 IComparable 。会这样做并报告。

标签: c# wpf datagrid


【解决方案1】:

MSDN 文档解释了如何允许将列用于排序: https://msdn.microsoft.com/en-us/library/system.windows.controls.datagrid.canusersortcolumns(v=vs.110).aspx

您可以通过设置 DataGridColumn.CanUserSort 属性为各个列设置此排序行为。

该属性实际上是否称为SummeryName?我将继续假设不是错字。您需要为特定的文本列同时设置SortMemberPath="SummeryName"CanUserSort="True"

除非您的名字让人想起夏天,否则您可能希望将属性从 SummeryName 更改为 SummaryName

我还假设SummeryName 是一个字符串,但如果不是,那么它必须实现 IComparable 才能进行排序。

【讨论】:

  • 根据 CanUserSortColumns 的文档:“获取或设置一个值,该值指示用户是否可以通过单击列标题对列进行排序。”所以我设置它和 SortMemberPath 来指示要排序的值(理论上)。当我再次删除它时,会发生同样的事情:期望触发并且我的 CompareTo 代码没有被命中。
  • 啊,我明白了。给我一点时间看看我之前是如何实现的
  • CanUserSortCanUserSortColumns 似乎默认为 True,顺便说一句。当我删除该属性时,我仍然会得到点击行为和异常。只有当我明确地将其设置为 false 时,事情才会停止“工作”。
  • 您能否提供有关 DocuObject 和 SummeryName 的更多信息?
【解决方案2】:

SummeryName 属性后面的类型需要实现IComparable,而不是DocuObject 类型。毕竟你设置了SortMemberPath="SummeryName"

【讨论】:

    【解决方案3】:

    但这似乎没有任何作用,无论我添加 IComparable 还是 IComparable。

    由于您使用SortMemberPath="SummeryName",这意味着SummeryName 应该实现IComparable(而不是IComparable)。如果是字符串,请检查拼写错误。如果是自定义类,DataGrid 在里面调用CompareTo

    public class CustomClass : IComparable
    {  
        public int CompareTo(object obj)
        {
            //...
        }
    }
    

    【讨论】:

      【解决方案4】:

      问题不在于 DocuObject 上缺少 IComparable...问题在于您用于 SummeryName 的任何对象上都缺少 IComparable。如果您对 SummeryName 使用字符串,则排序将正常工作。这是因为字符串实现了 IComparable。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-18
        • 1970-01-01
        • 2021-12-17
        • 1970-01-01
        相关资源
        最近更新 更多