Reputation: 1611
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.
Upvotes: 2
Views: 4199
Reputation: 739
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.
Upvotes: 1
Reputation: 2698
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
Upvotes: 2