2011-12-22 69 views
0

這似乎是一個非常常見的情況,但我無法弄清楚如何綁定菜單項以在剪貼板中沒有任何內容時禁用。Treeview ContextMenu綁定剪切並粘貼到邏輯樹

我決定不使用Windows剪貼板,而是將實際對象存儲在名爲NodeClipboard的UserControl上的引用變量中。由於它是強類型的,並且實現了INotifyProperty,所​​以比Windows剪貼板更有用。

綁定到單個項目時工作正常,但它非常冗長,因爲如果不使用樣式事件設置器,您無法在資源中設置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> 

我使用這會導致相對源嘗試同樣的問題。到目前爲止,我認爲唯一的解決辦法是使兩種上下文菜單,一個與粘貼啓用,另一個沒有,和開關上的樹型視圖樣式的文本菜單二傳手,像這樣的風格的上下文菜單...

<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> 

回答

1

使用剪貼板類。然後,您可以使用ContainsText方法確定剪貼板上是否有任何數據。

http://msdn.microsoft.com/en-us/library/system.windows.forms.clipboard.aspx

+0

但是,因爲當其內容的變化我沒有的菜單項的啓用狀態結合到它的方式剪貼板類不給予任何通知。我不得不在ContextMenu Open事件中檢查狀態。 – NtscCobalt 2011-12-23 01:13:58

+0

當然可以。在ContextMenuOpening上,處理它。如果它不符合你的標準,那麼e.Handled = true。它永遠不會彈出。要添加,您不會在此處使用MVVM樣式綁定。 – Xcalibur37 2011-12-23 01:33:35

+0

接受,因爲這些方法(在ContextMenu Opened事件中使用Windows剪貼板或修改上下文菜單)看起來像是隻有兩種可行的方法,只是有點糟糕。希望在未來的WPF版本中會引入更好的方法。 – NtscCobalt 2011-12-28 18:06:43