2011-07-26 4 views
5

내부에 어떻게의 ContextMenu의 내부에있는 UserControl의 원래의 DataContext를 얻을 수 있습니다.액세스 뷰 모델/DataConext은의 ContextMenu

코드 아래

올바르게 결합하는 DataTemplate을,에 버튼이있는 것을 볼 수 있습니다. 그러나 컨텍스트 메뉴의 데이터 소스를 바인딩 할 때 다음 오류가 나타납니다.

System.Windows.Data 오류 : 4 '참조 원본 RelativeSource FindAncestor, AncestorType ='System.Windows. Controls.TreeView ', AncestorLevel ='1 '. BindingExpression : Path = DataContext; DataItem = null; 대상 요소는 'ContextMenu'(Name = ''); 대상 속성이 'DataContext'('Object'유형)입니다.

ContextMenu를 ViewModel에 바인딩하려면 어떻게해야합니까?

============================================== =================================

뷰 모델은 숨김으로 뷰의 데이터 컨텍스트에 할당 :

보기 :

<TreeView ItemsSource="{Binding Clients}" 
      cmd:TreeViewSelect.Command="{Binding SelectionChangedCommand}" 
      cmd:TreeViewSelect.CommandParameter="{Binding RelativeSource={RelativeSource Self},Path=SelectedItem}"> 
    <TreeView.ItemTemplate> 
     <DataTemplate> 
      <StackPanel> 
       <TextBlock Text="{Binding Name}"> 
        <TextBlock.ContextMenu> 
         <ContextMenu DataContext="{Binding DataContext, 
          RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeView}}}"> 
          <MenuItem Header="{Binding TestString}" /> 
         </ContextMenu> 
        </TextBlock.ContextMenu> 
       </TextBlock> 

       <Button DataContext="{Binding DataContext, 
          RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeView}}}" 
         Content="{Binding TestString}" Command="{Binding EditSelectedClientCommand}" /> 
      </StackPanel> 
     </DataTemplate> 
    </TreeView.ItemTemplate> 
</TreeView> 

뷰 모델 :

public class ClientListViewModel : ViewModelBase 
{ 
    public String TestString { 
     get { 
      return "TESTING"; 
     } 
    } 

    private ClientList _clients = null; 
    private readonly IClientService _clientService = null; 
    private readonly IEventAggregator _eventAggregator = null; 
    private Client _selectedClient = null; 
    private ICommand _selectionChangedCommand = null; 
    private ICommand _editSelectedClientCommand = null; 
    .... 
} 

답변

9

ContextMenus은 여전히 ​​비록 DataContext 어떤 식 으로든를 얻을 수 있습니다, 실패 할 RelativeSource - 바인딩을 일으키는 원인이되는 시각적 트리에 표시되지 않습니다.

<TextBlock Text="{Binding Name}" 
      Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType=TreeView}}"> 
    <TextBlock.ContextMenu> 
     <ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}"> 
      <MenuItem Header="{Binding TestString}" /> 
      <!-- ... ---> 

PlacementTarget

는 TextBlock의, 그리고 DataContextTag 통해 터널링됩니다 : 당신은 예를 들어이 시도 할 수 있습니다. 이 작업을 수행하는 한 가지 방법 (적어도 내가 작동하기를 바랍니다),이 격차를 다르게 연결하는 라이브러리를 보았습니다. 그러나 그들의 기원을 기억하지 못합니다 ...

+0

이 기능은 훌륭했습니다! 고맙습니다! 이 격차를 해소 할 수있는 다른 도서관을 언급했는데 프리즘은 이것들 중 하나가 될까요? –

+0

은 도움이 :) 프리즘이 그 지원이 있는지 모르겠어요 다행이, 난 그냥 다시 주위를 둘러 보았다 및 [이] (http://www.codeproject.com/KB/WPF/AttachingVirtualBranches.aspx) 중 하나가 될 것입니다 그 라이브러리는 내가 처음에 건너 왔지만 실제로 사용하지 않는다고 생각할 때이 시나리오에서 작동하는지 모르겠습니다. 그러나 나는 꽤 오래 전에 [DataContextSpy] (http://www.codeproject.com/KB/WPF/ArtificialInheritanceCxt.aspx)라고 불리는 다른 것을 시험해 보았습니다. 그러나 그것은 나에게 많은 도움이되지 못했을 것입니다. 잘못 입력했을 수도 있습니다. ... –

+0

태그 속성은 제가 누락 된 것입니다! 고맙습니다! –