TreeViewItem 上的键绑定

发布于 2024-09-07 16:46:12 字数 1381 浏览 9 评论 0原文

我有一个典型的树视图和视图模型。视图模型具有其他视图模型的可观察集合,用作树的数据源。

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

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

视图:

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

但是,无论我尝试什么,只要它位于 HierarchicalDataTemplate“内部”,我的命令都不会被调用。

如果我将 TreeView.InputBindings 中的 KeyBinding(以及 ICommand / RelayCommand 从 ItemVM 移动到 TreeViewVM),一切都很好,命令将被调用。

但我希望在 ItemVM 上使用该命令(因为这是有意义的)。有什么想法吗?

I have a typical treeview and a viewmodel. The viewmodel has an observable collection of other viewmodels that serves as a data source for the tree.

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

and the 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; }
}

The view :

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

However my command will not be invoked no matter what I try as long as it is "inside" the HierarchicalDataTemplate.

If I move the KeyBinding in the TreeView.InputBindings (and the ICommand / RelayCommand from the ItemVM to the TreeViewVM) all is nice, the command gets invoked.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

攒眉千度 2024-09-14 16:46:24

需要在 TreeViewItem 上定义键绑定,因为它是具有焦点的元素。问题是您无法使用样式定义键绑定,而这正是您可能想要在此处执行的操作。

这里是一种使用自定义附加属性将项目添加到 InputBinding 的解决方法通过样式收集。因此,您需要使用类似的东西来定义您的样式,并将其分配给 TreeView.ItemContainerStyle。

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.

熟人话多 2024-09-14 16:46:22

但我希望在 ItemVM 上使用该命令(因为这是有意义的)。有什么想法吗?

如果 TreeViewVM 通过 SelectedItem 属性跟踪所选项目,您可以在 TreeView 上定义 InputBindings 并且仍然可以实现命令在 ItemVM 上:

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

请注意如何使用子属性语法 SelectedItem.RenameItemVM 用作绑定源。

不幸的是,绑定到 TreeView 上的所选项目有点乏味。您无法直接绑定到 SelectedItem (正如您的 XAML 似乎建议的那样),但存在 有多种方法可以克服此限制

一种简单的方法是使用 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>

您必须实现 TreeViewVM 上的 SetSeletectedItemCommand,用于设置属性 SelectedItem

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文