当 TreeViewItem 包含带有 DropShadowEffect 的边框时,如何应用 TreeView 突出显示颜色?
How to apply TreeView highlight color when TreeViewItem contains border with DropShadowEffect?
情况:
我想要 DropShadowEffect
围绕我的 TreeViewItem
,同时我希望 TreeViewItem
在被选中时改变颜色。
问题:
为了让 DropShadowEffect
不应用于 TreeViewItem
中的文本,我需要在包含 DropShadowEffect
的边框上设置 Background="White"
,这似乎选择时覆盖 TreeViewItem
的突出显示。
我可以像这个例子一样正确应用 DropShadowEffect
:
或者我可以在选择时正确突出显示,但在文本上放置阴影,如本例所示:
问题:
有没有办法保持 TreeView
的突出显示可能性,同时防止 DropShadowEffect
被应用到 TreeViewItem
中的文本?
到目前为止我尝试了什么:
- 我尝试将
TreeViewItem
的 Panel.ZIndex
设置为您在下面看到的样式,例如 <Setter Property="Panel.ZIndex" Value="5"/>
。
- 我尝试使用两个边框,它们占据相同的 space,就像这个 tutorial 一样。
增加:
我无法将白色背景应用到 TreeViewItem
,因为我的边框周围有圆边,TreeViewItem
的完美正方形背景不符合这一点。
我不想将 DropShadowEffect
应用于 Expander
按钮。
最小(非)工作示例:
树视图:
<Window x:Class="TreeViewDropShadowExampl.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TreeViewDropShadowExampl"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<TreeView ItemsSource="{Binding Root}" MinWidth="100" MinHeight="100">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Node}" ItemsSource="{Binding Children}">
<Grid>
<Border BorderBrush="Gray">
<TextBlock Text="{Binding ID}"/>
<Border.Effect>
<DropShadowEffect Color="Gray" BlurRadius="2"/>
</Border.Effect>
</Border>
</Grid>
</HierarchicalDataTemplate>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="Margin" Value="2" />
</Style>
</TreeView.Resources>
</TreeView>
</Window>
VM:
using System.Collections.ObjectModel;
namespace TreeViewDropShadowExampl
{
class VM
{
public VM()
{
var root = new Node("1");
Root.Add(root);
for (int i = 1; i < 4; i++)
{
Node newNode = new Node("1." + i.ToString());
for (int j = 1; j < 4; j++)
{
newNode.Children.Add(new Node("1." + i.ToString() + "." + j.ToString()));
}
root.Children.Add(newNode);
}
}
public ObservableCollection<Node> Root { get; set; } = new ObservableCollection<Node>();
}
}
节点:
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace TreeViewDropShadowExampl
{
public class Node : INotifyPropertyChanged
{
#region WPF integration properties
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion WPF integration properties
public Node(string id)
{
ID = id;
}
private string _id;
public string ID
{
get { return _id; }
set
{
_id = value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged();
}
}
public ObservableCollection<Node> Children { get; set; } = new ObservableCollection<Node>();
}
}
不要将效果应用于数据模板中的 Border
,而是将效果应用于整个项目:
<TreeView>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Style.Triggers>
<Trigger Property="IsSelected" Value="False">
<Setter Property="Background" Value="White"/>
</Trigger>
</Style.Triggers>
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect Color="Gray" BlurRadius="2"/>
</Setter.Value>
</Setter>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
不要忘记从数据模板的 Border
中删除效果。
或者甚至完全删除 Border
,如果你只是为了阴影效果需要它。
更新:
您也可以对项目应用白色背景。只需将其置于触发器中即可确保它仅在未选择项目时发生。
更新二:
有了所有新要求,这里是您问题的完整解决方案。
首先,可以有一个圆角的选择矩形——你只需要改变选择边框的样式。
<TreeView>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<!-- This style changes the item's border appearance -->
<Style.Resources>
<Style TargetType="Border">
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect Color="Gray" BlurRadius="2"/>
</Setter.Value>
</Setter>
<!-- Set the same corner radius here as in your data template -->
<Setter Property="CornerRadius" Value="8"/>
</Style>
</Style.Resources>
<Setter Property="Margin" Value="2"/>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate>
<Grid>
<Border x:Name="RoundedBorder" CornerRadius="8">
<!-- Your content here -->
</Border>
</Grid>
<HierarchicalDataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType=TreeViewItem}}" Value="False">
<!-- Only setting the item's background when it's not selected -->
<Setter TargetName="RoundedBorder" Property="Background" Value="White"/>
</DataTrigger>
</HierarchicalDataTemplate.Triggers>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
情况:
我想要 DropShadowEffect
围绕我的 TreeViewItem
,同时我希望 TreeViewItem
在被选中时改变颜色。
问题:
为了让 DropShadowEffect
不应用于 TreeViewItem
中的文本,我需要在包含 DropShadowEffect
的边框上设置 Background="White"
,这似乎选择时覆盖 TreeViewItem
的突出显示。
我可以像这个例子一样正确应用 DropShadowEffect
:
或者我可以在选择时正确突出显示,但在文本上放置阴影,如本例所示:
问题:
有没有办法保持 TreeView
的突出显示可能性,同时防止 DropShadowEffect
被应用到 TreeViewItem
中的文本?
到目前为止我尝试了什么:
- 我尝试将
TreeViewItem
的Panel.ZIndex
设置为您在下面看到的样式,例如<Setter Property="Panel.ZIndex" Value="5"/>
。 - 我尝试使用两个边框,它们占据相同的 space,就像这个 tutorial 一样。
增加:
我无法将白色背景应用到 TreeViewItem
,因为我的边框周围有圆边,TreeViewItem
的完美正方形背景不符合这一点。
我不想将 DropShadowEffect
应用于 Expander
按钮。
最小(非)工作示例:
树视图:
<Window x:Class="TreeViewDropShadowExampl.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TreeViewDropShadowExampl"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<TreeView ItemsSource="{Binding Root}" MinWidth="100" MinHeight="100">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Node}" ItemsSource="{Binding Children}">
<Grid>
<Border BorderBrush="Gray">
<TextBlock Text="{Binding ID}"/>
<Border.Effect>
<DropShadowEffect Color="Gray" BlurRadius="2"/>
</Border.Effect>
</Border>
</Grid>
</HierarchicalDataTemplate>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="Margin" Value="2" />
</Style>
</TreeView.Resources>
</TreeView>
</Window>
VM:
using System.Collections.ObjectModel;
namespace TreeViewDropShadowExampl
{
class VM
{
public VM()
{
var root = new Node("1");
Root.Add(root);
for (int i = 1; i < 4; i++)
{
Node newNode = new Node("1." + i.ToString());
for (int j = 1; j < 4; j++)
{
newNode.Children.Add(new Node("1." + i.ToString() + "." + j.ToString()));
}
root.Children.Add(newNode);
}
}
public ObservableCollection<Node> Root { get; set; } = new ObservableCollection<Node>();
}
}
节点:
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace TreeViewDropShadowExampl
{
public class Node : INotifyPropertyChanged
{
#region WPF integration properties
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion WPF integration properties
public Node(string id)
{
ID = id;
}
private string _id;
public string ID
{
get { return _id; }
set
{
_id = value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged();
}
}
public ObservableCollection<Node> Children { get; set; } = new ObservableCollection<Node>();
}
}
不要将效果应用于数据模板中的 Border
,而是将效果应用于整个项目:
<TreeView>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Style.Triggers>
<Trigger Property="IsSelected" Value="False">
<Setter Property="Background" Value="White"/>
</Trigger>
</Style.Triggers>
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect Color="Gray" BlurRadius="2"/>
</Setter.Value>
</Setter>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
不要忘记从数据模板的 Border
中删除效果。
或者甚至完全删除 Border
,如果你只是为了阴影效果需要它。
更新:
您也可以对项目应用白色背景。只需将其置于触发器中即可确保它仅在未选择项目时发生。
更新二:
有了所有新要求,这里是您问题的完整解决方案。
首先,可以有一个圆角的选择矩形——你只需要改变选择边框的样式。
<TreeView>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<!-- This style changes the item's border appearance -->
<Style.Resources>
<Style TargetType="Border">
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect Color="Gray" BlurRadius="2"/>
</Setter.Value>
</Setter>
<!-- Set the same corner radius here as in your data template -->
<Setter Property="CornerRadius" Value="8"/>
</Style>
</Style.Resources>
<Setter Property="Margin" Value="2"/>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate>
<Grid>
<Border x:Name="RoundedBorder" CornerRadius="8">
<!-- Your content here -->
</Border>
</Grid>
<HierarchicalDataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType=TreeViewItem}}" Value="False">
<!-- Only setting the item's background when it's not selected -->
<Setter TargetName="RoundedBorder" Property="Background" Value="White"/>
</DataTrigger>
</HierarchicalDataTemplate.Triggers>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>