2011-07-26 701 views
5

¿Cómo puedo obtener el DataContext original del UserControl dentro de un ContextMenu?Acceso a ViewModel/DataConext dentro de ContextMenu

El siguiente código, puede ver que hay un botón en el DataTemplate, que se une correctamente. Sin embargo, cuando se trata de obligar a la fuente de datos del menú contextual, que recibo el siguiente error:

System.Windows.Data error: 4: No se puede encontrar la fuente para la unión con referencia 'RelativeSource FindAncestor, AncestorType =' System.Windows. Controls.TreeView ', AncestorLevel =' 1 ''. BindingExpression: Path = DataContext; DataItem = null; el elemento objetivo es 'ContextMenu' (Name = ''); propiedad de destino es 'DataContext' (tipo 'Objeto')

¿Qué debo hacer para permitir que el ContextMenu se vincule al ViewModel?

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

El ViewModel se asigna al contexto de datos de la vista en el código subyacente :

Vista:

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

modelo de vista:

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

Respuesta

9

ContextMenus no aparece en el árbol visual que hace que las vinculaciones de RelativeSource fallen, aún así puede obtener el DataContext de una forma u otra. Usted podría intentar esto, por ejemplo:

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

El PlacementTarget es el TextBlock, y el DataContext forma un túnel a través de la Tag. Solo una forma de hacerlo (al menos espero que funcione), también he visto algunas bibliotecas que cubren esta brecha de manera diferente, pero no recuerdo su origen ...

+0

¡Esto funcionó muy bien! ¡Gracias! Mencionaste otras bibliotecas que podrían cerrar esta brecha, ¿Prism sería uno de estos? –

+0

Me alegro de que haya ayudado :) No sé si Prism tiene soporte para eso, solo volví a mirar alrededor y [este] (http://www.codeproject.com/KB/WPF/AttachingVirtualBranches.aspx) sería uno de aquellas bibliotecas que he encontrado anteriormente, pero no sé si funcionaría en este escenario, ya que creo que nunca lo usé realmente. Sin embargo, probé hace mucho tiempo otra cosa llamada [DataContextSpy] (http://www.codeproject.com/KB/WPF/ArtificialInheritanceCxt.aspx) pero no me sirvió de mucho, tal vez la apliqué incorrectamente. ... –

+0

¡La propiedad Tag es lo que me faltaba! ¡Gracias! –

Cuestiones relacionadas