我在查明如何在DataContext
上设置正确的ContextMenu
时遇到了一些麻烦。
我有一组视图模型,它们是ItemsControl
的来源。每个视图模型都有一组项目,这些项目也是另一个ItemsControl
的来源。每个项目用于绘制具有ContextMenu
的图像。 MenuItems
中的ContextMenu
需要绑定到视图模型上的命令,但PlacementTarget
的{{1}}指向单个项目。
我的Xaml看起来像这样:
ContextMenu
如何将<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>
的{{1}}设置为项目的相应父视图模型?
答案 0 :(得分:39)
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>
这post解释了这是如何运作的。
答案 1 :(得分:15)
您可以使用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>
答案 2 :(得分:2)
我不喜欢使用Tag。我更喜欢附属物。
您需要添加附加属性:
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>
答案 3 :(得分:0)
此代码允许您同时使用全局和本地DataContext(用于整个userControl和当前TreeViewItem):
<TreeView Grid.Row="0" ItemsSource="{Binding Path=SelectableEnterprises}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<Grid Height="20" Tag="{Binding DataContext, ElementName=userControl}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="25"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}" >
<ContextMenu.Visibility>
<MultiBinding Converter="{converters:SurveyReportVisibilityConverter}">
<Binding Path="DataContext"/> <!--local DataContext-->
<Binding Path="Tag.SelectedSurvey"/> <!--global DataContext-->
</MultiBinding>
</ContextMenu.Visibility>
<MenuItem Header="Show HTML-report" Command ="{Binding Tag.OpenHTMLReportCommand}"
CommandParameter="{Binding DataContext}" />
</ContextMenu>
</Grid.ContextMenu>