WPF ContextMenu困境:如何设置ContextMenu的DataContext?

Ash*_*non 31 wpf datacontext contextmenu

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

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

我的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>
Run Code Online (Sandbox Code Playgroud)

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

kev*_*aub 44

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>
Run Code Online (Sandbox Code Playgroud)

这篇文章解释了它的工作原理.

  • 是的,我使用 PlacementTarget 获得的 DataContext 级别太深了。我取回了一个项目,但我需要的是具有包含该项目的集合的视图模型。如果我可以绑定到外部控件的 DataContext,那就完美了。 (2认同)

Joh*_*son 16

您可以使用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

它可以让你做到:

<ItemsControl ItemsSource="{Binding Markers}">
   ...
   <ContextMenu DataContext="{Binding DataContext, Source={local:RootObject}}">
      <MenuItem Header="Edit"
                Command="{Binding EditCommand}" />
   </ContextMenu>
   ...
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)

  • 啊呀,星期五,4点,这个有效! (2认同)