【问题标题】:Treeview ContextMenu binding Cut and Paste to logical treeTreeview ContextMenu 绑定剪切和粘贴到逻辑树
【发布时间】:2012-01-26 10:51:52
【问题描述】:

这似乎是一个很常见的场景,但是当剪贴板中没有任何内容时,我不知道如何绑定菜单项以禁用。

我决定不使用 Windows 剪贴板,而是将实际对象存储在 UserControl 上称为 NodeClipboard 的引用变量中。由于它是强类型并实现了 INotifyProperty,它对我来说比 Windows 剪贴板有用得多。

绑定到单个项目可以正常工作,尽管它非常冗长,因为如果不使用样式事件设置器就无法在资源中设置事件处理程序。

好像是这样的……

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

我尝试过使用相对源,这会导致同样的问题。到目前为止,我想到的唯一解决方案是制作两个上下文菜单,一个启用粘贴,一个不启用,然后像这样在 TreeViewItem 样式的 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>

【问题讨论】:

    标签: wpf xaml treeview contextmenu


    【解决方案1】:

    使用剪贴板类。然后可以使用 ContainsText 方法判断剪贴板上是否有数据。

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

    【讨论】:

    • 但是由于剪贴板类在其内容更改时不会发出任何通知,因此我无法将菜单项的启用状态绑定到它。我必须在 ContextMenu Open 事件中检查状态。
    • 当然可以。在 ContextMenuOpening 上,处理它。如果它不符合您的标准,则 e.Handled = true。它永远不会弹出。要添加,您不会在此处使用 MVVM 样式绑定。
    • 被接受是因为这些方法(使用 Windows 剪贴板或在 ContextMenu Opened 事件期间修改上下文菜单)似乎是仅有的两种可行的方法,但有点糟糕。希望在 WPF 的未来版本中引入更好的方法。
    猜你喜欢
    • 2023-03-26
    • 1970-01-01
    • 2018-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多