WPF文本菜单困境:如何设置的文本菜单的DataContext的?(WPF ContextMenu

2019-07-20 09:23发布

我有一些麻烦搞清楚如何设置正确DataContext上的一个ContextMenu

我有个视图模型谁是一个源的集合ItemsControl 。 每个视图模型这也是另一个源项目的集合ItemsControl 。 每个项目用于绘制,其具有图像ContextMenu 。 该MenuItemsContextMenu需要绑定到视图模型的一个命令,但是PlacementTarget中的ContextMenu所指向的单个项目。

我的XAML看起来是这样的:

<ItemsControl ItemsSource="{Binding Markers"}>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ItemsControl ItemsSource="{Binding Items}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Image>
                            <Image.ContextMenu>
                                <ContextMenu>
                                     <MenuItem Header="Edit" Command="{Binding EditCommand}" />
                                </ContextMenu>
                            </Image.ContextMenu>
                        </Image>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

我如何设置DataContext的的ContextMenu给该项目的相应的父视图模型?

Answer 1:

通过ContextMenu是视觉树之外。 下面是应该让你在DataContext的XAML:

<ItemsControl ItemsSource="{Binding Markers}" Tag="{Binding ElementName=outerControl, Path=DataContext}">
   ...
   <ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
      <MenuItem Header="Edit"
                Command="{Binding EditCommand}" />
   </ContextMenu>
   ...
</ItemsControl>

此帖子解释了如何工作的。



Answer 2:

您可以使用的MarkupExtension:

using System;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Xaml;

[MarkupExtensionReturnType(typeof(ContentControl))]
public class RootObject : MarkupExtension
{
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var rootObjectProvider = (IRootObjectProvider)serviceProvider.GetService(typeof(IRootObjectProvider));
        return rootObjectProvider?.RootObject;
    }
}

它可以让你做的事:

<ItemsControl ItemsSource="{Binding Markers}">
   ...
   <ContextMenu DataContext="{Binding DataContext, Source={local:RootObject}}">
      <MenuItem Header="Edit"
                Command="{Binding EditCommand}" />
   </ContextMenu>
   ...
</ItemsControl>


Answer 3:

我不喜欢使用标签。 我更喜欢附加属性。

您需要添加附加属性:

public static readonly DependencyProperty DataContextExProperty = DependencyProperty.RegisterAttached("DataContextEx", typeof(Object), typeof(DependencyObjectAttached));

    public static Object GetDataContextEx(DependencyObject element)
    {
        return element.GetValue(DataContextExProperty);
    }

    public static void SetDataContextEx(DependencyObject element, Object value)
    {
        element.SetValue(DataContextExProperty, value);
    }

在XAML:

<Button attached:DependencyObjectAttached.DataContextEx="{Binding ElementName=MyDataContextElement, Path=DataContext}">
        <Button.ContextMenu>
            <ContextMenu DataContext="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.(attached:DependencyObjectAttached.DataContextEx)}">

            </ContextMenu>
        </Button.ContextMenu>
    </Button>


文章来源: WPF ContextMenu woes: How do I set the DataContext of the ContextMenu?