Frage

habe ich eine typische treeview und ein Ansichtsmodell. Das Ansichtsmodell hat eine beobachtbare Sammlung anderer Viewmodel, das für den Baum als Datenquelle dient.

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

und die 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; }
}

Die Aussicht:

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

Allerdings wird mein Befehl nicht egal aufgerufen werden, was ich versuche, so lange, wie es ist „innen“ die HierarchicalDataTemplate.

Wenn ich das KeyBinding in dem TreeView.InputBindings (und das ICommand / RelayCommand vom ItemVM zum TreeViewVM) bewege alles schön ist, wird der Befehl aufgerufen wird.

Aber ich möchte den Befehl auf dem ItemVM haben (wie es ist, wo es Sinn macht). Irgendwelche Ideen?

War es hilfreich?

Lösung

The key binding would need to be defined on the TreeViewItem, as that is the element with the focus. The problem is you cannot define key bindings using a Style, which is what you'd probably want to do here.

Here is one workaround that uses a custom attached property to add items to the InputBinding collection via a Style. So you'd want to use something like that to define your Style, which you'd assign to TreeView.ItemContainerStyle.

Andere Tipps

But I would like to have the command on the ItemVM (as it is where it makes sense). Any ideas?

If TreeViewVM tracks the selected item through the SelectedItem property you can define InputBindings on TreeView and still have the commands implemented on the ItemVM:

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

Notice how the subproperty syntax SelectedItem.Rename is employed to use the ItemVM as the source of the binding.

Unfortunately, it is slightly tedious to bind to the selected item on a TreeView. You cannot bind directly to SelectedItem (as your XAML seems to suggest) but there exist various methods to overcome this limitation.

One simple method is to use Blend Interactivity:

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

You will have to implement a SetSeletectedItemCommand on TreeViewVM that sets the property SelectedItem.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top