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. MenuItemsContextMenu besoin de se lier à une commande sur le modèle de vue, mais PlacementTargetContextMenu 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 DataContextContextMenu au modèle de vue parent correspondant de l'article?

21
demandé sur Ashley Grenon 2013-02-23 01:30:24

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.

37
répondu kevindaub 2013-02-22 22:13:58

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>
9
répondu Johan Larsson 2015-11-02 20:08:18

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>
2
répondu Smagin Alexey 2016-07-19 10:49:51