XAML 中的 WPF 合并上下文菜单

问题描述 投票:0回答:1

是否可以在 XAML 中合并两个 ContextMenu?

我创建了两个 ContextMenues 作为资源。我在几个数据模板中使用它们并且工作正常。但是,对于某些 DataTemplates,我想合并两个 ContextMenues。不幸的是,这似乎不起作用。 以下是其中一个 ContextMenues 的一些代码,其他的定义相同:

<ContextMenu x:Key="CtxIEditableViewModel" DataContext="{Binding PlacementTarget,RelativeSource={RelativeSource Self}}">
    <MenuItem Header="Edit" Command="{Binding Path=DataContext.EditCommand}" CommandParameter="{Binding }">
        <MenuItem.Icon>
            <Image Source="{StaticResource IcoEdit}"  Width="16" Height="16"></Image>
        </MenuItem.Icon>
    </MenuItem>
    ...

使用其中一个 ContextMenues 效果很好:

<StackPanel Orientation="Horizontal" ContextMenu="{StaticResource CtxIEditableViewModel}">

但是如何合并两个呢?这不行

<StackPanel Orientation="Horizontal">
        <ContextMenu>
            <ContextMenu.ItemsSource>
                <CompositeCollection>
                    <StaticResource ResourceKey="CtxIEditableViewModel" />
                    <StaticResource ResourceKey="CtxRootViewModel" />
                </CompositeCollection>
            </ContextMenu.ItemsSource>

这也不起作用:

<StackPanel Orientation="Horizontal">
        <ContextMenu>
            <StaticResource ResourceKey="CtxIEditableViewModel" />
            <StaticResource ResourceKey="CtxRootViewModel" />
        </ContextMenu>

当我运行程序时,会抛出异常,指出上下文菜单可能不包含逻辑或视觉父级。由于如果我只使用一个 ContextMenu 它就可以正常工作,因此我不理解异常消息。

如何在 XAML 中合并这两个 ContextMenues(或者根本不可能)?

wpf xaml contextmenu
1个回答
9
投票

这是一种使用

CompositeCollection

来做到这一点的方法
<Window.Resources>
    <ResourceDictionary>
        <x:Array Type="{x:Type sys:Object}" x:Key="CtxIEditableViewModel" x:Shared="false">
            <MenuItem Header="Edit1"/>
            <MenuItem Header="Edit2"/>
        </x:Array>
        <x:Array Type="{x:Type sys:Object}" x:Key="CtxRootViewModel" x:Shared="false">
            <MenuItem Header="Root1" />
            <MenuItem Header="Root2"/>
        </x:Array>              
    </ResourceDictionary>
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Border Grid.Row="0" Background="LightBlue">
        <Border.ContextMenu>
            <ContextMenu>
                <ContextMenu.ItemsSource>
                    <CompositeCollection>
                        <CollectionContainer Collection="{StaticResource CtxIEditableViewModel}" />                            
                    </CompositeCollection>
                </ContextMenu.ItemsSource>
            </ContextMenu>
        </Border.ContextMenu>
    </Border>
    <Border Grid.Row="1" Background="LightGreen">
        <Border.ContextMenu>
            <ContextMenu>
                <ContextMenu.ItemsSource>
                    <CompositeCollection>                            
                        <CollectionContainer Collection="{StaticResource CtxRootViewModel}" />
                    </CompositeCollection>
                </ContextMenu.ItemsSource>
            </ContextMenu>
        </Border.ContextMenu>
    </Border>
    <Border Grid.Row="2" Background="Khaki">
        <Border.ContextMenu>
            <ContextMenu>
                <ContextMenu.ItemsSource>
                    <CompositeCollection>                            
                        <CollectionContainer Collection="{StaticResource CtxIEditableViewModel}" />
                        <CollectionContainer Collection="{StaticResource CtxRootViewModel}" />
                    </CompositeCollection>
                </ContextMenu.ItemsSource>
            </ContextMenu>

        </Border.ContextMenu>
    </Border>
</Grid>

PS:

x:Shared
很重要,如此处所描述:

x:Shared="false"
的一个场景是,如果您将
FrameworkElement
FrameworkContentElement
派生类定义为资源,然后将元素资源引入到内容模型中。
x:Shared="false"
允许在同一集合中多次引入元素资源(例如
UIElementCollection
)。如果没有
x:Shared="false"
,这是无效的,因为集合强制其内容的唯一性。

© www.soinside.com 2019 - 2024. All rights reserved.