要素数制限ObservableCollection

ログ等を蓄積して画面に表示する為に ObservableCollection を使用する時に、蓄積データ数に制限をかけられるクラスを ObservableCollection をベースに作りました。 データを足して行った時に、所定数を超えると古い要素が削除されます。

素数制限付きObservableCollection

ObservableCollection を継承して SizeLimitStringCollection を作成し、下記のような項目を追加します。

  1. 素数の制限値である Limit を作成します。
  2. 素数を Limit に抑えるためのメソッド Shrink を追加します。 Shrink では、要素が先頭に挿入された時には最後を、それ以外に加えられた時には先頭を削除します。
  3. InsertItem(int index, string item) を override します。 insert される文字列には、先頭に現在時刻を付加します。 Shrink の引数に index を渡して、Limit を超えた時の削除位置が変わるようにします。
public class SizeLimitStringCollection : ObservableCollection<string>
{
    protected bool SetProperty<T>(ref T field, T value, [CallerMemberName]string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        return true;
    }

    protected virtual void Shrink(int index)
    {
        if (index != 0)
        {
            while (Limit < Count) RemoveAt(0);
        }
        else
        {
            while (Limit < Count) RemoveAt(Count - 1);
        }
    }

    private int limit = 100;
    public int Limit
    {
        get { return limit; }
        set
        {
            if (value < 1) value = 1;
            if (SetProperty(ref limit, value))
            {
                Shrink(Count);
            }
        }
    }

    protected override void InsertItem(int index, string item)
    {
        item = DateTime.Now.ToString("hh:MM:ss ") + item;
        base.InsertItem(index, item);
        Shrink(index);
    }
}

使い方

LogCollection を作成します。

private SizeLimitStringCollection logCollection = new SizeLimitStringCollection();
public SizeLimitStringCollection LogCollection
{
    get { return logCollection; }
    set { SetProperty(ref logCollection, value); }
}
  • 先頭にログを追加する時には
    LogCollection .inseret(0, LogString) とします。

  • 最後尾にログを追加する時には
    LogCollection .add(LogString) とします。

別スレッドからのアクセス

ObservableCollectionはUIスレッドにあるので、別スレッドから操作する時にはDispatcherを使用します。 その為には以下のメソッドを作っておいて呼び出してあげます。

public void SetLog(string st)
{
    System.Windows.Application.Current.Dispatcher.BeginInvoke(
         new Action(() => LogCollection.Insert(0, st)));
}

サンプルアプリケーション

SizeLimitStringCollection を使ったサンプルアプリを作りました。

f:id:feynman911:20190918231540j:plain

ソースコードは下記にあります。

github.com