WPF自定义控件没有渲染样式

huangapple go评论67阅读模式
英文:

WPF Custom controls don't have rendering styles

问题

I create a custom control library like this:
enter image description here

KiwiButton.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:KiwiWPFControl.Controls">
    <Style x:Key="KiwiButtonStyle" TargetType="local:KiwiButton">
        <Setter Property="FontSize" Value="30"/>
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="Background">
            <Setter.Value>
                <LinearGradientBrush EndPoint="1,1" StartPoint="0,0">
                    <GradientStop Color="#FF00AA11" Offset="0"/>
                    <GradientStop Color="#FF00AA88" Offset="0.5"/>
                    <GradientStop Color="#FF00AAA6" Offset="1"/>
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:KiwiButton">
                    <Border BorderThickness="1" CornerRadius="15" Background="Transparent">
                        <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="Button.IsMouseOver" Value="True">
                            <Setter Property="Button.Background" Value="#AA00AAA6"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style BasedOn="{StaticResource KiwiButtonStyle}" TargetType="local:KiwiButton"/>
</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="/KiwiWPFControl;component/Themes/KiwiButton.xaml"/>
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

KiwiButton.cs:

namespace KiwiWPFControl.Controls
{
    public class KiwiButton : Button
    {
        static KiwiButton()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(KiwiButton), new FrameworkPropertyMetadata(typeof(KiwiButton)));
        }
    }
}

And I use this button like this

App.xaml:

<Application x:Class="KiwiWPFDemo.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:KiwiWPFDemo"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/KiwiWPFControl;component/Themes/Generic.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

MainWindow.xaml:

<Window x:Class="KiwiWPFDemo.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:KiwiWPFDemo"
        mc:Ignorable="d"
        xmlns:kiwi="clr-namespace:KiwiWPFControl.Controls;assembly=KiwiWPFControl"
        Height="450" Width="800">
    <Grid>
        <kiwi:KiwiButton Width="200" Height="100" Content="12"/>
    </Grid>
</Window>

It compiles and runs successfully

But it shows this:enter image description here

How to make the style of the control take effect??

英文:

I create a custom control library like this:
enter image description here

KiwiButton.xaml:

&lt;ResourceDictionary xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
                xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
                xmlns:local=&quot;clr-namespace:KiwiWPFControl.Controls&quot;&gt;
&lt;Style x:Key=&quot;KiwiButtonStyle&quot; TargetType=&quot;local:KiwiButton&quot; &gt;
    &lt;Setter Property=&quot;FontSize&quot; Value=&quot;30&quot;/&gt;
    &lt;Setter Property=&quot;Foreground&quot; Value=&quot;White&quot;/&gt;
    &lt;Setter Property=&quot;Background&quot;&gt;
        &lt;Setter.Value&gt;
            &lt;LinearGradientBrush EndPoint=&quot;1,1&quot; StartPoint=&quot;0,0&quot;&gt;
                &lt;GradientStop Color=&quot;#FF00AA11&quot; Offset=&quot;0&quot;/&gt;
                &lt;GradientStop Color=&quot;#FF00AA88&quot; Offset=&quot;0.5&quot;/&gt;
                &lt;GradientStop Color=&quot;#FF00AAA6&quot; Offset=&quot;1&quot;/&gt;
            &lt;/LinearGradientBrush&gt;
        &lt;/Setter.Value&gt;
    &lt;/Setter&gt;
    &lt;Setter Property=&quot;Template&quot;&gt;
        &lt;Setter.Value&gt;
            &lt;ControlTemplate TargetType=&quot;local:KiwiButton&quot; &gt;
                &lt;Border BorderThickness=&quot;1&quot; CornerRadius=&quot;15&quot; Background=&quot;Transparent&quot;&gt;
                    &lt;ContentPresenter VerticalAlignment=&quot;Center&quot; HorizontalAlignment=&quot;Center&quot;/&gt;
                &lt;/Border&gt;
                &lt;ControlTemplate.Triggers &gt;
                    &lt;Trigger Property=&quot;Button.IsMouseOver&quot; Value=&quot;True&quot;&gt;
                        &lt;Setter Property=&quot;Button.Background&quot; Value=&quot;#AA00AAA6&quot;/&gt;
                    &lt;/Trigger &gt;
                &lt;/ControlTemplate.Triggers &gt;
            &lt;/ControlTemplate &gt;
        &lt;/Setter.Value&gt;
    &lt;/Setter&gt;
&lt;/Style &gt;
&lt;Style BasedOn=&quot;{StaticResource KiwiButtonStyle}&quot; TargetType=&quot;local:KiwiButton&quot;/&gt;

</ResourceDictionary>

Generic.xaml:

&lt;ResourceDictionary
xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;&gt;
&lt;ResourceDictionary.MergedDictionaries&gt;
    &lt;ResourceDictionary Source=&quot;/KiwiWPFControl;component/Themes/KiwiButton.xaml&quot;/&gt;
&lt;/ResourceDictionary.MergedDictionaries&gt;

</ResourceDictionary>

KiwiButton.cs:

namespace KiwiWPFControl.Controls{
public class KiwiButton : Button
{
    static KiwiButton()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(KiwiButton), new FrameworkPropertyMetadata(typeof(KiwiButton)));
    }
}

}

And I use this button like this

App.xaml:

&lt;Application x:Class=&quot;KiwiWPFDemo.App&quot;
         xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
         xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
         xmlns:local=&quot;clr-namespace:KiwiWPFDemo&quot;
         StartupUri=&quot;MainWindow.xaml&quot;&gt;
