【问题标题】:Type key for style not found未找到样式的类型键
【发布时间】:2021-07-25 23:35:47
【问题描述】:

我创建了一个名为 FlatButton 的自定义用户控件,源自 Button

XAML:

<Button
    x:Class="Program.GUI.Controls.FlatButton"
    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:GUIControls="clr-namespace:Program.GUI.Controls"
    mc:Ignorable="d">
    <Button.Resources>
        <ResourceDictionary>
            <Style x:Key="{x:Type GUIControls:FlatButton}" TargetType="{x:Type GUIControls:FlatButton}" BasedOn="{StaticResource ResourceKey={x:Type Button}}">
                <Setter Property="OverridesDefaultStyle" Value="True"/>
                <Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True"/>
                <Setter Property="BorderThickness" Value="0"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type GUIControls:FlatButton}">
                            <Grid x:Name="LayoutRoot" Background="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}">
                                <TextBlock
                                    x:Name="Text"
                                    Text="{TemplateBinding Content}"
                                    Foreground="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Foreground}"
                                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter TargetName="LayoutRoot" Property="Background" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HoverBackground}"/>
                                    <Setter TargetName="Text" Property="Foreground" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HoverForeground}"/>
                                </Trigger>
                                <Trigger Property="IsMouseCaptured" Value="True">
                                    <Setter TargetName="LayoutRoot" Property="Background" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ClickBackground}"/>
                                    <Setter TargetName="Text" Property="Foreground" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ClickForeground}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ResourceDictionary>
    </Button.Resources>
</Button>

CS:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Program.GUI.Controls {
    /// <summary>
    /// Interaction logic for FlatButton.xaml
    /// </summary>
    public partial class FlatButton : Button {
        public static readonly DependencyProperty HoverBackgroundProperty = DependencyProperty.Register(
            "HoverBackground",
            typeof(Brush),
            typeof(FlatButton)
        );

        public static readonly DependencyProperty HoverForegroundProperty = DependencyProperty.Register(
            "HoverForeground",
            typeof(Brush),
            typeof(FlatButton)
        );

        public static readonly DependencyProperty ClickBackgroundProperty = DependencyProperty.Register(
            "ClickBackground",
            typeof(Brush),
            typeof(FlatButton)
        );

        public static readonly DependencyProperty ClickForegroundProperty = DependencyProperty.Register(
            "ClickForeground",
            typeof(Brush),
            typeof(FlatButton)
        );

        public Brush HoverBackground { get; set; }
        public Brush HoverForeground { get; set; }

        public Brush ClickBackground { get; set; }
        public Brush ClickForeground { get; set; }

        static FlatButton() {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(FlatButton), new FrameworkPropertyMetadata(typeof(FlatButton)));
        }

        public FlatButton() {
            this.InitializeComponent();
        }
    }
}

问题是当我尝试创建扩展样式时,找不到基本样式:

主窗口 XAML:

<Style x:Key="DefaultDarkButtonThemeStyle" TargetType="{x:Type GUIControls:FlatButton}" BasedOn="{StaticResource {x:Type GUIControls:FlatButton}}">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="Foreground" Value="{DynamicResource ColorTextPrimaryDark}"/>
    <Setter Property="HoverBackground" Value="{DynamicResource ColorPrimaryDarkLight}"/>
    <Setter Property="HoverForeground" Value="{DynamicResource ColorTextPrimaryDarkLight}"/>
    <Setter Property="ClickBackground" Value="{DynamicResource ColorPrimaryDarkLightLight}"/>
    <Setter Property="ClickForeground" Value="{DynamicResource ColorTextPrimaryDarkLightLight}"/>
</Style>

例外:

System.Windows.Markup.XamlParseException: ''Provide value on 'System.Windows.Markup.StaticResourceHolder' threw an exception.' Line number '45' and line position '47'.'

Inner Exception
Exception: Cannot find resource named 'Program.GUI.Controls.FlatButton'. Resource names are case sensitive.

【问题讨论】:

  • 在您共享的 XAML 中,我认为您需要将主要元素从 &lt;Button&gt;&lt;Button.Resources&gt; 更改为 &lt;GUIControls:FlatButton&gt;&lt;GUIControls.FlatButton:Resources&gt; 才能正常工作。你试过吗?
  • @TamBui 我了解到您必须使用基类。如果您扩展 UserControl,您还可以使用 UserControl-Tag。更改它会导致很多错误,因为找不到或无法访问某些属性。 The attachable property 'Resources' was not found in type 'FlatButton'.

标签: wpf xaml custom-controls


【解决方案1】:

如果您开发像FlatButton 这样的自定义控件,如果您开发自定义控件库或任何其他专用资源字典,则应该创建一个单独的样式,该样式驻留在theme resource dictionary(例如Themes/Generic.xaml)中。无论您选择哪种路径,您都可以将相应的资源字典合并到应用程序资源或较低范围内的任何其他资源字典中,以使该样式在该范围内可访问(如果它是隐式,则自动应用它em> 或基于它创建样式,无论如何)。

您的部分 XAML 定义是创建 UserControls 的常用方法,但不适用于自定义控件。 Button 标记的资源中FlatButton 的样式只能在此本地资源字典的范围内解析,这意味着FlatButton 本身或其可视化树。查看static resource lookup behavior 以了解样式是如何被解决的以及它失败的原因。

  1. 查找过程在设置属性的元素定义的资源字典中检查请求的键。

  2. 然后查找过程向上遍历逻辑树到父元素及其资源字典。这个过程一直持续到到达根元素。

  3. 检查应用资源。应用资源是由 WPF 应用的 Application 对象定义的资源字典中的那些资源。

因此,当您的DefaultDarkButtonThemeStyle 在主窗口中创建并尝试解析GUIControls:FlatButton 基本样式时,它找不到它,因为它没有在窗口资源中定义或可视化树或应用程序资源的任何位置。

但是,如果您只是简单地创建了一个包含样式的主题或常规资源字典并将其包含在窗口或应用程序资源中,则可以成功解析。

有关创建自定义控件的更多信息,包括如何设置样式和资源字典,可以参考Control authoring overview

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-16
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    • 1970-01-01
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多