【问题标题】:Highlight custom DataTemplate in TreeView在 TreeView 中突出显示自定义 DataTemplate
【发布时间】:2016-10-05 16:58:01
【问题描述】:

我有一个简单的TreeView,我正在尝试为它创建一个自定义DataTemplate。它按需要显示,但是当我尝试选择TreeViewItem 时,如果单击TreeView 中的文本,突出显示将不起作用。但是,如果我只选择文本的左侧,它会起作用:

来源非常简单,所以我猜我只是缺少样式连接:

xaml

   <TreeView x:Name="treeView"
             ItemsSource="{Binding TreeViewItems}"
             Grid.Row="0">
      <TreeView.ItemTemplate>
         <HierarchicalDataTemplate ItemsSource="{Binding Path=MenuItems}">
            <TreeViewItem Header="{Binding Header}">
               <TreeViewItem.InputBindings>
                  <MouseBinding MouseAction="LeftClick"
                                Command="{Binding Command}" />
               </TreeViewItem.InputBindings>
            </TreeViewItem>
         </HierarchicalDataTemplate>
      </TreeView.ItemTemplate>
   </TreeView>

我尝试将此添加到 xaml,但没有帮助:

      <TreeView.ItemContainerStyle>
         <Style TargetType="{x:Type TreeViewItem}" 
                BasedOn="{StaticResource {x:Type TreeViewItem}}" />
      </TreeView.ItemContainerStyle>

树视图模型

   public class TreeViewModel : BaseNotifyModel, ITreeViewModel
   {
      public TreeViewModel(ITreeViewService menuService)
      {
         TreeViewItems = 
            new ReadOnlyObservableCollection<MenuItemViewModel>(menuService.TreeViewMenu);
      }

      public ReadOnlyObservableCollection<MenuItemViewModel> TreeViewItems
      {
         get
         {
            return Get<ReadOnlyObservableCollection<MenuItemViewModel>>();
         }
         private set
         {
            Set(value);
         }
      }
   }

MenuItemViewModel

  public class MenuItemViewModel : BaseNotifyModel
   {
      public MenuItemViewModel()
      {
         MenuItems = 
            new ObservableCollection<MenuItemViewModel>();
      }

      public String Header
      {
         get
         {
            return Get<String>();
         }
         set
         {
            Set(value);
         }
      }

      public ICommand Command
      {
         get
         {
            return Get<ICommand>();
         }
         set
         {
            Set(value);
         }
      }

      public ObservableCollection<MenuItemViewModel> MenuItems
      {
         get
         {
            return Get<ObservableCollection<MenuItemViewModel>>();
         }
         set
         {
            Set(value);
         }
      }
   }

【问题讨论】:

  • 为什么要将 TreeViewItem 放入 TreeViewItem 的数据模板中?为什么要两个嵌套的树视图项?
  • 只需将常规 TextBlock 放入模板中,而不是另一个 TreeViewItem。
  • 我会在 ItemContainerStyle 中进行输入绑定,并将 Header 绑定到样式中的 MenuItemViewModel.Header,然后在数据模板中扔一个&lt;ContentControl Content="{Binding Header}" /&gt;。或者只使用 Evk 所说的 TextBlock 或 Label。
  • 感谢您的反对,似乎有道理
  • @EdPlunkett - 我想为其添加自定义命令操作

标签: c# wpf xaml treeview highlight


【解决方案1】:

TreeView 正在为ItemsSource 中的每个项目创建一个TreeViewItem,因此不要在TreeView 已经为您创建的项目中嵌套另一个TreeViewItem。这没有任何目的。您的模板应该只是为现有的TreeViewItem 提供一种方法来显示其DataContext 中的任何内容(在这种情况下是您的MenuItemViewModel)。

您想在树视图项中显示Header 属性;所以就这样做吧。没什么特别的,只是一个LabelContentControl,或者甚至是TextBlock,如果它是String(尽管在WPF 中拥有任意内容的灵活性很有趣)。当用户单击内容时,您的命令将执行。用户在树中唯一能看到的是内容。这是TreeViewItem 项的唯一可见部分,所以这就是用户要单击的内容。

