locked
sort list box observable collection RRS feed

  • Question

  • hi,

    my listbox itemsource is "sourceList" - which is MultiSelectCollectionView<string>

    i want my list box to be sorted using sort description.but we need to add property with the sort description like below

     

    <CollectionViewSource.SortDescriptions>

    <scm:SortDescriptionPropertyName="PropertName"/>

    </CollectionViewSource.SortDescriptions>

    but there is no such property exist in my item source as my item source itself is property.

    so how to sort my list box using sort descrion in xaml it self

    Friday, January 3, 2014 10:29 AM

Answers

  • You need to bind the ItemsSource property of the ListBox to a CollectionViewSource and add the SortDescriptions to this CollectionViewSource object.

    I don't know what a MultiSelectCollectionView is, but if it is a class that inherits from the ListCollectionView class, you can add the SortDescriptions to it directly:

    SourceUserList.SortDescriptions.Add(new System.ComponentModel.SortDescription("", System.ComponentModel.ListSortDirection.Descending));

    If you for some reason want to to do this in XAML, you could create a class that inherits from the generic one and define a resource of this type in your window:

    public class MultiSelectCollectionViewString : MultiSelectCollectionView<string>
        {
            public MultiSelectCollectionViewString(List<string> list)
                : base(list) { }
    
            public MultiSelectCollectionViewString()
                : base(new List<string>()) { }
        }
    

    public MainWindow()
            {
                InitializeComponent();
    
                MultiSelectCollectionViewString items = this.Resources["sourceList"] as MultiSelectCollectionViewString;
                for (int i = 0; i < 10; ++i)
                {
                    items.AddNewItem(i.ToString());
                }
            }
    

    <Window.Resources>
            <local:MultiSelectCollectionViewString x:Key="sourceList">
                <local:MultiSelectCollectionViewString.SortDescriptions>
                    <scm:SortDescription PropertyName="" Direction="Descending"/>
                </local:MultiSelectCollectionViewString.SortDescriptions>
            </local:MultiSelectCollectionViewString>
        </Window.Resources>
    

    <ListBox x:Name="sourceUserList"  ItemsSource="{Binding Source={StaticResource sourceList}}, ...

    Friday, January 3, 2014 12:00 PM
  • Hi,

    You can just implement a Custom Sort.

    Window x:Class="WpfApplication9.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
            Title="MainWindow" x:Name="MyWindow" Height="350" Width="525">
        <Window.Resources>
            <CollectionViewSource x:Key="cvs">           
            </CollectionViewSource>
    
        </Window.Resources>
        <Grid>
            <DataGrid x:Name="dgGrid" EnableRowVirtualization="True" AutoGenerateColumns="False" ItemsSource="{Binding Source={StaticResource cvs}}">          
                <DataGrid.Columns>
                    <DataGridTemplateColumn Header="Names">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding}" />
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>                    
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
    </Window>


    Code Behind 

    public partial class MainWindow : Window
        {
          
           public MainWindow()
            {
                InitializeComponent();            
                this.Loaded += MainWindow_Loaded;
            }
    
            void MainWindow_Loaded(object sender, RoutedEventArgs e)
            {
                var stringList = new List<string> { "Ball", "Apple", "Cat", "Elephant", "Dog" };
                var multiSelectCollectionView = new MultiSelectCollectionView<string>(stringList);
                dgGrid.ItemsSource = multiSelectCollectionView;
                MultiSelectCollectionView<string> mscv = CollectionViewSource.GetDefaultView(dgGrid.ItemsSource) as MultiSelectCollectionView<string>;
                if (mscv != null)
                {
                    mscv.CustomSort = new CustomStringSort();
                }           
            }
        }
    
        public class CustomStringSort : IComparer
        {
            int IComparer.Compare(object x, object y)
            {
                return ((new CaseInsensitiveComparer()).Compare(x, y));
            }
        }

    Output:


    srithar

    Friday, January 3, 2014 12:14 PM

