为了简化我遇到的问题,请考虑这个假设情景。
在我控制的XAML中,我定义了一个TreeView
和两个固定的根TreeViewItem
节点,'AItemsNode'和'BItemsNode'。在它的ViewModel中,我公开了两个子集合:AItems和BItems。然后,我将每个根节点的ItemsSource属性绑定到ViewModel上的相应集合。这很有效,可以准确显示我想要的内容。
现在我要做的是将ApplicationCommands.Open的CommandBinding添加到两个根节点的子 TreeViewItem节点。具体来说,我希望根'AItemsNode'下的子项将'Open'CommandBinding指向'OpenAItem_Executed',将第二个根节点的子节点指向'OpenBItem_Executed'。
我遇到的问题是我不知道如何在TreeViewItem对象上设置CommandBindings。我无法通过XAML解决这个问题,如果我要在代码隐藏中完成它,我必须与ItemContainerGenerator集成,检查生成的内容并添加绑定,基本上写了这么多代码我也可以将'Open'CommandBinding添加到TreeView本身并检查SelectedObject并从那里开始。不是最优的,因为我现在有一个Open_Executed处理程序,它根据数据类型委托所有地方,但它确实有效!
尽管如此,我希望有人可以告诉我如何将CommandBinding直接添加到生成的TreeViewItem中以避免这种情况并更清晰地分离出代码。
那么......如何通过样式(或XAML中的任何其他方式)为TreeViewItem应用特定的CommandBindings?
答案 0 :(得分:0)
我认为你没有实施MVVM
(通过使用RelayCommands
/ DelegateCommands
代替RoutedCommands
来直观地解决了这个问题)
但是,在您的情况下,您需要通过Initialized
来TreeViewItem
处理Style
TreeViewItem
事件。在EventSetter
中使用Style
。并将代码添加CommandBinding
到e.OriginalSource
值(即已初始化的TreeViewItem
本身)传入TreeViewItem.Initialized
事件处理程序。
让我知道这是否有意义。
修改强>
据我所知,你有x个不同TreeViewItems
的x个keyborad快捷键。如果是这样的话,x的样式对我来说很有意义。
但是如果你想在树视图级别的单个处理程序中混乱,那么你可能需要处理该级别的附加事件...我不认为Initialised
/ {{1从indv treeviewitem到父树视图的事件气泡,但检查一下会很有趣,我很乐意证明它是错误的!
另外,这可能对折叠的树视图项无效。
因此,假设您为折叠树分支内的特定树视图项定义“Ctrl + o”快捷方式,或者它位于打开的分支中,但它位于滚动视图之外,基于路由事件的机制(因此命令)因为他们需要将项目虚拟化(在UI内存中)以便路由工作,所以工作得很好...
所以我的解决方案(正如我现在所理解的)在这种情况下变得有点不切实际。
<强>解决方案强>
什么时候一直可见?
的TreeView!
所以尽量利用它。将所有命令绑定(和快捷方式)添加到TreeView本身!
在处理程序中(可能在所有命令绑定中都是通用的)设计一种机制,通过在Loaded
内ItemsSource
进行搜索来识别单个项目,然后在相关的{{1}内搜索通过通用样式通过绑定TreeViewItemViewModels
属性(INotifyable)到TreeViewItemViewModel
的{{1}}属性来Open
branch hierarchy
机制。
答案 1 :(得分:0)
实施mvvm,我建议使用交互触发器。
希望这能帮助你朝着正确的方向前进。
的Xaml:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
<TreeView >
<TreeView.Resources>
<DataTemplate x:Key="ItemATemplate">
<TextBlock Text="{Binding MyNodeTitle}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseDown">
<i:InvokeCommandAction Command="{Binding AChildCommand}" CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</DataTemplate>
<DataTemplate x:Key="ItemBTemplate">
<TextBlock Text="{Binding MyNodeTitle}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseDown">
<i:InvokeCommandAction Command="{Binding BChildCommand}" CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</DataTemplate>
</TreeView.Resources>
<TreeView.Items>
<TreeViewItem Header="AItemRootNode" ItemsSource="{Binding SomeAStuff}" ItemTemplate="{StaticResource ItemATemplate}"/>
<TreeViewItem Header="BItemRootNode" ItemsSource="{Binding SomeBStuff}" ItemTemplate="{StaticResource ItemBTemplate}"/>
</TreeView.Items>
</TreeView>
视图模型:
private ICommand _aChildCommand;
public ICommand AChildCommand
{
get
{
if (_aChildCommand == null)
_aChildCommand = new DelegateCommand(OnAChild);
return _aChildCommand;
}
}
private void OnAChild(object obj)
{
}