&lt;Application.Resources&gt;
    &lt;ResourceDictionary&gt;
        &lt;ResourceDictionary.MergedDictionaries&gt;
            &lt;ResourceDictionary Source=&quot;pack://application:,,,/KiwiWPFControl;component/Themes/Generic.xaml&quot;/&gt;
        &lt;/ResourceDictionary.MergedDictionaries&gt;
    &lt;/ResourceDictionary&gt;
&lt;/Application.Resources&gt;

</Application>

MainWindow.xaml:

&lt;Window x:Class=&quot;KiwiWPFDemo.MainWindow&quot;
    xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
    xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
    xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;
    xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
    xmlns:local=&quot;clr-namespace:KiwiWPFDemo&quot;
    mc:Ignorable=&quot;d&quot;
    xmlns:kiwi=&quot;clr-namespace:KiwiWPFControl.Controls;assembly=KiwiWPFControl&quot;
    Height=&quot;450&quot; Width=&quot;800&quot;&gt;
&lt;Grid&gt;
    &lt;kiwi:KiwiButton Width=&quot;200&quot; Height=&quot;100&quot; Content=&quot;12&quot;/&gt;
&lt;/Grid&gt;

</Window>

It compiles and runs successfully

But it shows this:enter image description here

How to make the style of the control take effect??

答案1

得分: 0

在你的控件模板中,你应该使用TemplateBinding来绑定背景属性。在你的标记中,你设置了该属性,但没有在任何地方使用它。

这强调了你在模板化中需要记住的一点。

一旦你替换了控件的模板,除了你设置的内容之外,视觉上不会有其他内容。

然后,你可以潜在地删除设置DefaultStyleKeyProperty的代码行。

<Style TargetType="local:KiwiButton">
    <Setter Property="FontSize" Value="30"/>
    <Setter Property="Foreground" Value="White"/>
    <Setter Property="Background">
        <Setter.Value>
            <LinearGradientBrush EndPoint="1,1" StartPoint="0,0">
                <GradientStop Color="#FF00AA11" Offset="0"/>
                <GradientStop Color="#FF00AA88" Offset="0.5"/>
                <GradientStop Color="#FF00AAA6" Offset="1"/>
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:KiwiButton">
                <Border BorderThickness="1" CornerRadius="15" Background="{TemplateBinding Background}">
                    <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="Button.IsMouseOver" Value="True">
                        <Setter Property="Button.Background" Value="#AA00AAA6"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

此外,在kiwibutton.xaml中,你删除了以下行:

<Style BasedOn="{StaticResource KiwiButtonStyle}" TargetType="local:KiwiButton"/>

正如Clemens在评论中指出的那样。

当你设置TargetType时,自动获取该类型作为x:Key。有些人喜欢明确设置它:

x:Key="{x:Type local:KiwiButton}"

这是我为几个客户工作时的标准做法,我也习惯这样做。

英文:

In your controltemplate, you should use templatebinding with the background. In your markup, you set the property but it is not used anywhere.

This highlights one of the things you need to bear in mind with templating.

Once you've replaced the template of a control then there is nothing there visually other than whatever you set.

You can then potentially remove the line of code sets defaultstylekeyproperty

&lt;Style  TargetType=&quot;local:KiwiButton&quot; &gt;
    &lt;Setter Property=&quot;FontSize&quot; Value=&quot;30&quot;/&gt;
    &lt;Setter Property=&quot;Foreground&quot; Value=&quot;White&quot;/&gt;
    &lt;Setter Property=&quot;Background&quot;&gt;
        &lt;Setter.Value&gt;
            &lt;LinearGradientBrush EndPoint=&quot;1,1&quot; StartPoint=&quot;0,0&quot;&gt;
                &lt;GradientStop Color=&quot;#FF00AA11&quot; Offset=&quot;0&quot;/&gt;
                &lt;GradientStop Color=&quot;#FF00AA88&quot; Offset=&quot;0.5&quot;/&gt;
                &lt;GradientStop Color=&quot;#FF00AAA6&quot; Offset=&quot;1&quot;/&gt;
            &lt;/LinearGradientBrush&gt;
        &lt;/Setter.Value&gt;
    &lt;/Setter&gt;
    &lt;Setter Property=&quot;Template&quot;&gt;
        &lt;Setter.Value&gt;
            &lt;ControlTemplate TargetType=&quot;local:KiwiButton&quot; &gt;
                &lt;Border BorderThickness=&quot;1&quot; CornerRadius=&quot;15&quot; 
                        Background=&quot;{TemplateBinding Background}&quot;&gt;
                    &lt;ContentPresenter VerticalAlignment=&quot;Center&quot; HorizontalAlignment=&quot;Center&quot;/&gt;
                &lt;/Border&gt;
                &lt;ControlTemplate.Triggers &gt;
                    &lt;Trigger Property=&quot;Button.IsMouseOver&quot; Value=&quot;True&quot;&gt;
                        &lt;Setter Property=&quot;Button.Background&quot; Value=&quot;#AA00AAA6&quot;/&gt;
                    &lt;/Trigger &gt;
                &lt;/ControlTemplate.Triggers &gt;
            &lt;/ControlTemplate &gt;
        &lt;/Setter.Value&gt;
    &lt;/Setter&gt;
&lt;/Style &gt;

WPF自定义控件没有渲染样式

BTW the above style is all that's in my kiwibutton.xaml, I removed the line:

  &lt;Style BasedOn=&quot;{StaticResource KiwiButtonStyle}&quot; TargetType=&quot;local:KiwiButton&quot;/&gt;

As Clemens pointed out in comments.

When you set targettype you automatically get the type as an x:Key.

Some people prefer to also set that explicitly.

 x:Key=&quot;{x:Type local:KiwiButton}&quot;

This a standard at several clients I have worked for and I am in the habit of doing this myself.

huangapple
  • 本文由 发表于 2023年2月8日 16:31:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/75383075.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定