これはかなり一般的なシナリオのようですが、クリップボードに何もないときに無効にするメニューアイテムをバインドする方法を理解できません。Treeview ContextMenuバインディング論理ツリーに切り取りと貼り付け
私はWindowsのクリップボードを使用しないで、代わりにNodeClipboardというUserControlの参照変数に実際のオブジェクトを格納しました。それは強く型付けされ、INotifyPropertyを実装しているので、Windowsのクリップボードよりもはるかに便利です。
Style Event Settersを使用せずにリソース内でEventHandlerを設定できないため、個々の項目へのバインドはきわめて冗長ですが、うまく機能します。
それは一種の、このようになります...
<UserControl x:Name="PART_Root">
<TreeView x:Name="PART_Tree" ItemsSource="{Binding ElementName=PART_Root, Path=RootItemContainer}">
<TreeView.Resources>
<ContextMenu x:Key="ContextMenu">
<ContextMenu.Style>
<Style TargetType="ContextMenu">
<!-- I use this event to select the tree view item otherwise it is actually pretty difficult to know what item you right clicked on -->
<EventSetter Event="Opened" Handler="ContextMenu_Opened"/>
</Style>
</ContextMenu.Style>
<MenuItem Header="Cut">
<MenuItem.Style>
<Style TargetType="MenuItem">
<EventSetter Event="Click" Handler="CutNode_Click"/>
<Style.Triggers>
<!-- This binding is fine because it binds to the item that was right clicked on -->
<DataTrigger Binding="{Binding Path=IsRoot}" Value="True">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Style>
</MenuItem>
<MenuItem Header="Paste">
<MenuItem.Style>
<Style TargetType="MenuItem">
<EventSetter Event="Click" Handler="PasteNode_Click"/>
<!-- This binding always fails because ContextMenu lives outside of the logical tree -->
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=PART_Root, Path=NodeClipboard" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Style>
</MenuItem>
</ContextMenu>
<Style TargetType="TreeViewItem">
<Setter Property="ContextMenu" Value="{StaticResource ContextMenu}"/>
</Style>
<HierarchicalDataTemplate DataType="{x:Type local:Node}" ItemsSource="{Binding Path=Children}">
<TextBlock Text="{Binding Path=Id}"/>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</UserControl>
動作しないキー部分は、ここではこれです:
<!-- This binding always fails because ContextMenu lives outside of the logical tree -->
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=PART_Root, Path=NodeClipboard" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
私は、その結果、相対ソースを使用して試してみました同じ問題。私がこれまで考えてきた唯一の解決策は... 2つのコンテキストメニュー、有効にペーストを1とせずに1を作る、などのようなツリービューアイテムのスタイルののContextMenuセッターのスタイルのコンテキストメニューを切り替えている
<TreeView.Resources>
<Style TargetType="TreeViewItem">
<Setter Property="ContextMenu" Value="{StaticResource ContextMenu_PasteEnabled}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=PART_Root, Path=NodeClipboard" Value="{x:Null}">
<Setter Property="ContextMenu" Value="{StaticResource ContextMenu_PasteDisabled}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TreeView.Resources>
しかし、その内容は、私はそれにメニュー項目の有効状態を結合する方法はありません変更したときにクリップボードクラスは、任意の通知を与えるものではありませんので。 ContextMenu Openイベントで状態をチェックする必要があります。 – NtscCobalt
ありがとうございます。 ContextMenuOpeningでそれを処理します。あなたの基準を満たしていない場合は、e.Handled = trueとなります。それは決してポップしません。追加するには、ここではMVVMスタイルのバインディングを使用しません。 – Xcalibur37
これらのメソッド(ContextMenu Openedイベント中にWindowsクリップボードを使用するかコンテキストメニューを変更する)は、ちょっとした厄介な2つの実行可能なメソッドのように思えます。うまくいけば、WPFの将来のバージョンでより良い方法が導入されることを願っています。 – NtscCobalt