Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting a combobox purely in XAML

Tags:

I'm surprised that no one has asked this before here... well, at least I haven't found an answer here or anywhere else, actually.

I have a ComboBox that is databound to an ObservableCollection. Everything worked great until the guys wanted the contents sorted. No problem -- I end up changing the simple property out:

public ObservableCollection<string> CandyNames { get; set; } // instantiated in constructor 

for something like this:

private ObservableCollection<string> _candy_names; // instantiated in constructor public ObservableCollection<string> CandyNames {     get {         _candy_names = new ObservableCollection<string>(_candy_names.OrderBy( i => i));         return _candy_names;     }     set {         _candy_names = value;     } } 

This post is really two questions in one:

  1. How can I sort a simple ComboBox of strings in XAML only. I have researched this and can only find info about a SortDescription class, and this is the closest implementation I could find, but it wasn't for a ComboBox.
  2. Once I implemented the sorting in code-behind, it my databinding was broken; when I added new items to the ObservableCollection, the ComboBox items didn't update! I don't see how that happened, because I didn't assign a name to my ComboBox and manipulate it directly, which is what typically breaks the binding.

Thanks for your help!

like image 416
Dave Avatar asked Feb 16 '10 17:02

Dave


1 Answers

You can use a CollectionViewSource to do the sorting in XAML, however you need to refresh it's view if the underlying collection changes.

XAML:

<Window x:Class="CBSortTest.Window1"     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"     Height="300" Width="300">      <Window.Resources>         <CollectionViewSource Source="{Binding Path=CandyNames}" x:Key="cvs">             <CollectionViewSource.SortDescriptions>                 <scm:SortDescription />             </CollectionViewSource.SortDescriptions>         </CollectionViewSource>      </Window.Resources>     <StackPanel>         <ComboBox ItemsSource="{Binding Source={StaticResource cvs}}" />         <Button Content="Add" Click="OnAdd" />     </StackPanel> </Window> 

Code behind:

using System; using System.Collections.ObjectModel; using System.Windows; using System.Windows.Data;  namespace CBSortTest {     public partial class Window1 : Window     {         public Window1()         {             InitializeComponent();              CandyNames = new ObservableCollection<string>();              OnAdd(this, null);             OnAdd(this, null);             OnAdd(this, null);             OnAdd(this, null);              DataContext = this;              CandyNames.CollectionChanged +=                  (sender, e) =>                 {                     CollectionViewSource viewSource =                         FindResource("cvs") as CollectionViewSource;                     viewSource.View.Refresh();                 };         }          public ObservableCollection<string> CandyNames { get; set; }          private void OnAdd(object sender, RoutedEventArgs e)         {             CandyNames.Add("Candy " + _random.Next(100));         }          private Random _random = new Random();     } } 
like image 152
Wallstreet Programmer Avatar answered Oct 12 '22 02:10

Wallstreet Programmer