问题二:一旦输入绑定得到LeftClick,就会破坏TreeView 中的选择。在我看来,您无法通过这种方法从这里到达那里。

  <TreeView.ItemTemplate>
     <HierarchicalDataTemplate ItemsSource="{Binding Path=MenuItems}">
        <ContentControl 
            Content="{Binding Header}"
            Background="Transparent"
            >
           <ContentControl.InputBindings>
              <!-- This invokes the command, but breaks selection -->
              <MouseBinding MouseAction="LeftClick"
                            Command="{Binding Command}" />
           </ContentControl.InputBindings>
        </ContentControl>
     </HierarchicalDataTemplate>
  </TreeView.ItemTemplate>

您可以这样做:

<TreeView.ItemTemplate>
    <HierarchicalDataTemplate ItemsSource="{Binding Path=MenuItems}">
        <ContentControl 
            Content="{Binding Header}"
            Background="Transparent"
            >
        </ContentControl>
    </HierarchicalDataTemplate>
</TreeView.ItemTemplate>
<TreeView.ItemContainerStyle>
    <Style TargetType="TreeViewItem" BasedOn="{StaticResource {x:Type TreeViewItem}}">
        <EventSetter Event="Selected" Handler="MenuTreeViewItem_Click" />
    </Style>
</TreeView.ItemContainerStyle>

代码隐藏

private void MenuTreeViewItem_Click(object sender, RoutedEventArgs e)
{
    ((MenuItemViewModel)((FrameworkElement)sender).DataContext).Command.Execute(null);
}

There is a way to bind an event to a command in pure XAML,但它需要一些 C# 代码 (LOL)。但我的意思是,它是“纯 XAML”,因为它是一个很好的通用可重用附加行为,而不是代码隐藏中难看的事件处理程序。相反,它与我在上面所做的完全一样,但它是在代码中执行的,您可以更轻松地避开视线,并且可以在纯 XAML 中重用。

【讨论】:

  • 好的,我知道了。但是,当我尝试此操作时,该命令在单击文本时有效,但不会突出显示文本(除非我双击)。
  • @SwDevMan81 已更新。将Background 显式设置为Transparent。将ContentControl 更改为Label 也可以;默认情况下具有Transparent 背景。唯一的问题是,如果您的命令正在执行干扰键盘焦点的操作,那么无论如何都会破坏选择突出显示。例如,我的测试代码命令最初弹出了一个 MessageBox,从而阻止了选择的发生。我认为它在 TreeView 知道发生了什么之前偷走了焦点,所以从来没有选择。
  • @EdPlunkett,设置背景并没有真正的帮助。 Click 事件仍然被 LeftClick 处理程序吃掉,因此项目没有突出显示。
  • 请注意,我不是 OP :) 也想帮助他。当然我自己不会这样做,但仍然很有趣。我将问题中的模板与您的 ItemTemplate 一起使用。所以只是带有 ItemTemplate 的 TreeView,仅此而已。 LeftClick 命令只写一行来跟踪,没有别的。而且当您单击树视图中的项目时,有时(经常)它不会被选中(但 LeftClick 处理程序将被执行)。但是如果我用常规的 MouseLeftButtonUp 事件替换 LeftClick - 一切正常。
  • @Evk 更新了答案。不是 OP 真正想听到的,但这一次它确实确实有效。
【解决方案2】:

在@Ed Plunket 和@Evk 的帮助下,我找到了一个可行的解决方案。我切换到ContentPresenter 并使用Interaction.Triggers 调用MouseLeftButtonUp 操作上的命令。

   <TreeView ItemsSource="{Binding TreeViewItems}">
      <TreeView.ItemTemplate>
         <HierarchicalDataTemplate ItemsSource="{Binding Path=MenuItems}">
            <ContentPresenter Content="{Binding Header}">
               <i:Interaction.Triggers>
                  <i:EventTrigger EventName="MouseLeftButtonUp">
                     <i:InvokeCommandAction Command="{Binding Path=DataContext.Command, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}}" />
                  </i:EventTrigger>
               </i:Interaction.Triggers>
            </ContentPresenter>
         </HierarchicalDataTemplate>
      </TreeView.ItemTemplate>
   </TreeView>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-13
    • 2015-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-27
    相关资源
    最近更新 更多