トップ回答者
TreeView上のContextMenuで右クリックしたオブジェクトを取得する方法

質問
-
いつもお世話になります。
環境はSilverlight4、VS2010、.NET4(C#)です。
下記XAMLコードのように、HierarchicalDataTemplateを使ってTreeViewにデータバインドしています。
<!-- メンバー -->
<sdk:HierarchicalDataTemplate x:Key="ChildTemplate">
<TextBlock Text="{Binding Path=Name}" Height="14" />
</sdk:HierarchicalDataTemplate>
<!-- グループ -->
<sdk:HierarchicalDataTemplate x:Key="NameTemplate"
ItemsSource="{Binding Path=Members}"
ItemTemplate="{StaticResource ChildTemplate}">
<TextBlock Text="{Binding Path=Name}" FontWeight="Bold" Height="14">
<cinput:ContextMenuService.ContextMenu>
<cinput:ContextMenu>
<cinput:MenuItem Header="名前を変更" Click="groupItemMenuChangeName_Click" />
<cinput:MenuItem Header="削除" />
</cinput:ContextMenu>
</cinput:ContextMenuService.ContextMenu>
</TextBlock>
</sdk:HierarchicalDataTemplate>
表示される各項目はTextBlockですので、そこにContextMenuを追加しているのですが、
コード中のgroupItemMenuChangeName_Clickが呼ばれた時、どの項目を右クリックしたかが分かりません。
どのように取得すればよいのでしょうか。2011年8月10日 3:34
回答
-
直接的な回答ではないのですが、Clickイベントを発生させる前、つまりMouseRightButtonDownイベントで該当オブジェクトを選択させ、
ClickイベントでSelectedItemを取得する方法は使えないでしょうか。XAMLでTreeViewのMouseRightButtonDownイベントハンドラを定義し、次のように書きます。
VisualTreeHelperを使って、マウスカーソル上のアイテムを取得し、そのアイテムを選択状態(SelectedItemに代入される)にしています。private void treeView_MouseRightButtonDown(object sender, MouseButtonEventArgs e) { foreach (var item in VisualTreeHelper.FindElementsInHostCoordinates(e.GetPosition(Application.Current.RootVisual), treeView)) { var treeViewItem = item as TreeViewItem; if (treeViewItem != null) { treeView.SelectItem(treeViewItem.DataContext); break; } } }
foreach文をbreakしているのは、VisualTreeHelperの仕様として、TreeViewの子アイテムにカーソルがある場合、子アイテムから順に親アイテムも取得してしまうからです。このあと、Clickイベントハンドラ内でTreeViewのSelectedItemを取得すると、私の場合うまくいったのですかいかがでしょうか。
- 回答としてマーク femp 2011年8月10日 5:26
2011年8月10日 5:00 -
> 私の環境化では、教えて頂いたコードのtreeView.SelectItem()が利用できなかったため(存在しないメソッドの模様)
私のソースをよくみたところ、SelectItemメソッドはSilverlightToolkitで定義されている拡張メソッドでした。
アセンブリ System.Windows.Controls.Toolkit.dll 内の System.Windows.Controls.TreeViewExtensions 静的クラスで定義されていました。
失礼しました。- 回答としてマーク femp 2011年8月10日 7:08
2011年8月10日 6:35
すべての返信
-
直接的な回答ではないのですが、Clickイベントを発生させる前、つまりMouseRightButtonDownイベントで該当オブジェクトを選択させ、
ClickイベントでSelectedItemを取得する方法は使えないでしょうか。XAMLでTreeViewのMouseRightButtonDownイベントハンドラを定義し、次のように書きます。
VisualTreeHelperを使って、マウスカーソル上のアイテムを取得し、そのアイテムを選択状態(SelectedItemに代入される)にしています。private void treeView_MouseRightButtonDown(object sender, MouseButtonEventArgs e) { foreach (var item in VisualTreeHelper.FindElementsInHostCoordinates(e.GetPosition(Application.Current.RootVisual), treeView)) { var treeViewItem = item as TreeViewItem; if (treeViewItem != null) { treeView.SelectItem(treeViewItem.DataContext); break; } } }
foreach文をbreakしているのは、VisualTreeHelperの仕様として、TreeViewの子アイテムにカーソルがある場合、子アイテムから順に親アイテムも取得してしまうからです。このあと、Clickイベントハンドラ内でTreeViewのSelectedItemを取得すると、私の場合うまくいったのですかいかがでしょうか。
- 回答としてマーク femp 2011年8月10日 5:26
2011年8月10日 5:00 -
回答ありがとうございます。
教えて頂いた方法でうまくいきました。
少し戸惑ってしまいましたが、上記イベントハンドラを設定するのは
TreeView要素ではなく、項目のTextBlockで良いんですよね?
TreeViewに対して設定すると、項目上で右クリックしても反応しませんでしたが、
(項目外のTreeView領域内なら反応した)
TextBlockに対して設定したらうまくいきました。
#教えて頂いた処理内容であれば、どっちでも関係ないですよね多分
大変助かりました。
ありがとうございました。
追記:
私の環境化では、教えて頂いたコードのtreeView.SelectItem()が利用できなかったため(存在しないメソッドの模様)
代わりに
treeViewItem.IsSelected = true;
として対応したことを、参考情報として追記させて頂きます。
ExpressionBlendだと存在するとか、そういう違いなんだろうか・・・2011年8月10日 5:26 -
> 私の環境化では、教えて頂いたコードのtreeView.SelectItem()が利用できなかったため(存在しないメソッドの模様)
私のソースをよくみたところ、SelectItemメソッドはSilverlightToolkitで定義されている拡張メソッドでした。
アセンブリ System.Windows.Controls.Toolkit.dll 内の System.Windows.Controls.TreeViewExtensions 静的クラスで定義されていました。
失礼しました。- 回答としてマーク femp 2011年8月10日 7:08
2011年8月10日 6:35