これまでCollectionViewSourceを使って並べ替えやフィルター等を行ってきましたが、コレクションに含まれている項目のプロパティを変更しても即座に反映はされません。
何らかの方法でViewを更新した際に初めて並べ替えやフィルターの結果が表示されていました。
これを対象のプロパティが変更された際に即座にViewを更新できるように設定することもできます。
以下のサンプルコードではValueというプロパティが変更された際に即座に並べ替えが起きるようにしています。
using Livet;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Data;
namespace CollectionViewSourceDemo5.ViewModels
{
public class MainWindowViewModel : ViewModel
{
public MainWindowViewModel()
{
Items = new ObservableCollection<ItemViewModel>();
Items.Add(new ItemViewModel(1));
Items.Add(new ItemViewModel(2));
Items.Add(new ItemViewModel(3));
Items.Add(new ItemViewModel(4));
Items.Add(new ItemViewModel(5));
ItemsViewSource = new CollectionViewSource() { Source = Items };
ItemsViewSource.SortDescriptions.Add(new SortDescription("Value", ListSortDirection.Ascending));
// Valueプロパティが変更された際は即座に並べ替えを行うようにする
ItemsViewSource.IsLiveSortingRequested = true;
ItemsViewSource.LiveSortingProperties.Add("Value");
}
public ObservableCollection<ItemViewModel> Items { get; private set; }
public CollectionViewSource ItemsViewSource { get; private set; }
}
public class ItemViewModel : ViewModel
{
public ItemViewModel(int value)
{
Value = value;
}
#region Value変更通知プロパティ
private int _Value;
public int Value
{
get
{ return _Value; }
set
{
if (_Value == value)
return;
_Value = value;
RaisePropertyChanged();
}
}
#endregion
}
}
コードの簡略化の為ViewModelとModelを一体化させています。
ViewModelではCollectionViewSourceを作成し、並べ替え条件を指定しています。
即座に並べ替えを行うためにはIsLiveSortingRequestedをtrueにして、LiveSortingPropertiesに監視するプロパティ名を追加します。
今回のサンプルでは並べ替えだけを扱っていますが、フィルターやグループ分けの時も同様です。
フィルターの場合は、IsLiveFilteringRequestedをtrueにして、LiveFilteringPropertiesにプロパティ名を追加します。
グループ分けの場合は、IsLiveGroupingRequestedをtrueにして、LiveGroupingPropertiesにプロパティ名を追加します。
<Window x:Class="CollectionViewSourceDemo5.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:CollectionViewSourceDemo5.ViewModels"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
xmlns:system="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<vm:MainWindowViewModel/>
</Window.DataContext>
<Window.Resources>
<DataTemplate DataType="{x:Type vm:ItemViewModel}">
<TextBox Text="{Binding Value}" Width="50"/>
</DataTemplate>
</Window.Resources>
<StackPanel Orientation="Horizontal">
<ListBox ItemsSource="{Binding ItemsViewSource.View}"/>
</StackPanel>
</Window>
ViewではViewModelで作成したCollectionViewをListBoxにバインディングしているだけです。
これでListBoxに表示されている値を変更しフォーカスが移動すると、リストが並び変わります。
これをXAMLで記述したい場合は以下の様になります。
<Window.Resources>
<CollectionViewSource x:Key="ViewSource" Source="{Binding Items}"
IsLiveSortingRequested="True">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Value" Direction="Descending"/>
</CollectionViewSource.SortDescriptions>
<CollectionViewSource.LiveSortingProperties>
Value
</CollectionViewSource.LiveSortingProperties>
</CollectionViewSource>
</Window.Resources>
こんな感じで簡単にリアルタイムで並べ替え等を行えるようにできますが、その分だけパフォーマンスは悪化します。
表示が我慢できないくらい遅くなってしまった場合は諦めましょう。
テーマ : プログラミング
ジャンル : コンピュータ