【问题标题】:How to display context menu for treeview item in a hierarchial data template in wpf如何在 wpf 的分层数据模板中显示树视图项的上下文菜单
【发布时间】:2012-11-05 10:31:17
【问题描述】:

如何使用分层数据模板在 wpf 中显示树视图项的上下文菜单?如何仅为 CountryTemplate 显示上下文菜单:

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

【问题讨论】:

    标签: c# wpf treeview contextmenu


    【解决方案1】:

    您还可以将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>
    

    【讨论】:

    • 如何绑定到视图模型根目录中定义的命令。到目前为止 FindAncestor 方法不起作用。你能给我举个例子吗?
    • 在我无法轻松访问视图模型以进行绑定的情况下,我尝试使用此 FindAncestor 绑定:Command="{Binding DataContext.Command, RelativeSource={RelativeSource FindAncestor, AncestorType={ x:Type MainWindow}}}",一般主窗口的datacontext有根视图模型,有你想要的命令。
    • 这不适用于上下文菜单,因为它不是可视化树的一部分。
    • 是的,你是对的,那么你应该从你的视图模型中发出命令。也许使用一种消息(mvvm light 或由您自己实现)或为您的所有视图模型层次结构引发事件,这是一种复杂的方式。
    • 是的,即使是像这样的小东西 XAML 也是一个真正的痛苦。我必须想出超出正常范围的解决方案。
    【解决方案2】:

    上下文菜单无法正常工作的原因之一是,默认情况下,它们位于与其他所有内容不同的可视化树中,因此无法找到 DataContext

    关键的见解是创建一个定义上下文菜单的&lt;Style&gt;, 然后将该样式附加到目标元素,该元素连接上下文 菜单。 这会将上下文菜单转换为一个可视树,该树与您想要的默认 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">
    

    【讨论】:

      【解决方案3】:
      <HierarchicalDataTemplate x:Key="CountryTemplate" ItemsSource="{Binding Path=Country}" ItemContainerStyle="{StaticResource CountryTemplateItemContainerStyle}" ItemTemplate="{StaticResource CountryTemplate}">
                              <StackPanel Orientation="Horizontal">
                                  <TextBlock Text="{Binding Path=RootName}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}" />
                              </StackPanel>
      </HierarchicalDataTemplate>
      
      
      <Style x:Key="CountryTemplateItemContainerStyle" TargetType="{x:Type TreeViewItem}">
      <Setter Property="ContextMenu" Value="{DynamicResource TreeViewContextMenu}"/>
      </Style>
       <ContextMenu x:Key="TreeViewContextMenu">
              <MenuItem .../>
       </ContextMenu>
      

      如您所见,您可以在 HierarchicalDataTemplate 的 Itemcontainerstyle 中添加上下文菜单

      【讨论】:

      • 这对我来说非常有用,而且,我喜欢 ContextMenu 是如何在项目附近定义的。
      • 这对我有用。为了避免编译错误,我不得不交换块(确保 XAML 标记 HierarchicalDataTemplateStyleContextMenu 标记之后)。它起作用的原因是因为将 ContextMenu 转换为样式会将所有内容转换为更密切相关的可视化树,这意味着可以轻松找到 DataContext。
      【解决方案4】:

      基本上我想出了这个

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

      并具有单独的复制和粘贴参数,以区分单个命令中的复制和粘贴。

      【讨论】:

        猜你喜欢
        • 2017-02-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-28
        • 2018-09-12
        • 1970-01-01
        • 2016-03-05
        相关资源
        最近更新 更多