WPF TreeView 样式 DataTemplate 绑定问题
WPF TreeView Style DataTemplate binding issues
我正尝试在特定类型的 TreeViewItem
上设置“在 select 上展开”功能,如下所示:
<UserControl x:Class="ImprovedDirectory.Views.DirectoryView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ImprovedDirectory.Views"
xmlns:vms="clr-namespace:ImprovedDirectory.ViewModels"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<DataTemplate x:Key="CollapsedItem" DataType="{x:Type vms:DirectoryItemViewModel}">
<TextBlock
Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center"
Margin="5"/>
</DataTemplate>
<DataTemplate x:Key="ExpandedItem" DataType="{x:Type vms:DirectoryItemViewModel}">
<StackPanel DataContext="{Binding}">
<TextBlock
Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center"
Margin="5"
Grid.Row="0"/>
<TextBlock
Text="{Binding Number, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center"
Margin="2.5"
Grid.Row="1"/>
<TextBlock
Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center"
Margin="2.5"
Grid.Row="2"/>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<TreeView x:Name="DirectoryTreeView" ItemsSource="{Binding Groups}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type vms:DirectoryGroupViewModel}" ItemsSource="{Binding Items, UpdateSourceTrigger=PropertyChanged}">
<TextBlock
Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center"
Margin="5"/>
</HierarchicalDataTemplate>
<Style TargetType="{x:Type TreeViewItem}">
<Style.Setters>
<Setter Property="ItemTemplate" Value="{StaticResource CollapsedItem}"/>
</Style.Setters>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="ItemTemplate" Value="{StaticResource ExpandedItem}"/>
</Trigger>
</Style.Triggers>
</Style>
</TreeView.Resources>
</TreeView>
上面的输出如下,我不知道为什么:
当什么都没有 selected 时,它应该是这样的:
我知道绑定中缺少的东西非常简单。但是,我现在真的不确定,我已经单独测试了 UserControl.Resources
中的每个 DataTemplate
元素,它们都按预期工作。
我也有一个问题,似乎 Style
覆盖了组的格式以及项目,所以我想第二个问题是关于如何定义特定的 DataType
正在成为项目的主要输出,而不是所有对象。
如有任何帮助,我们将不胜感激。
您看到的输出来自于您在 TreeViewItem
样式中将 DataTemplate
设置为 ItemTemplate
,它没有层次结构的表示,例如ItemsSource
儿童。
如果您将模板更改为 HierarchicalDataTemplate
s,就像在您的 TreeView
中一样,您将获得层次结构,但我认为这不会像您预期的那样运行。当您展开一个项目并 select 它或随后的另一个项目时,您会看到所有子项的模板都在变化,并且 selection 已损坏。
无需交换数据模板,您可以通过将两个模板合并为一个并在触发器中对 IsSelected
属性 做出反应,以更简单的方式获得所需的结果,这会改变可见性unselected.
时隐藏的控件数
<TreeView x:Name="DirectoryTreeView"
ItemsSource="{Binding Groups}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type vms:DirectoryGroupViewModel}"
ItemsSource="{Binding Items}">
<StackPanel>
<TextBlock Text="{Binding Name}"
VerticalAlignment="Center"
Margin="5"/>
<TextBlock x:Name="NumberTextBlock"
Text="{Binding Number}"
VerticalAlignment="Center"
Margin="2.5"
Visibility="Collapsed"/>
<TextBlock x:Name="EmailTextBlock"
Text="{Binding Email}"
VerticalAlignment="Center"
Margin="2.5"
Visibility="Collapsed"/>
</StackPanel>
<HierarchicalDataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}, Path=IsSelected}" Value="True">
<Setter TargetName="NumberTextBlock" Property="Visibility" Value="Visible"/>
<Setter TargetName="EmailTextBlock" Property="Visibility" Value="Visible"/>
</DataTrigger>
</HierarchicalDataTemplate.Triggers>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
除了触发器,您还可以使用 BooleanToVisibilityConverter
直接绑定 Visibility
。
<TreeView x:Name="DirectoryTreeView"
ItemsSource="{Binding Groups}">
<TreeView.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</TreeView.Resources>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type vms:DirectoryGroupViewModel}"
ItemsSource="{Binding Items}">
<StackPanel>
<TextBlock Text="{Binding Name}"
VerticalAlignment="Center"
Margin="5"/>
<TextBlock Text="{Binding Number}"
VerticalAlignment="Center"
Margin="2.5"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<TextBlock Text="{Binding Email}"
VerticalAlignment="Center"
Margin="2.5"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
我正尝试在特定类型的 TreeViewItem
上设置“在 select 上展开”功能,如下所示:
<UserControl x:Class="ImprovedDirectory.Views.DirectoryView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ImprovedDirectory.Views"
xmlns:vms="clr-namespace:ImprovedDirectory.ViewModels"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<DataTemplate x:Key="CollapsedItem" DataType="{x:Type vms:DirectoryItemViewModel}">
<TextBlock
Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center"
Margin="5"/>
</DataTemplate>
<DataTemplate x:Key="ExpandedItem" DataType="{x:Type vms:DirectoryItemViewModel}">
<StackPanel DataContext="{Binding}">
<TextBlock
Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center"
Margin="5"
Grid.Row="0"/>
<TextBlock
Text="{Binding Number, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center"
Margin="2.5"
Grid.Row="1"/>
<TextBlock
Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center"
Margin="2.5"
Grid.Row="2"/>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<TreeView x:Name="DirectoryTreeView" ItemsSource="{Binding Groups}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type vms:DirectoryGroupViewModel}" ItemsSource="{Binding Items, UpdateSourceTrigger=PropertyChanged}">
<TextBlock
Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center"
Margin="5"/>
</HierarchicalDataTemplate>
<Style TargetType="{x:Type TreeViewItem}">
<Style.Setters>
<Setter Property="ItemTemplate" Value="{StaticResource CollapsedItem}"/>
</Style.Setters>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="ItemTemplate" Value="{StaticResource ExpandedItem}"/>
</Trigger>
</Style.Triggers>
</Style>
</TreeView.Resources>
</TreeView>
上面的输出如下,我不知道为什么:
当什么都没有 selected 时,它应该是这样的:
我知道绑定中缺少的东西非常简单。但是,我现在真的不确定,我已经单独测试了 UserControl.Resources
中的每个 DataTemplate
元素,它们都按预期工作。
我也有一个问题,似乎 Style
覆盖了组的格式以及项目,所以我想第二个问题是关于如何定义特定的 DataType
正在成为项目的主要输出,而不是所有对象。
如有任何帮助,我们将不胜感激。
您看到的输出来自于您在 TreeViewItem
样式中将 DataTemplate
设置为 ItemTemplate
,它没有层次结构的表示,例如ItemsSource
儿童。
如果您将模板更改为 HierarchicalDataTemplate
s,就像在您的 TreeView
中一样,您将获得层次结构,但我认为这不会像您预期的那样运行。当您展开一个项目并 select 它或随后的另一个项目时,您会看到所有子项的模板都在变化,并且 selection 已损坏。
无需交换数据模板,您可以通过将两个模板合并为一个并在触发器中对 IsSelected
属性 做出反应,以更简单的方式获得所需的结果,这会改变可见性unselected.
<TreeView x:Name="DirectoryTreeView"
ItemsSource="{Binding Groups}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type vms:DirectoryGroupViewModel}"
ItemsSource="{Binding Items}">
<StackPanel>
<TextBlock Text="{Binding Name}"
VerticalAlignment="Center"
Margin="5"/>
<TextBlock x:Name="NumberTextBlock"
Text="{Binding Number}"
VerticalAlignment="Center"
Margin="2.5"
Visibility="Collapsed"/>
<TextBlock x:Name="EmailTextBlock"
Text="{Binding Email}"
VerticalAlignment="Center"
Margin="2.5"
Visibility="Collapsed"/>
</StackPanel>
<HierarchicalDataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}, Path=IsSelected}" Value="True">
<Setter TargetName="NumberTextBlock" Property="Visibility" Value="Visible"/>
<Setter TargetName="EmailTextBlock" Property="Visibility" Value="Visible"/>
</DataTrigger>
</HierarchicalDataTemplate.Triggers>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
除了触发器,您还可以使用 BooleanToVisibilityConverter
直接绑定 Visibility
。
<TreeView x:Name="DirectoryTreeView"
ItemsSource="{Binding Groups}">
<TreeView.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</TreeView.Resources>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type vms:DirectoryGroupViewModel}"
ItemsSource="{Binding Items}">
<StackPanel>
<TextBlock Text="{Binding Name}"
VerticalAlignment="Center"
Margin="5"/>
<TextBlock Text="{Binding Number}"
VerticalAlignment="Center"
Margin="2.5"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<TextBlock Text="{Binding Email}"
VerticalAlignment="Center"
Margin="2.5"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>