2013-02-22 3 views
20

ContextMenu에 올바른 DataContext을 설정하는 방법을 알아 내는데 문제가 있습니다.WPF ContextMenu Woes : 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는 시각적 트리 외부에 있습니다. 이것이 어떻게 작동하는지

<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는 설명 : 다음은 당신에게 데이터 컨텍스트를 취득해야하는 XAML입니다. 그것은 당신이 할 수 있습니다

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

이 내가 PlacementTarget이 무엇인지에 바인딩하지 않을 것입니다 함께 문제. 외부 컨트롤의 DataContext에 바인딩하고 싶습니다. –

+0

그들은 동일한 DataContext (즉, outerControl 및 내부 itemsControl)를 가지고 있지 않습니까? – kevindaub

+0

예, PlacementTarget을 사용하여 얻은 DataContext는 너무 깊은 수준입니다. 항목을 다시 가져 오지만 필요한 항목은 해당 항목이 포함 된 컬렉션이있는보기 모델입니다. 외부 컨트롤의 DataContext에 바인딩 할 수 있다면 완벽 할 것입니다. –

8

당신은 markupextension를 사용할 수 있습니다. 나는 첨부 된 속성을 선호합니다.

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

아아 그래, 금요일, 4 시가이 작품! – grunge

2

내가 사용 태그를 좋아하지 않는다