2013-02-22 17 views
20

Mam problem z ustaleniem poprawnego DataContext na ContextMenu.WPO ContextMenu Woes: Jak ustawić DataContext w ContextMenu?

Mam kolekcję modeli widoków, które są źródłem ItemsControl. Każdy model widoku ma kolekcję przedmiotów, które są również źródłem innego ItemsControl. Każdy element służy do rysowania obrazu o numerze ContextMenu. MenuItems w tym ContextMenu trzeba powiązać z poleceniem w modelu widoku, ale PlacementTarget z ContextMenu wskazuje na pojedynczą pozycję.

My Xaml wygląda mniej więcej tak:

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

Jak mogę ustawić DataContext z ContextMenu do odpowiedniego widoku modelu nadrzędnego danego elementu?

Odpowiedz

35

Menu kontekstowe znajduje się poza graficznym drzewem. Poniżej znajduje się XAML, który powinien Ci 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> 

Ten post wyjaśnia, jak to działa.

+1

Problem polega na tym, że nie chcą wiązać się co PlacementTarget jest. Chcę powiązać z DataContext zewnętrznej kontroli. –

+0

Czy jesteś pewien, że nie mają tego samego Kontekstu danych (tj. OuterControl i inner itemsControl)? – kevindaub

+0

Tak, DataContext, który uzyskuję za pomocą PlacementTarget, jest zbyt głęboki. Odzyskuję element, ale potrzebuję modelu widoku, który ma kolekcję zawierającą ten element. Gdybym mógł powiązać Kontekst danych zewnętrznej kontroli, byłoby to idealne. –

8

Można użyć 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; 
    } 
} 

To pozwala zrobić:

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

Ah Tak, piątek, 4 godzina i to działa! – grunge

2

Nie lubię użycia Tag. Wolę przywiązaną własność.

Trzeba dodać załączony właściwość:

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

w 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> 
Powiązane problemy