WPF ContextMenu woes: comment définir le DataContext du ContextMenu?
j'ai du mal à trouver comment régler le bon DataContext
sur un ContextMenu
.
j'ai une collection de modèles de vue qui sont à la source d'un ItemsControl
. Chaque modèle de vue a une collection d'éléments qui sont aussi la source d'un autre ItemsControl
. Chaque élément est utilisé pour dessiner une image qui a un ContextMenu
. MenuItems
ContextMenu
besoin de se lier à une commande sur le modèle de vue, mais PlacementTarget
ContextMenu
pointe vers l'élément individuel.
mon Xaml ressemble à quelque chose comme ceci:
<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>
comment définir le DataContext
ContextMenu
au modèle de vue parent correspondant de l'article?
3 réponses
Le ContextMenu est en dehors de l'arbre visuel. Ci-dessous se trouve le XAML qui devrait vous fournir le datacontext:
<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 explique comment cela fonctionne.
Vous pouvez utiliser un 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;
}
}
Il vous permet de faire:
<ItemsControl ItemsSource="{Binding Markers}">
...
<ContextMenu DataContext="{Binding DataContext, Source={local:RootObject}}">
<MenuItem Header="Edit"
Command="{Binding EditCommand}" />
</ContextMenu>
...
</ItemsControl>
je n'aime pas utiliser la Balise. Je préfère la propriété attenante.
vous devez ajouter la propriété attachée:
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:
<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>