Treeview ContextMenu привязки вырезать и вставить в логическое дерево - PullRequest
0 голосов
/ 23 декабря 2011

Это кажется довольно распространенным сценарием, но я не могу понять, как связать пункты меню, чтобы отключить их, когда в буфере обмена ничего нет.

Я решил не использовать буфер обмена Windows и вместо этого сохранить фактический объект в ссылочной переменной в UserControl под названием NodeClipboard.Поскольку он строго типизирован и реализует INotifyProperty, он гораздо полезнее для меня, чем буфер обмена Windows.

Привязка к отдельному элементу работает нормально, хотя и чрезвычайно многословна, поскольку вы не можете устанавливать EventHandlers внутри ресурсов без использованиясеттеры событий стиля.

Это выглядит примерно так ...

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

Я попытался использовать относительный источник, который приводит к той же проблеме.Единственное решение, о котором я до сих пор думал, - это создать два контекстных меню, одно с включенной вставкой, а другое без, и переключить контекстное меню на стиль в установщике ContextMenu стиля TreeViewItem следующим образом ...

<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 Ответ

1 голос
/ 23 декабря 2011

Используйте класс Clipboard.Затем вы можете использовать метод ContainsText, чтобы определить, есть ли какие-либо данные в буфере обмена.

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

...