我有一个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
事件不会触发。
这是应可点击的区域(红色虚线):
这是实际可点击的区域(文本框的外边框):
我尝试了很多不同的方法,包括这个方法:
VerticalAlignment="Stretch"
和这一个:
Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}, Path=ActualHeight}"
但它们要么没有效果,要么以意想不到的方式破坏TreeView。我认为问题的一部分是在ItemsPanelTemplate
中使用的StackPanel通常的高度怪异。
如何让每个TreeViewItem中的TextBox呈现实际TreeViewItem的高度?
下面是可视树的相关部分的图像,从TreeView到可单击的文本框。 Ripple
元素是MaterialDesignThemes.Wpf.Ripple
对象。
答案 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}" />
现在树视图项目无论在何处被点击都能正常响应。