为 TreeViewItem 使用自定义样式时,Wpf 树视图双向绑定不起作用
Wpf tree-view two-way binding not working when using custom style for TreeViewItem
我尝试设置一个自定义样式的树视图,它通过将展开的 属性 双向绑定到视图模型中的类似 属性 来 "just in time" 加载。样式和功能方面单独使用时效果很好,但放在一起时就不行了。
当我这样做时,功能就在那里:
<TreeView Name="treeView" ItemsSource="{Binding}" Grid.Column="0">
<TreeView.Resources>
<ResourceDictionary Source="GroupedTreeViewItemStyle.xaml"/>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding Expanded, Mode=TwoWay}"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
但是当我添加 BasedOn
以使用我的自定义样式时,它不再加载任何节点。
我通过将上面的样式定义替换为以下内容来使用我的样式:
<Style TargetType="TreeViewItem" BasedOn="{StaticResource GroupedTreeViewItemStyle}">
这是我根据 this 教程自定义的样式:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:this="*******namespace omitted*******">
<!-- This Style redefines the ControlTemplate used by TreeViewItems and
also provides a different itemspanel for their child items. -->
<Style TargetType="TreeViewItem" x:Key="GroupedTreeViewItemStyle">
<Style.Resources>
<LinearGradientBrush x:Key="ItemAreaBrush" StartPoint="0.5, 0" EndPoint="0.5, 1" Opacity="1">
<GradientStop Color="#fff" Offset="0" />
<GradientStop Color="#f2fcfe" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="SelectedItemAreaBrush" StartPoint="0.5, 0" EndPoint="0.5, 1" Opacity="1">
<GradientStop Color="#fff" Offset="0" />
<GradientStop Color="#f2fcfe" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ItemBorderBrush" StartPoint="0.5, 0" EndPoint="0.5, 1">
<GradientStop Color="#243B55" Offset="0" />
<GradientStop Color="#141E30" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="SelectedItemBorderBrush" StartPoint="0.5, 0" EndPoint="0.5, 1">
<GradientStop Color="#243B55" Offset="0" />
<GradientStop Color="#141E30" Offset="1" />
</LinearGradientBrush>
<DropShadowBitmapEffect x:Key="DropShadowEffect" />
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem">
<Grid Margin="8,4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- This Border contains elements which display
the content and child items of the TreeViewItem. -->
<Border Name="Bd"
Background="{StaticResource ItemAreaBrush}"
BorderBrush="{StaticResource ItemBorderBrush}"
BorderThickness="0.6"
CornerRadius="8"
Padding="6"
SnapsToDevicePixels="True"
>
<Grid>
<!-- Items with children are
shown in an Expander. -->
<Expander Name="Exp" IsExpanded="{TemplateBinding TreeViewItem.IsExpanded}">
<Expander.Header>
<!-- Displays the item's header in the Expander. -->
<ContentPresenter ContentSource="Header" />
</Expander.Header>
<!-- Displays the item's children. -->
<ItemsPresenter />
</Expander>
<!-- Items without children are
shown in a ContentPresenter. -->
<ContentPresenter Name="CntPres"
ContentSource="Header"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Visibility="Collapsed"
/>
</Grid>
</Border>
</Grid>
<ControlTemplate.Triggers>
<!-- If the TreeViewItem has child items,
show it in an Expander. Otherwise
hide the Expander and show the hidden
ContentPresenter. -->
<Trigger Property="TreeViewItem.HasItems" Value="false">
<Setter
TargetName="Exp"
Property="Visibility"
Value="Collapsed" />
<Setter
TargetName="CntPres"
Property="Visibility"
Value="Visible" />
</Trigger>
<!--When the item is selected in the TreeView, use the
"selected" colors and give it a drop shadow. -->
<Trigger Property="IsSelected" Value="true">
<Setter
TargetName="Bd"
Property="Panel.Background"
Value="{StaticResource SelectedItemAreaBrush}" />
<Setter
TargetName="Bd"
Property="Border.BorderBrush"
Value="{StaticResource SelectedItemBorderBrush}" />
<!--<Setter
TargetName="Bd"
Property="TextElement.Foreground"
Value="{DynamicResource
{x:Static SystemColors.HighlightTextBrushKey}}" />-->
<Setter
TargetName="Bd"
Property="Border.BitmapEffect"
Value="{StaticResource DropShadowEffect}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<!-- Make each TreeViewItem show it's children
in a StackPanel. If it is a root item then
the Orientation will be 'Horizontal', else
'Vertical'. -->
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<ItemsPanelTemplate.Resources>
<this:ItemsPanelOrientationConverter x:Key="conv" />
</ItemsPanelTemplate.Resources>
<StackPanel
IsItemsHost="True"
Orientation="{Binding
RelativeSource={x:Static RelativeSource.TemplatedParent},
Converter={StaticResource conv}}"
/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
有人知道我在结合我的树的样式和功能时做错了什么吗?
问题是样式已经根据 isExpanded
属性 定义了什么?还是缺少某些东西,类似于 super(isExpanded)
?
感谢您的帮助!
扩展器绑定可能是问题的原因:
<Expander Name="Exp" IsExpanded="{TemplateBinding TreeViewItem.IsExpanded}">
A TemplateBinding is always a one-way binding, even if properties involved default to two-way binding.
(另见 TemplateBinding limitations)
尝试re-write绑定为:
<Expander Name="Exp"
IsExpanded="{Binding IsExpanded,
RelativeSource={RelativeSource TemplatedParent}}">
我尝试设置一个自定义样式的树视图,它通过将展开的 属性 双向绑定到视图模型中的类似 属性 来 "just in time" 加载。样式和功能方面单独使用时效果很好,但放在一起时就不行了。
当我这样做时,功能就在那里:
<TreeView Name="treeView" ItemsSource="{Binding}" Grid.Column="0">
<TreeView.Resources>
<ResourceDictionary Source="GroupedTreeViewItemStyle.xaml"/>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding Expanded, Mode=TwoWay}"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
但是当我添加 BasedOn
以使用我的自定义样式时,它不再加载任何节点。
我通过将上面的样式定义替换为以下内容来使用我的样式:
<Style TargetType="TreeViewItem" BasedOn="{StaticResource GroupedTreeViewItemStyle}">
这是我根据 this 教程自定义的样式:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:this="*******namespace omitted*******">
<!-- This Style redefines the ControlTemplate used by TreeViewItems and
also provides a different itemspanel for their child items. -->
<Style TargetType="TreeViewItem" x:Key="GroupedTreeViewItemStyle">
<Style.Resources>
<LinearGradientBrush x:Key="ItemAreaBrush" StartPoint="0.5, 0" EndPoint="0.5, 1" Opacity="1">
<GradientStop Color="#fff" Offset="0" />
<GradientStop Color="#f2fcfe" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="SelectedItemAreaBrush" StartPoint="0.5, 0" EndPoint="0.5, 1" Opacity="1">
<GradientStop Color="#fff" Offset="0" />
<GradientStop Color="#f2fcfe" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ItemBorderBrush" StartPoint="0.5, 0" EndPoint="0.5, 1">
<GradientStop Color="#243B55" Offset="0" />
<GradientStop Color="#141E30" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="SelectedItemBorderBrush" StartPoint="0.5, 0" EndPoint="0.5, 1">
<GradientStop Color="#243B55" Offset="0" />
<GradientStop Color="#141E30" Offset="1" />
</LinearGradientBrush>
<DropShadowBitmapEffect x:Key="DropShadowEffect" />
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem">
<Grid Margin="8,4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- This Border contains elements which display
the content and child items of the TreeViewItem. -->
<Border Name="Bd"
Background="{StaticResource ItemAreaBrush}"
BorderBrush="{StaticResource ItemBorderBrush}"
BorderThickness="0.6"
CornerRadius="8"
Padding="6"
SnapsToDevicePixels="True"
>
<Grid>
<!-- Items with children are
shown in an Expander. -->
<Expander Name="Exp" IsExpanded="{TemplateBinding TreeViewItem.IsExpanded}">
<Expander.Header>
<!-- Displays the item's header in the Expander. -->
<ContentPresenter ContentSource="Header" />
</Expander.Header>
<!-- Displays the item's children. -->
<ItemsPresenter />
</Expander>
<!-- Items without children are
shown in a ContentPresenter. -->
<ContentPresenter Name="CntPres"
ContentSource="Header"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Visibility="Collapsed"
/>
</Grid>
</Border>
</Grid>
<ControlTemplate.Triggers>
<!-- If the TreeViewItem has child items,
show it in an Expander. Otherwise
hide the Expander and show the hidden
ContentPresenter. -->
<Trigger Property="TreeViewItem.HasItems" Value="false">
<Setter
TargetName="Exp"
Property="Visibility"
Value="Collapsed" />
<Setter
TargetName="CntPres"
Property="Visibility"
Value="Visible" />
</Trigger>
<!--When the item is selected in the TreeView, use the
"selected" colors and give it a drop shadow. -->
<Trigger Property="IsSelected" Value="true">
<Setter
TargetName="Bd"
Property="Panel.Background"
Value="{StaticResource SelectedItemAreaBrush}" />
<Setter
TargetName="Bd"
Property="Border.BorderBrush"
Value="{StaticResource SelectedItemBorderBrush}" />
<!--<Setter
TargetName="Bd"
Property="TextElement.Foreground"
Value="{DynamicResource
{x:Static SystemColors.HighlightTextBrushKey}}" />-->
<Setter
TargetName="Bd"
Property="Border.BitmapEffect"
Value="{StaticResource DropShadowEffect}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<!-- Make each TreeViewItem show it's children
in a StackPanel. If it is a root item then
the Orientation will be 'Horizontal', else
'Vertical'. -->
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<ItemsPanelTemplate.Resources>
<this:ItemsPanelOrientationConverter x:Key="conv" />
</ItemsPanelTemplate.Resources>
<StackPanel
IsItemsHost="True"
Orientation="{Binding
RelativeSource={x:Static RelativeSource.TemplatedParent},
Converter={StaticResource conv}}"
/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
有人知道我在结合我的树的样式和功能时做错了什么吗?
问题是样式已经根据 isExpanded
属性 定义了什么?还是缺少某些东西,类似于 super(isExpanded)
?
感谢您的帮助!
扩展器绑定可能是问题的原因:
<Expander Name="Exp" IsExpanded="{TemplateBinding TreeViewItem.IsExpanded}">
A TemplateBinding is always a one-way binding, even if properties involved default to two-way binding.
(另见 TemplateBinding limitations)
尝试re-write绑定为:
<Expander Name="Exp"
IsExpanded="{Binding IsExpanded,
RelativeSource={RelativeSource TemplatedParent}}">