代码之家  ›  专栏  ›  技术社区  ›  Robert Harvey

如何获取文本框以填充TreeView项

  •  2
  • Robert Harvey  · 技术社区  · 8 年前

    我有一个三级树视图,由 HierarchicalDataTemplate . 以下是部分XAML列表:

    <TreeView
        Name="TreeView"
        ItemsSource="{Binding GTOs}"
        ScrollViewer.HorizontalScrollBarVisibility="Hidden">
        <TreeView.ItemsPanel>
            <ItemsPanelTemplate>
                <!--  This binding prevents the TreeView from slipping over to the right when an item is clicked.  -->
                <StackPanel MaxWidth="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=ContentPresenter, AncestorLevel=1}}" />
            </ItemsPanelTemplate>
        </TreeView.ItemsPanel>
    
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type local:TreeGTOViewModel}" ItemsSource="{Binding Children}">
                <TextBlock
                    Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeView}}, Path=ActualWidth}"
                    MouseDown="TextBlock_MouseDown"
                    Tag="{Binding Uri}"
                    Text="{Binding Title}" />
            </HierarchicalDataTemplate>
    

    这个 Binding Width textBlock的属性确保 TreeViewItem 假定TreeView容器的整个宽度(而不仅仅是文本框的宽度)。与材质设计样式相结合,当鼠标悬停在树中的某个特定项上时,会产生很好的着色效果。

    只有一个问题。虽然我可以得到宽度来假设树视图项的整个宽度,但对于高度我似乎做不到相同的事情。这意味着用户可以在TreeView项的边缘附近单击,并像单击该项一样查看所有效果,但是 MouseDown 事件不激发。

    这是一个 应该 可点击(红色虚线):

    enter image description here

    这是实际可单击的区域(文本框的外部边框):

    enter image description here

    我尝试过很多不同的方法,包括:

    VerticalAlignment="Stretch"
    

    而这个:

    Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}, Path=ActualHeight}"
    

    但它们要么没有效果,要么以意想不到的方式破坏树视图。我认为问题的一部分是通常的高度怪异的堆垛板被使用在 ItemsPanelTemplate .

    如何让每个TreeView项中的文本框假定实际TreeView项的高度?

    下面是可视化树的相关部分的图像,从树视图到可单击文本框。这个 Ripple 元素是 MaterialDesignThemes.Wpf.Ripple 对象。

    enter image description here

    2 回复  |  直到 8 年前
        1
  •  1
  •   Robert Harvey    8 年前

    我用一个TreeView和一个TreeView项(没有绑定)做了一个非常简单的Mahapp测试项目。

    在实况视觉树中,零件头的垂直对齐值为“中心”。如果我将其更改为Stretch(使用Live属性资源管理器),则文本块将垂直填充该空间。

    因此,我使用vs中的文档大纲来编辑TreeView模板的副本。在里面,我看到 <Setter Property="VerticalContentAlignment" Value="Center"> 所以我决定把它放在我的树视图上,它看起来很管用。

    <TreeView x:Name="TreeView"
      ScrollViewer.HorizontalScrollBarVisibility="Hidden"
      VerticalContentAlignment="Stretch">
    
        2
  •  0
  •   Robert Harvey    8 年前

    嗯,我通过走不同的路线解决了这个问题。而不是钩住 MouseDown 事件在文本块上,我将挂接 SelectedItemChanged 树视图上的事件。

        <TreeView
            ItemsSource="{Binding GTOs}"
            SelectedItemChanged="TreeView_SelectedItemChanged">
    

    这个 RoutedPropertyChangedEventArgs 选择编辑更改 事件包含该特定的ViewModel TreeViewItem ,这将生成导航所需的URI属性(我以前将此属性绑定到了文本框的标记属性)。

    新的事件处理程序如下所示:

    private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        dynamic viewModel = e.NewValue;
        var uri = viewModel.Uri;
        (DataContext as TreeViewModel).Navigate(uri);
    }
    

    树的每个级别都包含不同的ViewModel类型,但它们都有一个URI属性,因此 dynamic 绑定提供了所需的“不关心它是什么类型”行为。

    我现在可以移除 Tag 约束和 事件 来自文本块的事件。

        <HierarchicalDataTemplate DataType="{x:Type local:TreeGTOViewModel}" ItemsSource="{Binding Children}">
            <TextBlock
                Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeView}}, Path=ActualWidth}"
                Text="{Binding Title}" />
    

    树视图项现在可以正确响应,不管单击在哪里。