开发者

Sorting ListBox with MVVM code binding

开发者 https://www.devze.com 2023-04-09 03:35 出处:网络
I have a ListBox which happily displays data using a code-behind MVVM object. However, I want to sort the entries and so I thought an intermediate CollectionViewSource might work. But instead the prog

I have a ListBox which happily displays data using a code-behind MVVM object. However, I want to sort the entries and so I thought an intermediate CollectionViewSource might work. But instead the program crashes on startup.

Original xaml extract:

<ListBox SelectedItem="{Binding SelectedCategory}"
    DisplayMemberPath="name"
    ItemsSource="{Binding Categories}"
    Name="CategoriesListBox" />

Code behind extract:

public class ViewModel : INotifyPropertyChanged
    {
        private trainCategory[] _categories;
        private trainCategory _selectedCategory;

        public event PropertyChangedEventHandler PropertyChanged;

        public trainCategory[] Categories
        {
            get { return _categories; }
            set
            {
                if (_categories == value)
                {
          开发者_开发知识库          return;
                }
                _categories = value;
                RaisePropertyChanged("Categories");
            }
        } //etc

Replacement XAML for ListBox:

<ListBox SelectedItem="{Binding SelectedCategory}"
    DisplayMemberPath="name"
    ItemsSource="{Binding Source={StaticResource SortedItems}}"
    Name="CategoriesListBox" />

And the CollectionViewSource:

<CollectionViewSource x:Key="SortedItems" Source="{Binding Categories}">
    <CollectionViewSource.SortDescriptions>
        <scm:SortDescription PropertyName="name"/>
    </CollectionViewSource.SortDescriptions>
</CollectionViewSource>

It seems to me that the CollectionViewSource goes in between the view model and the ListBox, but it clearly doesn't (or I've done it wrong). Any pointers appreciated.


Use your original xaml

<ListBox SelectedItem="{Binding SelectedCategory}" 
    DisplayMemberPath="name" 
    ItemsSource="{Binding Categories}" 
    Name="CategoriesListBox" /> 

Update your View Model to use a List instead:

   public List<trainCategory> _categories;
   public List<trainCategory> Categories 
    { 
        get 
        {   // This LINQ statement returns a sorted list
            return (from c in _categories
                    orderby c
                    select c);
        } 
        set 
        { 
            if (_categories == value) 
            { 
                return; 
            } 
            _categories = value; 
            RaisePropertyChanged("Categories"); 
        } 
    } //etc 

Then you can skip all that nastiness of trying to bind to a static resporce. Just bind strait to the property in your view model.

Alternately, you can still use arrays as your backing variable in your viewmodel:

   public trainCategory[] _categories;
   public List<trainCategory> Categories 
    { 
        get 
        {   // This LINQ statement returns a sorted list
            return (from c in _categories
                    orderby c
                    select c).ToList();
        } 
        set 
        { 
            if (_categories == value.ToArray()) 
            { 
                return; 
            } 
            _categories = value.ToArray();
            RaisePropertyChanged("Categories");
        } 
    } //etc 


What exception are you getting on startup? Remember to have your Resources section before all other code that needs to use the resources.

An alternative to that would be:

<ListBox SelectedItem="{Binding SelectedCategory}" DisplayMemberPath="name" Name="CategoriesListBox">
    <ListBox.ItemsSource>
        <Binding>
            <Binding.Source>
                <CollectionViewSource Source="{Binding Categories}">
                    <CollectionViewSource.SortDescriptions>
                        <scm:SortDescription PropertyName="name"/>
                    </CollectionViewSource.SortDescriptions>
                </CollectionViewSource>
            </Binding.Source>
        </Binding>
    </ListBox.ItemsSource>
</ListBox>

Also remember to have the proper xmlns declaration for scm in any case.

0

精彩评论

暂无评论...
验证码 换一张
取 消