WPF 样式不适用于已设置样式的 UserControl

bgc*_*ode 5 wpf

我来找你是因为我对控件样式感到头疼了几个小时。通过给用户控件定义样式是行不通的!

我的用户控件声明:

<uiComponent:NumericTextBox Text="{Binding myProperty}"/>
Run Code Online (Sandbox Code Playgroud)

我想要应用的样式:

<Style TargetType="uiComponent:NumericTextBox">
   <Setter Property="Background" Value="Black"/>
</Style>
Run Code Online (Sandbox Code Playgroud)

为什么它不能与背景属性一起使用,尽管它可以与可见性属性一起使用!我尝试使用 TargetType=FrameworkElement,没有效果......

我的用户控件是一个数字文本框,它定义了自己的样式,如下所示:

<ResourceDictionary
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mwt="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
  xmlns:l="clr-namespace:LSX.Space.PropertyUI.NumericTextBox">

    <SolidColorBrush x:Key="CustomTextBox_Background" Color="White" />
    <SolidColorBrush x:Key="CustomTextBox_Foreground" Color="Black" />
    <LinearGradientBrush x:Key="CustomTextBox_Border" StartPoint="0,0" EndPoint="0,1">
        <GradientStop Color="#FFABADB3" Offset="0.05" />
        <GradientStop Color="#FFE2E3EA" Offset="0.07" />
        <GradientStop Color="#FFE3E9EF" Offset="1" />
    </LinearGradientBrush>

    <Style x:Key="{x:Type l:NumericTextBox}" TargetType="{x:Type l:NumericTextBox}">
        <Setter Property="Background" Value="{StaticResource CustomTextBox_Background}" />
        <Setter Property="BorderBrush" Value="{StaticResource CustomTextBox_Border}" />
        <Setter Property="Foreground" Value="{StaticResource CustomTextBox_Foreground}" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type l:NumericTextBox}">
                    <Border x:Name="Border"
                      Background="{TemplateBinding Background}"
                      BorderBrush="{TemplateBinding BorderBrush}"
                      BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid x:Name="LayoutGrid">
                            <ScrollViewer Margin="2" x:Name="PART_ContentHost" />
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <!--Message validation des erreurs-->
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="HasText" Value="True" />
                                <Condition Property="Validation.HasError" Value="True" />
                            </MultiTrigger.Conditions>
                            <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path= TextError}"/>
                            <Setter Property="Validation.ErrorTemplate">
                                <Setter.Value>
                                    <ControlTemplate>
                                        <DockPanel LastChildFill="True">
                                            <Image x:Name="ValidationIcon" DockPanel.Dock="Left" Stretch="None" Width="15" Height="15" Source="pack://application:,,,/LS.Net.Telcom.Space.PropertyUI;component/Images/validationError.png" />
                                            <Border BorderBrush="Red" BorderThickness="1">
                                                <AdornedElementPlaceholder />
                                            </Border>
                                        </DockPanel>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </MultiTrigger>

                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>
Run Code Online (Sandbox Code Playgroud)

非常感谢您的帮助。

Abe*_*cht 3

我刚刚对你的进行了快速测试Style,一切正常。然而,为了使 WPFStyle正常工作,您需要做一些事情。首先,您的自定义控件需要重写DefaultStyleKey其静态构造函数中的:

public class NumericTextBox : TextBox
{
    static NumericTextBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(
            typeof(NumericTextBox),
            new FrameworkPropertyMetadata(typeof(NumericTextBox)));
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)

第二个是您的NumericTextBox默认值Style需要在程序集中的特定位置定义才能被拾取。标准位置位于Project\Themes\Generic.xaml

如果您仍在为如何创建自定义 WPF 控件并设计它们的样式而苦苦挣扎,这里有一篇很棒的CodeProject 介绍性文章

bgcode的评论

TDefaultStyleKey,它仍然按照您的建议实现。第二个是我的 NumericTextBox 的样式作为资源字典实现到其他文件中,但我将其加载到构造函数中,如下所示:

    public NumericTextBox ()
        : base()
    {
        ResourceDictionary res = Application.LoadComponent(new Uri("/MyAssemblyName;component/NumericTextBox/NumericTextBoxStyle.xaml", UriKind.RelativeOrAbsolute)) as ResourceDictionary;
        if(res != null)
            this.Resources = res;
    }
Run Code Online (Sandbox Code Playgroud)

我认为这也是一个好方法,不是吗?

阿贝·海德布莱希特的回应

不,不要那样做。如果您想Style在单独的 中定义默认值ResourceDictionary,请这样做。只需将其合并到 generic.xaml 中即可:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="MyAssemblyName;component/NumericTextBox/NumericTextBoxStyle.xaml" />
    </ResourceDictionary.MergedDictionaries>

</ResourceDictionary>
Run Code Online (Sandbox Code Playgroud)

如果您确实不想使用 generic.xaml,您可以将字典合并到App.Resources您的app.xaml. 您宁愿将其放入的原因generic.xaml是,如果在某个时刻将此控件放入控件的程序集中,您将需要generic.xaml,否则 WPF 将不知道在哪里可以找到默认的Style. 最好养成以正确方式进行操作的习惯。