All replies

  • Hi,

    Since you are using collection of string. You can directly use the below code for sorting.

    <Window x:Class="ListBoxSort_Learning.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <CollectionViewSource x:Key="SortedItems">
                <CollectionViewSource.SortDescriptions>
                    <scm:SortDescription Direction="Ascending"/>
                </CollectionViewSource.SortDescriptions>
            </CollectionViewSource>
        </Window.Resources>
        <Grid>
            <ListBox ItemsSource="{Binding Source={StaticResource SortedItems}}"/>
        </Grid>
    </Window>

    public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                CollectionViewSource cvs = FindResource("SortedItems") as CollectionViewSource;
                ObservableCollection<string> lst = new ObservableCollection<string>();
                lst.Add("test");
                lst.Add("Abs");
                cvs.Source = lst;
            }
        }


    Let me know if need more info
    Friday, January 3, 2014 11:02 AM
  • Just omit the PropertyName attribute or specify an empty string:

    <CollectionViewSource.SortDescriptions>
                    <scm:SortDescription PropertyName="" Direction="Descending"/>
    </CollectionViewSource.SortDescriptions> 

    Friday, January 3, 2014 11:23 AM

  • Thanks for reply !!!

    i have tried followings

    <ListBox x:Name="sourceUserList"  ItemsSource="{Binding SourceUserList , ValidatesOnDataErrors=True}" Validation.ErrorTemplate="{StaticResource validationTemplate}" >

                    <CollectionViewSource >               
                        <CollectionViewSource.SortDescriptions>
                            <scm:SortDescription Direction="Ascending" PropertyName=""/>           
                     </CollectionViewSource.SortDescriptions>
                    </CollectionViewSource>

      </ListBox>

    not able to sort list box contain

    run time my list box contain System.Windows.Data.CollectionView  as value

    Friday, January 3, 2014 11:49 AM
  • Hi

    What is type of SourceUserList?

    Can you post the code?

    Friday, January 3, 2014 11:54 AM
  • You need to bind the ItemsSource property of the ListBox to a CollectionViewSource and add the SortDescriptions to this CollectionViewSource object.

    I don't know what a MultiSelectCollectionView is, but if it is a class that inherits from the ListCollectionView class, you can add the SortDescriptions to it directly:

    SourceUserList.SortDescriptions.Add(new System.ComponentModel.SortDescription("", System.ComponentModel.ListSortDirection.Descending));

    If you for some reason want to to do this in XAML, you could create a class that inherits from the generic one and define a resource of this type in your window:

    public class MultiSelectCollectionViewString : MultiSelectCollectionView<string>
        {
            public MultiSelectCollectionViewString(List<string> list)
                : base(list) { }
    
            public MultiSelectCollectionViewString()
                : base(new List<string>()) { }
        }
    

    public MainWindow()
            {
                InitializeComponent();
    
                MultiSelectCollectionViewString items = this.Resources["sourceList"] as MultiSelectCollectionViewString;
                for (int i = 0; i < 10; ++i)
                {
                    items.AddNewItem(i.ToString());
                }
            }
    

    <Window.Resources>
            <local:MultiSelectCollectionViewString x:Key="sourceList">
                <local:MultiSelectCollectionViewString.SortDescriptions>
                    <scm:SortDescription PropertyName="" Direction="Descending"/>
                </local:MultiSelectCollectionViewString.SortDescriptions>
            </local:MultiSelectCollectionViewString>
        </Window.Resources>
    

    <ListBox x:Name="sourceUserList"  ItemsSource="{Binding Source={StaticResource sourceList}}, ...

    Friday, January 3, 2014 12:00 PM
  • Hi,

    You can just implement a Custom Sort.

    Window x:Class="WpfApplication9.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
            Title="MainWindow" x:Name="MyWindow" Height="350" Width="525">
        <Window.Resources>
            <CollectionViewSource x:Key="cvs">           
            </CollectionViewSource>
    
        </Window.Resources>
        <Grid>
            <DataGrid x:Name="dgGrid" EnableRowVirtualization="True" AutoGenerateColumns="False" ItemsSource="{Binding Source={StaticResource cvs}}">          
                <DataGrid.Columns>
                    <DataGridTemplateColumn Header="Names">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding}" />
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>                    
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
    </Window>


    Code Behind 

    public partial class MainWindow : Window
        {
          
           public MainWindow()
            {
                InitializeComponent();            
                this.Loaded += MainWindow_Loaded;
            }
    
            void MainWindow_Loaded(object sender, RoutedEventArgs e)
            {
                var stringList = new List<string> { "Ball", "Apple", "Cat", "Elephant", "Dog" };
                var multiSelectCollectionView = new MultiSelectCollectionView<string>(stringList);
                dgGrid.ItemsSource = multiSelectCollectionView;
                MultiSelectCollectionView<string> mscv = CollectionViewSource.GetDefaultView(dgGrid.ItemsSource) as MultiSelectCollectionView<string>;
                if (mscv != null)
                {
                    mscv.CustomSort = new CustomStringSort();
                }           
            }
        }
    
        public class CustomStringSort : IComparer
        {
            int IComparer.Compare(object x, object y)
            {
                return ((new CaseInsensitiveComparer()).Compare(x, y));
            }
        }

    Output:


    srithar

    Friday, January 3, 2014 12:14 PM