通过加载自定义样式清除 ItemContainerStyle
ItemContainerStyle cleared by loading custom style
所以,我在使用自定义 treeviewitem:s 制作自定义树视图时遇到了这个问题,其中 ItemContainerStyle
通过从自定义样式加载样式来清除。
它是这样工作的。我有基于 TreeViewItem 的自定义 MyTreeViewItem。
<TreeViewItem x:Class="UI.MyTreeViewItem"
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"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<TreeViewItem.Resources>
<Style x:Key="MyTreeViewItemStyle" TargetType="TreeViewItem">
<Setter Property="Background" Value="#AEFFC1" />
</Style>
</TreeViewItem.Resources>
</TreeViewItem>
正如您所看到的,我只是在这里进行了简单的着色,以确保样式本身有效。除非我在后面的代码中这样做,否则永远不会加载。
编辑:我知道着色之类的东西不需要放在这里,因为本来打算在这里放一个模板。自从注释真的起作用以来,我只是将它精简到骨头,以确保我把一些超级简单的东西放在里面,我知道应该可以工作,以防万一它是因为它自己的模板。
public partial class MyTreeViewItem : TreeViewItem
{
public MyTreeViewItem()
{
InitializeComponent();
this.Loaded += MyTreeViewItem_Loaded;
}
private void MyTreeViewItem_Loaded(object sender, RoutedEventArgs e)
{
this.Style = Resources["MyTreeViewItemStyle"] as Style;
}
}
这很好用。已经多次将此与其他控件一起使用,以便为需要加载的控件设置自定义样式,而不必一遍又一遍地“重新设计”所有内容。
我怎么遇到过这个问题。那就是 ItemContainerStyle
正在使用这种自定义样式的控制器。
<local:BaseTreeView x:Class="My.Navigator.NavigatorTreeView"
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:ui="clr-namespace:UI;assembly=BaseCode"
d:DesignHeight="450" d:DesignWidth="800">
<ui:MyTreeView ItemsSource="{Binding Path=Nodes}">
...
<ui:MyTreeView.ItemContainerStyle>
<Style TargetType="{x:Type ui:MyTreeViewItem}">
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<EventSetter Event="Selected" Handler="TreeView_SelectedItemChanged" />
<EventSetter Event="Expanded" Handler="TreeView_NodeExpanded" />
<EventSetter Event="Collapsed" Handler="TreeView_NodeCollapsed" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
</ui:MyTreeView.ItemContainerStyle>
</ui:MyTreeView>
</local:BaseTreeView>
MyTreeViewItem_Loaded
中的 this.Style = Resources["MyTreeViewItemStyle"] as Style;
加载样式后,您在上面看到的 ui:MyTreeView.ItemContainerStyle
将被完全忽略。
这意味着这些设置器、事件设置器和触发器根本不会触发,因为它们仍然需要能够作为附加规则添加。
如何解决这个问题,以便可以加载自定义控件中的预定义样式,并且通过使用此控件,您仍然可以像上面那样连接独特的规则,而无需预定义的规则否决它们?
不太清楚你为什么要做你正在做的事情。我只能说,在使用 TreeView.ItemContainerStyle
.
中的值初始化控件后,您通过显式分配它来覆盖 Style
值
通常,在 UserControl
上,您会在元素上本地设置属性:
<TreeViewItem x:Class="UI.MyTreeViewItem"
...
d:DesignHeight="450" d:DesignWidth="800"
Background="#AEFFC1">
</TreeViewItem>
或在代码隐藏中:
private void MyTreeViewItem_Loaded(object sender, RoutedEventArgs e)
{
this.Background =
new SolidColorBrush(ColorConverter.ConvertFromString("#AEFFC1"));
}
编写自定义 Control
时,您将在 Generic.xaml 中提供默认值 Style
。这是最好的解决方案,因为它允许对控件进行样式设置(允许自定义样式覆盖默认 Style
提供的默认值)。外部样式被隐式合并。您应该更喜欢自定义控件而不是 UserControl。
您当前的代码不允许设置样式,因为您强行覆盖了自定义 Style
:
提供的值
// Overwrite previous property value.
this.Style = someValue;
这是编程 101,一年级:赋值总是覆盖变量的旧值(引用)。
假设您知道自己在做什么并且不想使用上述解决方案之一,则必须使用 Style.BasedOn 属性:
private void MyTreeViewItem_Loaded(object sender, RoutedEventArgs e)
{
var defaultStyle = Resources["MyTreeViewItemStyle"] as Style;
defaultStyle.BasedOn = this.ItemContainerStyle;
this.Style = defaultStyle;
}
所以,我在使用自定义 treeviewitem:s 制作自定义树视图时遇到了这个问题,其中 ItemContainerStyle
通过从自定义样式加载样式来清除。
它是这样工作的。我有基于 TreeViewItem 的自定义 MyTreeViewItem。
<TreeViewItem x:Class="UI.MyTreeViewItem"
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"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<TreeViewItem.Resources>
<Style x:Key="MyTreeViewItemStyle" TargetType="TreeViewItem">
<Setter Property="Background" Value="#AEFFC1" />
</Style>
</TreeViewItem.Resources>
</TreeViewItem>
正如您所看到的,我只是在这里进行了简单的着色,以确保样式本身有效。除非我在后面的代码中这样做,否则永远不会加载。
编辑:我知道着色之类的东西不需要放在这里,因为本来打算在这里放一个模板。自从注释真的起作用以来,我只是将它精简到骨头,以确保我把一些超级简单的东西放在里面,我知道应该可以工作,以防万一它是因为它自己的模板。
public partial class MyTreeViewItem : TreeViewItem
{
public MyTreeViewItem()
{
InitializeComponent();
this.Loaded += MyTreeViewItem_Loaded;
}
private void MyTreeViewItem_Loaded(object sender, RoutedEventArgs e)
{
this.Style = Resources["MyTreeViewItemStyle"] as Style;
}
}
这很好用。已经多次将此与其他控件一起使用,以便为需要加载的控件设置自定义样式,而不必一遍又一遍地“重新设计”所有内容。
我怎么遇到过这个问题。那就是 ItemContainerStyle
正在使用这种自定义样式的控制器。
<local:BaseTreeView x:Class="My.Navigator.NavigatorTreeView"
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:ui="clr-namespace:UI;assembly=BaseCode"
d:DesignHeight="450" d:DesignWidth="800">
<ui:MyTreeView ItemsSource="{Binding Path=Nodes}">
...
<ui:MyTreeView.ItemContainerStyle>
<Style TargetType="{x:Type ui:MyTreeViewItem}">
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<EventSetter Event="Selected" Handler="TreeView_SelectedItemChanged" />
<EventSetter Event="Expanded" Handler="TreeView_NodeExpanded" />
<EventSetter Event="Collapsed" Handler="TreeView_NodeCollapsed" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
</ui:MyTreeView.ItemContainerStyle>
</ui:MyTreeView>
</local:BaseTreeView>
MyTreeViewItem_Loaded
中的 this.Style = Resources["MyTreeViewItemStyle"] as Style;
加载样式后,您在上面看到的 ui:MyTreeView.ItemContainerStyle
将被完全忽略。
这意味着这些设置器、事件设置器和触发器根本不会触发,因为它们仍然需要能够作为附加规则添加。
如何解决这个问题,以便可以加载自定义控件中的预定义样式,并且通过使用此控件,您仍然可以像上面那样连接独特的规则,而无需预定义的规则否决它们?
不太清楚你为什么要做你正在做的事情。我只能说,在使用 TreeView.ItemContainerStyle
.
Style
值
通常,在 UserControl
上,您会在元素上本地设置属性:
<TreeViewItem x:Class="UI.MyTreeViewItem"
...
d:DesignHeight="450" d:DesignWidth="800"
Background="#AEFFC1">
</TreeViewItem>
或在代码隐藏中:
private void MyTreeViewItem_Loaded(object sender, RoutedEventArgs e)
{
this.Background =
new SolidColorBrush(ColorConverter.ConvertFromString("#AEFFC1"));
}
编写自定义 Control
时,您将在 Generic.xaml 中提供默认值 Style
。这是最好的解决方案,因为它允许对控件进行样式设置(允许自定义样式覆盖默认 Style
提供的默认值)。外部样式被隐式合并。您应该更喜欢自定义控件而不是 UserControl。
您当前的代码不允许设置样式,因为您强行覆盖了自定义 Style
:
// Overwrite previous property value.
this.Style = someValue;
这是编程 101,一年级:赋值总是覆盖变量的旧值(引用)。
假设您知道自己在做什么并且不想使用上述解决方案之一,则必须使用 Style.BasedOn 属性:
private void MyTreeViewItem_Loaded(object sender, RoutedEventArgs e)
{
var defaultStyle = Resources["MyTreeViewItemStyle"] as Style;
defaultStyle.BasedOn = this.ItemContainerStyle;
this.Style = defaultStyle;
}