2010年1月21日木曜日

第5回 画像を表示する

画像が表示されないと寂しいので発言者のアイコンを表示するようにしてみます。

ぼかしていますが、完成イメージはだいたいこんな感じ↓


まずStatusクラスとUserクラスでこれまで取得していなかったデータをとるようにしてみます。


namespace WTwitter.Model.Twitter {
/// <summary>
/// TwitterのJson形式データ
/// </summary>
[DataContract]
class Status {
[DataMember(Name = "id")]
public long Id { get; set; }
[DataMember(Name = "text")]
public string Text { get;set;}
[DataMember(Name = "favorited")]
public bool Favorited { get; set; }
[DataMember(Name="user")]
public User User { get; set; }
[DataMember(Name = "in_reply_to_user_id")]
public long? InReplyToUserId { get; set; }
[DataMember(Name = "in_reply_to_status_id")]
public long? InReplyToStatusId { get; set; }
[DataMember(Name = "in_reply_to_screen_name")]
public string InReplyToScreenName { get; set; }
public override string ToString() {
return User.ScreenName + ":" + Text;
}
}
}




namespace WTwitter.Model.Twitter {
/// <summary>
/// TwitterのJson形式のユーザ情報
/// </summary>
[DataContract]
class User {
[DataMember(Name = "id")]
public long Id { get; set; }
[DataMember(Name = "screen_name")]
public string ScreenName { get; set;}
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "url")]
public string Url { get; set;}
[DataMember(Name = "description")]
public string Description { get; set; }
[DataMember(Name = "profile_image_url")]
public string ProfileImageUrl { get; set; }
[DataMember(Name = "following")]
public bool? Following { get; set; }
}
}




TwitterのJSON形式にはもっといっぱいデータが入っていますが、
今回は近いうちに使いそうなのだけピックアップしています。
また、すぐに使うのはProfileImageUrl だけです。

データが多くなっただけでそれほど難しくないと思います。
整数が返ってくるものはlong型など、true/falseで返ってくるものはbool型で宣言します。
文字列だけではなく整数型(long)なども正しく型指定しておけば
勝手に文字列から変換してくれます。
ただし変換できない型で変数を宣言していたら例外で落ちます。
また、値が入っていない(null)可能性があるものには
long?のように?を付けてnull許容型で宣言します。



namespace WTwitter.ViewModel.Twitter {
 /// <summary>
 /// タイムラインで表示する1アイテムを表すViewModel
 /// </summary>
 class TimelineItemViewModel {
  private Status _item;
  public TimelineItemViewModel(Status item) {
   _item = item;
  }

  public string Text {
   get { return _item.Text; }
  }

  public string Name {
   get { return _item.User.ScreenName; }
  }

  public string ProfileImageUrl {
   get { return _item.User.ProfileImageUrl; }
  }

  public override string ToString() {
   return _item.ToString();
  }
 }
}



TimelineItemViewModelは今回使うProfileImageUrl だけを増やしました。



<Window x:Class="WTwitter.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="WTwitter" Height="300" Width="300" >
 <DockPanel>
  <ListBox ItemsSource="{Binding Path=AllItems}"
     ScrollViewer.HorizontalScrollBarVisibility="Disabled"
     HorizontalContentAlignment="Stretch">
   <ListBox.ItemTemplate>
    <DataTemplate>
     <Border BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Margin="1">
      <DockPanel>
       <Image Source="{Binding Path=ProfileImageUrl}" Stretch="None" DockPanel.Dock="Left"/>
       <TextBlock Text="{Binding Path=Name}" DockPanel.Dock="Top"/>
       <TextBlock Text="{Binding Path=Text}" TextWrapping="Wrap"/>
      </DockPanel>
     </Border>
    </DataTemplate>
   </ListBox.ItemTemplate>
  </ListBox>
 </DockPanel>
</Window>



Viewは上記のように、Borderの中をDockPanelに変更しました。
これは今までも使っていましたが、
まずImageを表示するだけ左詰めで領域を確保して、
残りの右の領域の上詰めでNameを表示するTextBlock、
その下にTextを表示するようにしています。

DockPanel.Dock="Left"のような表記が、どっちに詰めるかを表しています。
DockPanelの動作に関しては検索してもらうとわかりやすいページがすぐに出てくると思います。

ここで注意して欲しいのは DockPanel.Dockはすぐ外側のDockPanelのDockプロパティを表します。
さらに外側のDockPanelには関係ありません。
また、Imageのプロパティではなく、DockPanelのプロパティであることを知っておくといいかもしれません。
なのでImageクラスの仕様を調べてもこのようなプロパティは存在しません。
ImageがDockPanelに自分のDock位置はTopですよーと伝えるような感じです。
すぐに知りたい場合は依存関係プロパティという仕組みを調べてみてください。


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

0 件のコメント:

コメントを投稿