Reputation: 180958
I have a TreeView that has 3 levels in it, driven by a HierarchicalDataTemplate
. Here is a partial xaml listing:
<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>
The Binding
on the Width
attribute of the TextBlock insures that each TreeViewItem
assumes the full width of the TreeView container (and not just the width of the text box). Coupled with the Material Design styling, this produces nice shading effects when the mouse is hovered over a particular item in the tree.
There's only one problem. While I can get the Width to assume the full width of the TreeViewItem, I can't seem to do the same for the Height. This means that the user can click near the edge of the TreeView item and see all of the effects as if that item was clicked, but the MouseDown
event does not fire.
This is the area that should be clickable (the dotted red line):
This is the area that is actually clickable (the outside border of the Text Box):
I've tried a number of different approaches, including this one:
VerticalAlignment="Stretch"
and this one:
Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}, Path=ActualHeight}"
but they either have no effect, or they break the TreeView in unexpected ways. I think part of the problem is the usual height weirdness of the StackPanel that is being used in the ItemsPanelTemplate
.
How do I get the TextBox in each TreeViewItem to assume the height of the actual TreeViewItem?
Below is an image of the relevant part of the visual tree, from the TreeView down to the clickable Text Box. The Ripple
element is a MaterialDesignThemes.Wpf.Ripple
object.
Upvotes: 2
Views: 1103
Reputation: 4322
I made a very simple MahApp test project with a treeview and one treeviewitem (no binding).
In the Live Visual Tree, the PART_Header had a VerticalAlignment value of Center. If I changed it to Stretch (using Live Property Explorer), the textblock filled the space vertically.
So, I used the Document Outline in VS to edit a copy of the treeview template. Inside of that, I saw <Setter Property="VerticalContentAlignment" Value="Center">
so I decided to set it to Stretch on my TreeView and it seemed to work.
<TreeView x:Name="TreeView"
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
VerticalContentAlignment="Stretch">
Upvotes: 1
Reputation: 180958
Well, I solved this by going a different route. Instead of hooking the MouseDown
event on the Text Block, I'm going to hook the SelectedItemChanged
event on the Tree View.
<TreeView
ItemsSource="{Binding GTOs}"
SelectedItemChanged="TreeView_SelectedItemChanged">
The RoutedPropertyChangedEventArgs
of the SelectedItemChanged
event contains the ViewModel for that particular TreeViewItem
, which yields the Uri property I need for navigation (I was previously binding this property to the TextBox's Tag property).
The new Event Handler looks like this:
private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
dynamic viewModel = e.NewValue;
var uri = viewModel.Uri;
(DataContext as TreeViewModel).Navigate(uri);
}
Each level of the tree contains a different ViewModel type, but they all have a Uri property, so the dynamic
binding provides the needed "don't care what type it is" behavior.
I can now remove the Tag
binding and MouseDown
event from the TextBlock.
<HierarchicalDataTemplate DataType="{x:Type local:TreeGTOViewModel}" ItemsSource="{Binding Children}">
<TextBlock
Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeView}}, Path=ActualWidth}"
Text="{Binding Title}" />
and the Tree View items now respond properly, no matter where they are clicked.
Upvotes: 0