2010-06-29 16 views
7

Tengo una vista de árbol típica y un modelo de vista. El modelo de vista tiene una colección observable de otros modelos de vista que sirven como fuente de datos para el árbol.KeyBinding en TreeViewItem

public class TreeViewVM { 
    public ObservableCollection<ItemVM> Items { get; private set; } 
    public ItemVM SelectedItem { get; set; } 
} 

y la ItemVM:

public class ItemVM { 
    public string Name { get; set; } 
    public ImageSource Image { get; private set; } 
    public ObservableCollection<ItemVM> Children { get; private set; } 
    public ICommand Rename { get; private set; } 
} 

La vista:

<TreeView Selecteditem="{Binding SelectedItem}" ItemsSource="{Binding Items}"> 
    <TreeView.ItemTemplate> 
     <HierarchicalDataTemplate> 
      <StackPanel Orientation="Horizontal"> 
       <StackPanel.InputBindings> 
        <KeyBinding Key="F2" Command="{Binding Rename}"/> 
       </StackPanel.InputBindings> 
       <Image Source="{Binding Image}"/> 
       <TextBlock Text="{Binding Name}"/> 
     </HierarchicalDataTemplate> 
     </TreeView.ItemTemplate> 
    </TreeView> 

Sin embargo, mi comando no será invocado no importa lo que intente, siempre y cuando se trata de "dentro" de la HierarchicalDataTemplate .

Si muevo el KeyBinding en TreeView.InputBindings (y el ICommand/RelayCommand desde el ItemVM al TreeViewVM) todo está bien, el comando se invoca.

Pero me gustaría tener el comando en el ItemVM (ya que es donde tiene sentido). ¿Algunas ideas?

Respuesta

5

El enlace de clave debería definirse en TreeViewItem, ya que ese es el elemento con el foco. El problema es que no puede definir enlaces de teclas usando un Estilo, que es lo que probablemente quiera hacer aquí.

Here es una solución que utiliza una propiedad adjunta personalizada para agregar elementos a la colección InputBinding mediante un estilo. Entonces, querrá usar algo así para definir su Estilo, que asignaría a TreeView.ItemContainerStyle.

7

Pero me gustaría tener el comando en el ItemVM (ya que es donde tiene sentido). ¿Algunas ideas?

Si TreeViewVM pistas del elemento seleccionado a través de la propiedad SelectedItem puede definir InputBindings en TreeView y todavía tienen los comandos implementados en el ItemVM:

<TreeView ItemsSource="{Binding Items}"> 
    <TreeView.InputBindings> 
    <KeyBinding Key="F2" Command="{Binding SelectedItem.Rename}"/> 
    </TreeView.InputBindings> 
</TreeView> 

Observe cómo se emplea la sintaxis subpropiedad SelectedItem.Rename utilizar el ItemVM como la fuente del enlace.

Lamentablemente, es un poco tedioso enlazar con el elemento seleccionado en un TreeView. No puede enlazar directamente al SelectedItem (como su XAML parece sugerir) pero existe various methods to overcome this limitation. Un método simple que me gusta es utilizar Blend Interativity:

<TreeView Name="treeView" ItemsSource="{Binding Items}"> 
    <i:Interaction.Triggers> 
    <i:EventTrigger EventName="SelectedItemChanged"> 
     <i:InvokeCommandAction Command="{Binding SetSelectedItemCommand}" CommandParameter="{Binding SelectedItem, ElementName=treeView}" /> 
    </i:EventTrigger> 
    </i:Interaction.Triggers> 
</TreeView> 

que tendrá que implementar un SetSeletectedItemCommand en TreeViewVM que establece la propiedad SelectedItem.

+0

Bueno, gracias! –

+0

Esto funcionó muy bien para mí. Gracias por señalar ** SelectedItem **. Renombrar. –

+0

@MartinLiversage, por favor, consulte mi pregunta http://stackoverflow.com/questions/36865204/keybinding-in-hierarchicaldatatemplate-of-treeview – StepUp

Cuestiones relacionadas