DataTemplate で生成されたコントロールにアクセスする
リストビューの各行にチェックボックスを配置して、さらにカラムヘッダにも全選択/全選択解除用のチェックボックスを配置しました。ヘッダのチェックボックスのチェック状態を変更すると、すべての行のチェック状態が連動するようなイメージです。
<Window x:Class="CheckListView.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="パン">
<Window.Resources>
<XmlDataProvider x:Key="MyListSource" XPath="/Breads">
<x:XData>
<Breads xmlns="">
<Bread>ツォップフ</Bread>
<Bread>クロワッサン</Bread>
<Bread>ベーグル</Bread>
<Bread>フガス</Bread>
<Bread>バケット</Bread>
<Bread>リュスティック</Bread>
<Bread>ロッゲンフォルコーンブロート</Bread>
<Bread>チャパタ</Bread>
</Breads>
</x:XData>
</XmlDataProvider>
</Window.Resources>
<ListView x:Name="CheckBoxList" ItemsSource="{Binding Source={StaticResource MyListSource}, XPath=Bread}">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.HeaderTemplate>
<DataTemplate>
<CheckBox x:Name="CheckAll" Checked="CheckAll_Checked" Unchecked="CheckAll_Checked"/>
</DataTemplate>
</GridViewColumn.HeaderTemplate>
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Name="CheckSelect"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="パンの種類" DisplayMemberBinding="{Binding XPath=.}"/>
</GridView>
</ListView.View>
</ListView>
</Window>
ヘッダのチェックボックス(CheckAll)の Checked と Unchecked のイベントハンドラ CheckAll_Checked の実装は、MSDN ライブラリの 方法 : DataTemplate によって生成された要素を検索する を参考にしました。
private void CheckAll_Checked (object sender, RoutedEventArgs e)
{
var checkAll = sender as CheckBox;
if (checkAll != null)
{
// ListView の各行を走査
foreach (var item in CheckBoxList.Items)
{
// 行より ListViewItem を取得
ListViewItem listViewItem = CheckBoxList.ItemContainerGenerator.ContainerFromItem (item) as ListViewItem;
if (listViewItem != null)
{
// ListViewItem の VisualTree より、ContentPresenter を検索する
ContentPresenter presenter = FindVisualChild<ContentPresenter> (listViewItem);
// ContentPresenter の DataTemplate より、名前でコントロールを検索する
CheckBox checkSelect = presenter.ContentTemplate.FindName ("CheckSelect", presenter) as CheckBox;
if (checkSelect != null)
{
// コントロールが見つかれば、チェック状態を追従
checkSelect.IsChecked = checkAll.IsChecked;
}
}
}
}
}
FindVisualTree の実装は上記リンクで紹介されているものと同じです。子要素を再帰検索して、最初に見つかった TChild 型の要素を返します。
private static TChild FindVisualChild<TChild> (DependencyObject parent)
where TChild : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount (parent); i++)
{
DependencyObject child = VisualTreeHelper.GetChild (parent, i);
if (child != null && child is TChild)
{
return (TChild) child;
}
else
{
TChild subItem = FindVisualChild<TChild> (child);
if (subItem != null)
{
return subItem;
}
}
}
return null;
}
結構レスポンスが悪いので、もう少し効率のよい方法がないか考えます・・・。
トラックバック
- このエントリーにトラックバック:
- http://frog.raindrop.jp/cgi-bin/mt/mt-tb.cgi/2150
コメント
ItemsControl の場合、itemsControl.ItemContainerGenerator.ContainerFromItem (item) がすでに ContentPresenter だったりするみたい。