2013-02-22 62 views
20

我在計算如何在ContextMenu上設置正確的DataContext時遇到了一些問題。WPF ContextMenu困境:如何設置ContextMenu的DataContext?

我有一組視圖模型誰是ItemsControl的來源。每個視圖模型都有一個項目集合,這些項目也是另一個ItemsControl的來源。每個項目用於繪製具有ContextMenu的圖像。該 ContextMenu需要綁定到視圖模型上的命令,但ContextMenuPlacementTarget指向單個項目。

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

如何設置的ContextMenuDataContext該項目的相應父視圖模式?

回答

35

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

這個是我不想綁定到PlacementTarget是什麼問題。我想綁定到外部控件的DataContext。 – 2013-02-22 21:48:45

+0

你確定它們沒有相同的DataContext(即outerControl和inner itemsControl)嗎? – kevindaub 2013-02-22 21:51:08

+0

是的,我使用PlacementTarget獲得的DataContext是一個太深的級別。我找回了一個項目,但我需要的是具有包含該項目的集合的視圖模型。如果我可以綁定到外部控件的DataContext,那將是完美的。 – 2013-02-22 21:55:06

8

可以使用的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> 
+1

啊,是啊,星期五,4點,這個工程! – grunge 2016-03-24 14:50:22

2

我不喜歡使用標籤。我更喜歡附屬的財產。

您需要添加附加屬性:

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>