Third Generation
After reading Messenger and View Services in MVVM by Laurent Bugnion, I thought about moving sorting again to the ViewModel. The View will still handle the visual elements, while the ViewModel has again the responsibility for sorting. So sorting can also be triggered by the business logic, if needed.
The ViewModel is nearly the same as in the First Generation, but the RelayCommand is not needed.
private ObservableCollection<ResultData> _thirdResultData; private CollectionViewSource _thirdResultDataView; private string _sortColumn; private ListSortDirection _sortDirection; public ObservableCollection<ResultData> ThirdResultData { get { return _thirdResultData; } set { _thirdResultData = value; _thirdResultDataView = new CollectionViewSource(); _thirdResultDataView.Source = _thirdResultData; } } public ListCollectionView ThirdResultDataView { get { return (ListCollectionView)_thirdResultDataView.View; } } public void Sort(string column) { if (_sortColumn == column) { // Toggle sorting direction _sortDirection = _sortDirection == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending; } else { _sortColumn = column; _sortDirection = ListSortDirection.Ascending; } _thirdResultDataView.SortDescriptions.Clear(); _thirdResultDataView.SortDescriptions.Add( new SortDescription(_sortColumn, _sortDirection)); }
The XAML part of the View is the same as in the Second Generation.
<UserControl.Resources> <DataTemplate x:Key="ArrowUp"> <DockPanel> <TextBlock HorizontalAlignment="Center" Text="{Binding}" /> <Path VerticalAlignment="Center" Fill="Black" Data="M 5,5 15,5 10,0 5,5" /> </DockPanel> </DataTemplate> <DataTemplate x:Key="ArrowDown"> <DockPanel> <TextBlock HorizontalAlignment="Center" Text="{Binding}" /> <Path VerticalAlignment="Center" Fill="Black" Data="M 5,0 10,5 15,0 5,0" /> </DockPanel> </DataTemplate> </UserControl.Resources> <Grid> <ListView ItemsSource="{Binding ThirdResultDataView}" GridViewColumnHeader.Click="ThirdResultDataViewClick"> <ListView.View> <GridView> <GridViewColumn DisplayMemberBinding="{Binding ResultNumber}"> <GridViewColumnHeader Content="Number" /> </GridViewColumn> <GridViewColumn DisplayMemberBinding="{Binding ResultOutput}"> <GridViewColumnHeader Content="Output" /> </GridViewColumn> </GridView> </ListView.View> </ListView> </Grid>
The code-behind of the View is nearly the same as in the Second Generation, but the call of the sorting method in the ViewModel is added.
private ListSortDirection _sortDirection; private GridViewColumnHeader _sortColumn; private void ThirdResultDataViewClick(object sender, RoutedEventArgs e) { GridViewColumnHeader column = e.OriginalSource as GridViewColumnHeader; if (column == null) { return; } if (_sortColumn == column) { // Toggle sorting direction _sortDirection = _sortDirection == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending; } else { // Remove arrow from previously sorted header if (_sortColumn != null) { _sortColumn.Column.HeaderTemplate = null; _sortColumn.Column.Width = _sortColumn.ActualWidth - 20; } _sortColumn = column; _sortDirection = ListSortDirection.Ascending; column.Column.Width = column.ActualWidth + 20; } if (_sortDirection == ListSortDirection.Ascending) { column.Column.HeaderTemplate = Resources["ArrowUp"] as DataTemplate; } else { column.Column.HeaderTemplate = Resources["ArrowDown"] as DataTemplate; } string header = string.Empty; // if binding is used and property name doesn't match header content Binding b = _sortColumn.Column.DisplayMemberBinding as Binding; if (b != null) { header = b.Path.Path; } var viewModel = DataContext as SortingViewModel; viewModel.Sort(header); }
The source code can be downloaded from http://code.msdn.microsoft.com/Sorting-a-WPF-ListView-by-ce9cf6d7
Further Posts
- Sorting a WPF ListView/GridView by clicking on the header
- Sort Direction Indicators
- Sort in ViewModel
- Sort Direction Indicators with Adorners
- Reusability
- More Reusability
- Attached Property
- Behaviors (Expression Blend)
No comments:
Post a Comment