WPF に ListBox などに DataTemplate を定義してバインディングした場合、DataTemplate によって動的に生成されたコントロールや要素には事前に名前が定義できないため、ソースコードからアクセスできない。
たとえば下記のような XAML においてそれぞれの planListBox にアクセスしたいような状況だ。この例では userListBoxItem というリストボックスの中に DataTemplate で生成された planListBox というリストボックスが含まれていることを仮定している。
<ListBox Name="userListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=DisplayText}" />
<ListBox Name="planListBox">
<ListBox.ItemTemplate>
〜中略〜
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
これらの要素を参照するためにはちょっと込み入った手順が必要である。まず、下記の FindVisualChild メソッドを定義する。これは MSDN のソースそのままだ。
private T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is T)
return (T)child;
else
{
T childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
実際には下記のように使う。
ListBoxItem userListBoxItem = (ListBoxItem)(userListBox.ItemContainerGenerator.ContainerFromItem(userListBox.SelectedItem));
ContentPresenter contentPresenter = FindVisualChild<ContentPresenter>(userListBoxItem);
DataTemplate dataTemplate = contentPresenter.ContentTemplate;
ListBox planListBox = (ListBox)dataTemplate.FindName("planListBox", contentPresenter);
Kenz Yamada(山田研二)。1984年生。大阪。ちょっとずつ好きなプログラム作ってます。
好きなものはカメラと旅行。ガジェットや身の回り、ちょっとこだわります。
詳しくは Web mixi で。