简体   繁体   English

通过加载自定义样式清除 ItemContainerStyle

[英]ItemContainerStyle cleared by loading custom style

So, I have this issue with making a custom treeview with custom treeviewitem:s where the ItemContainerStyle gets cleared by loading the style from the custom style.因此,我在使用自定义 treeviewitem:s 制作自定义树视图时遇到了这个问题,其中ItemContainerStyle通过从自定义样式加载样式而被清除。

It work like this.它是这样工作的。 I have custom MyTreeViewItem based on TreeViewItem.我有基于 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>

As you can see I have just have a simple coloring here just to make sure that the styling it self works.正如你所看到的,我只是在这里做了一个简单的着色,以确保它自己的样式有效。 This how ever wont load unless I do like this in code behind.除非我在后面的代码中这样做,否则这永远不会加载。

EDIT : I know things like coloring don't need to be put here as there was intended to be a template here instead.编辑:我知道不需要把着色之类的东西放在这里,因为这里本来是一个模板。 How ever since noting really worked, I just stripped this down to the bones to make sure I put something super simple in that I know should work in case it was becaouse of the template it self.自从注意到真正起作用以来,我只是将其剥离到骨头,以确保我放了一些超级简单的东西,因为我知道应该可以工作,以防万一它是因为模板本身。

    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;
        }
   }

This works grate.这工作炉排。 Have used this several other times with other controls to have custom styling for controls needed to be loaded up with out having to bother to "restyle" everything over and over again.在其他控件中多次使用它来为需要加载的控件自定义样式,而不必费心一遍又一遍地“重新设计”所有内容。

How ever there are a issue I come across with this.我遇到过这个问题。 And that is when ItemContainerStyle is being used of this kind of custom styled controller.这就是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>

This ui:MyTreeView.ItemContainerStyle as you see above gets totally ignored once the style is loaded, by this.Style = Resources["MyTreeViewItemStyle"] as Style;这个ui:MyTreeView.ItemContainerStyle正如你在上面看到的一样,一旦样式被加载,就会被完全忽略,通过this.Style = Resources["MyTreeViewItemStyle"] as Style; in the MyTreeViewItem_Loaded .MyTreeViewItem_Loaded That means these Setters, EventSetters and Triggers will not fire at all, as they still are needed to be able to be added as as additional rules.这意味着这些 Setter、EventSetter 和 Triggers 根本不会触发,因为它们仍然需要能够作为附加规则添加。

How can this be solved, so that the predefined styling in the custom control can be loaded and by using this control, you can still can hook up unique rules, like above with out having the the predefined overrule them?如何解决这个问题,以便可以加载自定义控件中的预定义样式,并且通过使用此控件,您仍然可以连接独特的规则,就像上面一样,而不会被预定义的规则否决?

It's not really clear why you are doing what you are doing.目前还不清楚你为什么要做你正在做的事情。 All I can say is that you are overwriting the Style value by assigning it explicitly after the control was initialized with the value from the TreeView.ItemContainerStyle .我只能说,在使用TreeView.ItemContainerStyle的值初始化控件后,您通过显式分配来覆盖Style值。

Normally, on a UserControl , you would set the properties locally on the element:通常,在UserControl ,您将在元素上本地设置属性:

<TreeViewItem x:Class="UI.MyTreeViewItem" 
              ...
              d:DesignHeight="450" d:DesignWidth="800"
              Background="#AEFFC1">
</TreeViewItem>

or in code-behind:或在代码隐藏中:

private void MyTreeViewItem_Loaded(object sender, RoutedEventArgs e)  
{
  this.Background = 
    new SolidColorBrush(ColorConverter.ConvertFromString("#AEFFC1"));
 }

When writing a custom Control , you would provide a default Style in Generic.xaml.编写自定义Control ,您将在 Generic.xaml 中提供默认Style This is the best solution as it allows the control to be styled (where custom styles are allowed to override default values provided by the default Style ).这是最好的解决方案,因为它允许设置控件的样式(允许自定义样式覆盖默认Style提供的默认值)。 External styles are merged implicitly.外部样式被隐式合并。 You should prefer a custom Control over a UserControl.您应该更喜欢自定义控件而不是 UserControl。

Your current code does not allow styling as you forcefully override values provided by a custom Style :您当前的代码不允许样式,因为您强行覆盖自定义Style提供的值:

// Overwrite previous property value.
this.Style = someValue;

This is programming 101, first grade: an assignment always overwrites the old value (reference) of the variable.这是编程 101,一年级:赋值总是覆盖变量的旧值(引用)。

Assumming that you are knowing what you are doing and you don't want to use one of the above solution, you must manually merge both styles using the Style.BasedOn property:假设您知道自己在做什么并且不想使用上述解决方案之一,则必须使用 Style.BasedOn 属性手动合并两种样式:

private void MyTreeViewItem_Loaded(object sender, RoutedEventArgs e)
{
  var defaultStyle = Resources["MyTreeViewItemStyle"] as Style;
  defaultStyle.BasedOn = this.ItemContainerStyle;
  this.Style = defaultStyle;
}

See: Control authoring overview: Models for Control Authoring请参阅: 控件创作概述:控件创作模型

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM