Drakestar
Drakestar

Reputation: 748

Exception when trying to sort DataGrid Column

Note: Fixed the SummeryName typo to avoid confusion.

I'm trying to make a simple DataGrid bound to an ObservableCollection sortable by column. It's a simple setup:

<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>

The binding source is a simple collection:

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

Every time I click on the column header, I get an exception:

System.Windows.Data Error: 55 : Cannot sort by 'SummaryName' InvalidOperationException:'System.InvalidOperationException: Failed to compare two elements in the array. ---> System.ArgumentException: At least one object must implement IComparable.

So obviously the next step I'm taking it to implement IComparable in the DocuObject class, as the exception suggests. But that doesn't seem to do anything, regardless of whether I add IComparable or IComparable. The exception still occurs, and my CompareTo() code doesn't get hit when I add a breakpoint.

For test purposes, I've simplified my code down to this - but that NotImplementedException is not even getting hit.

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

What fundamental error am I making? SummaryName itself is a string, where CompareTo should work

Upvotes: 0

Views: 1665

Answers (4)

Max Weinzierl
Max Weinzierl

Reputation: 1261

The MSDN documentation explains how you can allow columns to be used for sorting: https://msdn.microsoft.com/en-us/library/system.windows.controls.datagrid.canusersortcolumns(v=vs.110).aspx

You can set this sorting behavior for individual columns by setting the DataGridColumn.CanUserSort property.

Is the property actually called SummeryName? I will continue under the assumption that is not a typo. You need to set both SortMemberPath="SummeryName" and CanUserSort="True" for the specific text column.

Unless your names are evocative of summer you might want to change the property from SummeryName to SummaryName

Also I am assuming SummeryName is a string, but if it is not then it must implement IComparable to be sorted.

Upvotes: 2

AQuirky
AQuirky

Reputation: 5236

The problem is not missing IComparable on the DocuObject...the problem is the missing IComparable on whatever object you are using for SummeryName. If you use string for SummeryName the sorting will work fine. This is because string implements IComparable.

Upvotes: 1

rmojab63
rmojab63

Reputation: 3631

But that doesn't seem to do anything, regardless of whether I add IComparable or IComparable.

Since you use SortMemberPath="SummeryName", it means that SummeryName should implement IComparable (and not IComparable). If it is a string, check for typos. If it is a custom class, DataGrid calls CompareTo in it:

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

Upvotes: 1

grek40
grek40

Reputation: 13438

The type behind the SummeryName property needs to implement IComparable, not the DocuObject type. You set SortMemberPath="SummeryName" after all.

Upvotes: 1

Related Questions