2011-07-26 31 views
5

Làm thế nào tôi có thể lấy được DataContext gốc của UserControl bên trong ContextMenu.Access ViewModel/DataConext bên trong ContextMenu

Mã bên dưới, bạn có thể thấy rằng có một Nút trong DataTemplate, liên kết chính xác. Tuy nhiên, khi cố gắng ràng buộc nguồn dữ liệu của contextmenu, tôi nhận được lỗi sau:

System.Windows.Data Lỗi: 4: Không thể tìm nguồn để ràng buộc với tham chiếu 'RelativeSource FindAncestor, AncestorType =' System.Windows. Controls.TreeView ', AncestorLevel =' 1 ''. BindingExpression: Đường dẫn = DataContext; DataItem = null; phần tử đích là 'ContextMenu' (Tên = ''); thuộc tính đích là 'DataContext' (loại 'Đối tượng')

Tôi cần làm gì để cho phép ContextMenu liên kết với ViewModel?

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

ViewModel được gán cho văn bản dữ liệu của chế độ xem trong codebehind :

Xem:

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

ViewModel:

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

Trả lời

9

ContextMenus không xuất hiện trong cây trực quan khiến cho RelativeSource-bindings thất bại, bạn vẫn có thể nhận được DataContext theo cách này hay cách khác. Bạn có thể thử này ví dụ:

<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}" /> 
      <!-- ... ---> 

Các PlacementTarget là TextBlock và DataContext được tạo đường hầm qua Tag. Chỉ cần một cách để làm điều này (ít nhất tôi hy vọng nó hoạt động), tôi cũng đã thấy một số thư viện mà cầu khoảng cách này khác nhau nhưng tôi không nhớ nguồn gốc của họ ...

+0

Điều này làm việc tuyệt vời! Cảm ơn bạn! Bạn đã đề cập đến các thư viện khác có thể thu hẹp khoảng cách này, liệu Prism có phải là một trong những thư viện này không? –

+0

Vui vì nó đã giúp :) Tôi không biết nếu Prism có hỗ trợ cho điều đó, tôi chỉ cần nhìn xung quanh một lần nữa và [this] (http://www.codeproject.com/KB/WPF/AttachingVirtualBranches.aspx) sẽ là một trong những thư viện tôi đã đi qua trước đó nhưng tôi không biết nếu nó sẽ làm việc trong kịch bản này như tôi nghĩ rằng tôi không bao giờ thực sự sử dụng nó. Tuy nhiên tôi đã thử một thứ gọi là [DataContextSpy] (http://www.codeproject.com/KB/WPF/ArtificialInheritanceCxt.aspx) khá lâu trước đây nhưng nó không được sử dụng nhiều cho tôi, có lẽ tôi đã áp dụng nó sai. ... –

+0

Thuộc tính Thẻ là những gì tôi đã bỏ lỡ! Cảm ơn bạn! –

Các vấn đề liên quan