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 だったりするみたい。