fc2ブログ

CollectionViewSourceのViewを遅延更新させる

 CollectionViewSourceを利用して並べ替え等を行う際に条件によっては無駄な更新が発生します。
 例えば、並べ替え条件を複数指定する場合、一つ目の条件を追加した時点でViewが更新されるのは完全に無駄です。
 コレクションのアイテム数が少ない場合は気にする必要はありませんが、アイテム数が多いときはこの無駄な更新によるパフォーマンスの悪化が気になってくることもあります。
 そんな場合はViewの遅延更新を行うことで無駄な更新を避け、パフォーマンスを改善することができます。
public CollectionViewSource ItemsViewSource { get; private set; }

public void ValueSort()
{
    using (ItemsViewSource.DeferRefresh())
    {
        ItemsViewSource.SortDescriptions.Clear();
        ItemsViewSource.SortDescriptions.Add(new SortDescription("Value", ListSortDirection.Ascending));
    }
}
 遅延更新を行いたい場合はDeferRefreshメソッドを使用します。
 DeferRefreshメソッドは戻り値にIDisposableインスタンスを返し、Disposeメソッドが呼ばれた際にViewを更新します。
 そのため通常はサンプルコードの様にusingステートメントを使用します。
 あとはusingステートメント内で並べ替え等の条件を変更するだけです。
スポンサーサイト



テーマ : プログラミング
ジャンル : コンピュータ

CollectionViewSourceの並べ替え等を即座に反映させる

 これまで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>
 こんな感じで簡単にリアルタイムで並べ替え等を行えるようにできますが、その分だけパフォーマンスは悪化します。
 表示が我慢できないくらい遅くなってしまった場合は諦めましょう。

テーマ : プログラミング
ジャンル : コンピュータ

カレンダー
11 | 2015/12 | 01
- - 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 - -
全記事表示リンク

全ての記事を表示する

カテゴリ
タグリスト

月別アーカイブ
04  10  11  09  08  07  06  05  04  03  02  01  12  11  10  09  08  07  06  04  03  02  01  12  11  10  09  08  07  06  05  04  03  02  01  12  11  10  09 
最新記事
リンク
最新コメント
検索フォーム
Amazon