如何让文本框填充树视图项目

时间:2018-05-24 18:18:29

标签: c# wpf xaml material-design-in-xaml

我有一个TreeView,其中有3个级别,由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>

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

只有一个问题。虽然我可以让宽度假设TreeViewItem的全宽,但我似乎无法对高度做同样的事情。这意味着用户可以在TreeView项目的边缘附近单击并查看所有效果,就好像单击了该项目一样,但MouseDown事件不会触发。

这是可点击的区域(红色虚线):

enter image description here

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

enter image description here

我尝试了很多不同的方法,包括这个方法:

VerticalAlignment="Stretch"

和这一个:

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

但它们要么没有效果,要么以意想不到的方式破坏TreeView。我认为问题的一部分是在ItemsPanelTemplate中使用的StackPanel通常的高度怪异。

如何让每个TreeViewItem中的TextBox呈现实际TreeViewItem的高度?

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

enter image description here

2 个答案:

答案 0 :(得分:1)

我做了一个非常简单的MahApp测试项目,它有一个树视图和一个treeviewitem(没有绑定)。

在实时可视树中,PART_Header的VerticalAlignment值为Center。如果我将其更改为Stretch(使用Live Property Explorer),则文本块会垂直填充空格。

所以,我使用VS中的Document Outline来编辑treeview模板的副本。在其中,我看到了<Setter Property="VerticalContentAlignment" Value="Center">所以我决定将它设置为在我的TreeView上拉伸,它似乎有效。

<TreeView x:Name="TreeView"
  ScrollViewer.HorizontalScrollBarVisibility="Hidden"
  VerticalContentAlignment="Stretch">

答案 1 :(得分:0)

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

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

RoutedPropertyChangedEventArgs事件的SelectedItemChanged包含特定TreeViewItem的ViewModel,它会生成导航所需的Uri属性(我以前将此属性绑定到TextBox的Tag属性)。

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

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绑定提供了所需的“不关心它是什么类型”行为。

我现在可以从TextBlock中删除Tag绑定和MouseDown事件。

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

现在树视图项目无论在何处被点击都能正常响应。