WPF ContextMenu 问题:如何设置 ContextMenu 的 DataContext?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15033522/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 23:41:33  来源:igfitidea点击:

WPF ContextMenu woes: How do I set the DataContext of the ContextMenu?

wpfcontextmenudatacontext

提问by Ashley Grenon

I am having some trouble figuring out how to set the correct DataContexton a ContextMenu.

我在弄清楚如何DataContextContextMenu.

I have a collection of view models who are the source of an ItemsControl. Each view model has a collection of items which are also the source of another ItemsControl. Each item is used to draw image which has a ContextMenu. The MenuItemsin that ContextMenuneed to bind to a command on the view model, but the PlacementTargetof the ContextMenuis pointing to the individual item.

我有一组视图模型,它们是ItemsControl. 每个视图模型都有一个项目的集合,这些项目也是另一个ItemsControl. 每个项目用于绘制具有ContextMenu. 将MenuItemsContextMenu需要绑定到视图模型的一个命令,但是PlacementTargetContextMenu是指向单个项目。

My Xaml looks something like this:

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

How can I set the DataContextof the ContextMenuto the item's corresponding parent view model?

我如何设置DataContextContextMenu,以该项目的相应父视图模式?

回答by kevindaub

The ContextMenu is outside of the visual tree. Below is the xaml that should get you the datacontext:

ContextMenu 在可视化树之外。下面是应该为您提供数据上下文的 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>

This postexplains how this works.

这篇文章解释了这是如何工作的。

回答by Johan Larsson

You can use a 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;
    }
}

It lets you do:

它可以让你:

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

回答by Smagin Alexey

I don't like use Tag. I prefer attached property.

我不喜欢使用标签。我更喜欢附加财产。

You need add attached property:

您需要添加附加属性:

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);
}

In XAML:

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