#setlinebreak(on);
[[WP TIPS に戻る>wp7/tips]]
*ListBox のアイテム描画の完了を確認する方法 [#g60c7566]
サンプルプロジェクト [[ListBox_Timing.zip>https://skydrive.live.com/redir.aspx?cid=793b87c06d2f0cd5&resid=793B87C06D2F0CD5!1902&parid=793B87C06D2F0CD5!223]]
ListBox のアイテム表示の方法は、ListBox.ItemSource に表示するコレクションをバインドするのが一般的な方法で、みなさんも良くお使いなのではないでしょうか。WinForm の頃のように ListBox.Items.Add メソッドでアイテムを追加する事は少なくなりましたね。
しかしアイテム描画は非同期で行われます。
描画が完了したら次のアクションを行う、という事をしたい場合はどうしたらよいでしょうか?
例えば以下のコードは、ListBox.ItemSource にバインドしている Items にアイテムを追加し、完了したら最後のアイテムまでスクロールを行う、というものです。が、このコードではスクロールが出来ません。
なぜなら ScrollIntoView メソッドを実行したときには、まだアイテムの描画が完了していないからです。
private void Update()
{
this.Items = new ObservableCollection<string>();
for(int i = 0; i< 100; i++)
{
this.Items.Add(i.ToString() + " " + DateTime.Now.ToString());
}
this.OnPropertyChanged("Items");
// スクロールするが出来ない - 描画完了前なので
this.listbox.ScrollIntoView(this.Items[this.Items.Count - 1]);
}
実は ListBox.ItemSouce にバインドしているアイテムの描画が完了したら、LayoutUpdated イベントが立ち上がるので、これをトリガにすれば可能です。
実は ListBox.ItemSouce にバインドしているアイテムの描画が完了したら LayoutUpdated イベントが立ち上がる& ItemSource.Count が更新されるので、これをトリガにすれば可能です。
public ObservableCollection<string> Items { get; set; }
// コンストラクター
public MainPage()
{
InitializeComponent();
this.DataContext = this;
this.listbox.LayoutUpdated += new EventHandler(listbox_LayoutUpdated);
}
int Count
{
get
{
int count = this.listbox.ItemsSource == null ? 0 : ((ICollection)this.listbox.ItemsSource).Count;
return count;
}
}
void listbox_LayoutUpdated(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine("listbox_LayoutUpdated " + this.Count);
// 描画完了後のスクロールなのでちゃんとスクロールする。
if (this.Items != null && this.Count == this.Items.Count)
{
this.listbox.ScrollIntoView(this.Items[this.Items.Count - 1]);
}
}