2010年2月26日金曜日

第17回 全部のタイムラインを表示するタイムラインを作る

今回のタイトルはちょっとわかりにくいかもしれませんが、
自分のタイムラインや検索のタイムラインごとにタブを切り替えるのがめんどうなので、
全部いっぺんに表示するタイムラインを作ります。

やることは簡単です。
複数のTimelineクラスを所持して、それらすべてのアイテムの追加を見張るクラスを作ります。
まず、ViewModelからはほぼ同一として扱うために
ITimelineというインターフェイスクラスを作ります。
これはこれまでのTimelineクラスのインターフェイスを切り出しただけなのでコード略。

新しく作ったMultiSourceTimeline 考え方はシンプルで、
持っているいくつかのTimelineクラスのすべてのItemAddedを拾って、
そのアイテムを自分のアイテムとして持つとともに、
ViewModelには自分のItemAddedイベントとしてそのままイベントを投げます。



 class MultiSourceTimeline : ITimeline {
  #region private member
  private UserInfo _info;
  private List<ITimelineItem> _allItems = new List<ITimelineItem>();
  private List<ITimeline> _sourceTimelines = new List<ITimeline>();
  #endregion

  public MultiSourceTimeline(IEnumerable<ITimeline> sources, UserInfo info) {
   _info = info;
   foreach (var timeline in sources) {
    AddTimeline(timeline);
   }
   ItemAdded += (sender, e) => {};
  }

  public MultiSourceTimeline(UserInfo info)
   : this(Enumerable.Empty<ITimeline>(), info){

  }

  public void AddTimeline(ITimeline target) {
   _sourceTimelines.Add(target);
   target.ItemAdded += this.OnItemAdded;
  }

  public void RemoveTimeline(ITimeline target) {
   _sourceTimelines.Remove(target);
   target.ItemAdded -= this.OnItemAdded;
  }

  private void OnItemAdded(object sender, ItemAddedEventArgs e) {
   _allItems.Add(e.Item);
   var handler = ItemAdded;
   handler(this, e);
  }

あとはMainWindowViewModelのInitialize()をちょっと工夫するだけです。
他のタイムラインを作った時に、MultiSourceTimeline にもそのタイムラインを追加しています。



  public void Initialize() {
・・・略
   //Modelの作成
   var allVM = new TimelineViewModel("All", _allItemTimeline);
   Timelines.Add(allVM);
   foreach (var setting in _option.TimelineSettings) {
    var vm = CreateFrom(setting);
    Timelines.Add(vm);
    if (vm.IsUpdatable) {
     vm.Update();
     vm.StartAutoUpdate();
    }
   }

   _submitPanel = new SubmitPanelViewModel(_userInfo);
   OnPropertyChanged("SubmitPanel");
  }



今回のソースまでにバグフィックスなど細かい点で
ソースコードに手を入れています。
個々は簡単な変更なので直接ソースコードを見てください。

今回のソースコード
http://wtwitter.codeplex.com/SourceControl/changeset/view/41872

1 件のコメント:

  1. 同じアイテムを拾う場合があるので
    OnItemAdded
    の最初に
    if (_allItems.Contains(e.Item)) {
    return;
    }
    が必要です。すみません。

    返信削除