Search code examples
c#wpfsortingitemscontrol

Problem in use of SortDescription in WPF - int and string are not IComparable?


I have a problem in using SortDescription. I've found some thread about the problem, like if you want to sort by a type that doesn't implement IComparable, like a user defined class, but it's not my case.

I have a class, that has two properties: string ID, and int Value. Let's call it Item! And I have a view:

<UserControl> <!-- ... -->
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <Button Click="Button_Click"
                Content="Sort by ID"
                Grid.Row="0"/>
        <Button Click="Button_Click1"
                Content="Sort by Value"
                Grid.Row="1"/>
        <DockPanel Grid.Row="2">
            <ItemsControl x:Name="mItemsControl"
                          ItemsSource="{Binding Items}"><!-- The type of Items is ObservableCollection<Item> -->
                <!-- ... -->
            </ItemsControl>
        </DockPanel>
    </Grid>
</GroupBox>

EventHandlers are like these:

private void Button_Click(object sender, RoutedEventArgs e)
    {
        mItemsControl.Items.SortDescriptions.Add(new SortDescription("ID", ListSortDirection.Ascending); //Exception here
    }
private void Button_Click1(object sender, RoutedEventArgs e)
    {
        mItemsControl.Items.SortDescriptions.Add(new SortDescription("Value", ListSortDirection.Ascending); //...and here as well
    }

I get InvalidOperationException because it "Failed to compare two elements in the array.", and it is because neither of the elements implement IComparable. And that is, what I can't understand, as I can compare ints, as well as strings.

Thanks for any idea!


Solution

  • This works fine for me so you are doing something wrong in other parts of your code. Compare what you do with below sample.

    XAML:

    <Window x:Class="SortDemo.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
        <StackPanel>
            <Button Click="OnSort" Content="Sort by ID" Tag="ID"/>
            <Button Click="OnSort" Content="Sort by Value" Tag="Value"/>
            <ItemsControl Name="_itemsControl" ItemsSource="{Binding Path=Items}" />
        </StackPanel>
    </Window>
    

    Code behind:

    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows;
    
    namespace SortDemo
    {
        public partial class Window1 : Window
        {
            public Window1()
            {
                InitializeComponent();
    
                Items = new ObservableCollection<Item>();
                Items.Add(new Item() { ID = "AAA", Value = 2 });
                Items.Add(new Item() { ID = "BBB", Value = 1 });
    
                DataContext = this;
            }
    
            public ObservableCollection<Item> Items { get; private set; }
    
            private void OnSort(object sender, RoutedEventArgs e)
            {
                string sortProperty = (sender as FrameworkElement).Tag as string;
                _itemsControl.Items.SortDescriptions.Clear();
                _itemsControl.Items.SortDescriptions.Add(new SortDescription(sortProperty, ListSortDirection.Ascending)); 
            }
        }
    
        public class Item
        {
            public string ID { get; set;}
            public int Value { get; set; }
    
            public override string ToString()
            {
                return ID + " " + Value;
            }
        }
    }