C# 如何在wpf中的层次数据模板中显示treeview项的上下文菜单
如何使用分层数据模板在wpf中显示树状视图项的上下文菜单?如何仅显示CountryTemplate的关联菜单:C# 如何在wpf中的层次数据模板中显示treeview项的上下文菜单,c#,wpf,treeview,contextmenu,C#,Wpf,Treeview,Contextmenu,如何使用分层数据模板在wpf中显示树状视图项的上下文菜单?如何仅显示CountryTemplate的关联菜单: <HierarchicalDataTemplate x:Key="DispTemplate"> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Path=Label}" Style="{StaticResource TreeText
<HierarchicalDataTemplate x:Key="DispTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Label}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}" Tag="{Binding Path=Tag}">
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="BuildingTemplate" ItemsSource="{Binding Path=Building}" ItemTemplate="{StaticResource BuildingTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Label}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="CityTemplate" ItemsSource="{Binding Path=City}" ItemTemplate="{StaticResource CityTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Label}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="CountryTemplate" ItemsSource="{Binding Path=Country}" ItemTemplate="{StaticResource CountryTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=RootName}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}"/>
</StackPanel>
</HierarchicalDataTemplate>
如您所见,您可以在HierarchycalDataTemplate的Itemcontainerstyle中添加contextmenu,也可以将contextmenu添加到数据模板中的任何可视子级,例如:
<HierarchicalDataTemplate x:Key="CountryTemplate" ItemsSource="{Binding Path=Country}" ItemTemplate="{StaticResource CountryTemplate}">
<StackPanel Orientation="Horizontal">
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="Header" Command="{Binding Command}"/> <!--This command should be in the data context (each country item)-->
</ContextMenu>
</StackPanel.ContextMenu>
<TextBlock Text="{Binding Path=RootName}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}"/>
</StackPanel>
</HierarchicalDataTemplate>
基本上我想到了这个
<HierarchicalDataTemplate x:Key="ChildTemplate">
<StackPanel Orientation="Horizontal">
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="Copy" CommandParameter="{Binding CopyTag}">
</MenuItem>
<MenuItem Header="Paste" CommandParameter="{Binding PasteTag}">
</MenuItem>
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.CopyPaste}"/>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</StackPanel.ContextMenu>
<Image Source="/Images/Child.png" Stretch="None" VerticalAlignment="Center" HorizontalAlignment="Center" Style="{StaticResource TreeIconStyle}"/>
<TextBlock Text="{Binding Path=Label}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}" Tag="{Binding Path=Tag}">
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
并且具有用于复制和粘贴的单独参数,以便在单个命令中区分复制和粘贴。上下文菜单不能尽可能干净地工作的原因之一是,默认情况下,它们位于与其他所有内容不同的视觉树中,因此无法找到
数据上下文
关键是创建一个定义上下文菜单的
,
然后将该样式附加到目标元素,该元素将连接上下文
菜单。这会将上下文菜单移动到一个可视化树中,该树与所需的默认DataContext
对齐
首先,创建样式:
<UserControl.Resources>
<ResourceDictionary>
<!-- For the context menu to work, we must shift it into a style, which means that the context menu is now in a
visual tree that is more closely related to the current data context. All we have to do then is set the style,
which hooks up the context menu. -->
<Style x:Key="ContextMenuStyle" TargetType="{x:Type StackPanel}">
<Setter Property="ContextMenu" Value="{DynamicResource TreeViewContextMenu}"/>
</Style>
<ContextMenu x:Key="TreeViewContextMenu">
<MenuItem Header="Test" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.CmdDisplayDetailsGraph}"/>
</ContextMenu>
然后,将上下文菜单连接到任何您想要的位置,而不会遇到由不同的视觉树引起的问题
例1:
<HierarchicalDataTemplate DataType="{x:Type snapshot:Details}" ItemsSource="{Binding DetailsList}">
<StackPanel Orientation="Vertical" Style="{StaticResource ContextMenuStyle}">
<ContentPresenter Content="{Binding}" ContentTemplate="{Binding View.DefaultDataRowTemplate}" />
</StackPanel>
例2:
<DataTemplate DataType="{x:Type snapshot:InstrumentDetails}">
<StackPanel Orientation="Vertical" Style="{StaticResource ContextMenuStyle}">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Center">
如何绑定到viewmodel根目录中定义的命令。到目前为止,FindAncestor方法不起作用。你能给我举个例子吗?在我无法轻松访问视图模型进行绑定的情况下,我尝试使用这个findancestorbinding:Command=“{binding DataContext.Command,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type MainWindow}}”,通常主窗口的DataContext具有根视图模型,还有您需要的命令。由于某些原因,上下文菜单不起作用,因为它不是可视化树的一部分。是的,您是对的,那么您应该从视图模型中发出该命令。可能使用一种消息(mvvm light或您自己实现的)或为所有视图模型层次结构引发事件,这是一种复杂的方法。是的,即使是像XAML这样的小事情也是一种痛苦。我必须想出一些超乎寻常的解决方案。这对我来说非常有效,而且,我喜欢在项目附近定义ContextMenu。这对我来说非常有效。为了避免编译错误,我必须交换块(确保XAML标记HierarchycalDataTemplate
位于Style
和ContextMenu
标记之后)。它之所以能够工作,是因为将ContextMenu转换为样式将所有内容转换为一个更密切相关的可视树,这意味着可以毫不费力地找到DataContext。
<DataTemplate DataType="{x:Type snapshot:InstrumentDetails}">
<StackPanel Orientation="Vertical" Style="{StaticResource ContextMenuStyle}">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Center">