2010年1月27日水曜日

第9回 時間順に並べる

前回までのコードを実行した人は気づいたかもしれませんが、
起動時には最新のつぶやきが一番上に来るのに、
次のタイマ時刻のつぶやきからは下に追加されていきます。

というわけで今回はソート機能を追加します。

まず、時間を取得します。
私が知らないだけかもしれませんが、
JSONから直接DateTime型で取得できないみたいなので、
いったんstringで受け取ってから変換します。



  [DataMember(Name = "created_at")]
  private string CreatedAtString { get; set; }

  private DateTime? _createdAt = null;
  public DateTime CreatedAt {
   get {
    if (_createdAt == null) {
     _createdAt = DateTime.ParseExact(CreatedAtString, "ddd MMM dd HH:mm:ss zzzz yyyy",
      CultureInfo.GetCultureInfoByIetfLanguageTag("en-us"));
    }
    return _createdAt.Value;
   }
  }



CreatedAtの方にはDataMember属性がついていないことに注意してください。
このためJSON形式としては読み込まれず(=nullのまま)、
初めてgetが呼び出されたときにParseExactで文字列からDateTime型に変換します。

このCreatedAtはViewModelにも追加しています。

次にViewを変更します。
複雑になりそうなので、タイムライン部分をTimelineViewクラスに切り出しました。

よってMainWindowは以下のように簡単になります。



<Window x:Class="WTwitter.View.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:vmt="clr-namespace:WTwitter.ViewModel.Twitter"
 xmlns:vw="clr-namespace:WTwitter.View"
 xmlns:CompModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
    Title="WTwitter" Height="500" Width="400">
 <Window.Resources>
  <DataTemplate DataType="{x:Type vmt:TimelineViewModel}">
   <vw:TimelineView/>
  </DataTemplate>
 </Window.Resources>

 <TabControl ItemsSource="{Binding Path=Timelines}">
  <TabControl.ItemTemplate>
   <DataTemplate>
    <TextBlock Text="{Binding Path=DisplayName}"/>
   </DataTemplate>
  </TabControl.ItemTemplate>
 </TabControl>
</Window>





見ての通り、TabControlのContentTemplateがなくなりました。
そのかわりWindow.ResourceにDataTemplateを追加しています。
これは、TimelineViewModel型の表示を要求されたら、
TimelineViewを使うということです。
TabControlには依然としてItemsSourceとしてTimelinesを指定しているので、
Timelineを表示しようとして、そのときにDataTemplateがあるのでそっちを見に行くという仕組みです。

ではTimelineViewを見てみます。


<UserControl x:Class="WTwitter.View.TimelineView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:compModel="clr-namespace:System.ComponentModel;assembly=WindowsBase">
 <UserControl.Resources>
  <CollectionViewSource  x:Key="AllItemsViewSource" Source="{Binding Path=AllItems}">
   <CollectionViewSource.SortDescriptions>
    <compModel:SortDescription PropertyName="CreatedAt" Direction="Descending"/>
   </CollectionViewSource.SortDescriptions>
  </CollectionViewSource>
 </UserControl.Resources>
 
 <ListBox ItemsSource="{Binding Source={StaticResource AllItemsViewSource}}"
以下略




ResourceとしてCollectionViewSourceを追加していて、
(=CollectionViewSourceのインスタンスを生成して、UserControlのリソースとして追加)
ListBoxのItemsSourceにそれを指定しています。
ListBoxに直接Sort方法をしていする方法はないみたいで、
CollectionViewSourceを通じて指定しています。
CollectionViewSourceは私もよく説明できないのですが、
Collectionを表示するようなViewを操作する一般的な方法を集めた
あらかじめ用意されたViewModelのようなもので、
どのようなViewにするかに依存しないでリストを操作できます。

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

0 件のコメント:

コメントを投稿