WPF样式/模板继承 [英] WPF Styles/Template inheritance

查看:362
本文介绍了WPF样式/模板继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想学习WPF的那一刻,并寻找到使默认的.NET控件通过使用的风格有所不同。今天用C#作为我的首选语言,虽然下面的所有代码是WPF的标记。

I'm trying to learn WPF at the moment, and looking into making the default .Net control look different through the use of style. Using C# as my preferred language although all the code below is WPF markup.

我设置的Gmail的新主题,(见下图),因此把我的自我挑战,有可能在WPF来完成。

I setup gmail today with the new theme, (see image below) and thus set my self the challenge, could be done in WPF.

我已成功地实现是建立中间的按钮垃圾邮件通过使用风格,配以控件模板和触发器。

What I have managed to achieve is to create the middle button Spam through the use of a style with a control template and triggers.

的左,右按键非常相似,但只有2分歧。他们有一个1角半径和毛利的15对左右两侧,而中间的按钮有它们均设置为0。

The right and left buttons are very similar but with only 2 differences. They have a corner radius of 1 and margin of 15 on the left or right sides, whilst the middle button has them both set to 0.

的问题!

Q1。而不是复制整个风格和不断变化的只是那些2的属性,是否可以通过某种类型的继承完成。由左,右按键在哪里都是基于现有的风格,但它使那些2的视觉变化。创建新样式,但无法编辑所需要的属性时,我已经尝试过支持算法FMP属性。

Q1. Rather than copying the entire style and changing just those 2 attributes, can it be done via some type of inheritance. Where by the right and left buttons are based on an existing style but it makes those 2 visual changes. I have already tried the BasedOn property when creating a new style but was unable to edit the attributes needed.

Q2。是样式的正确方法在WPF来解决这个问题。在的WinForms,你会看创建一个自定义的控制,其中有连接到一个枚举可见的属性,就是你点击按钮的样式选项也许左,中,右。

Q2. Are styles the right way to address this problem in WPF. In WinForms you would look to create a custom control, which has a visible property linked to an enum, i.e. you click on the button and the style options maybe Left, Middle, Right.

Q3。直到最后一个最困难的问题。是否有可能使它的,所以如果一个按钮已经应用了我的风格。然后,当你设置的背景颜色为蓝说。然后按钮保持梯度,但不是他们被灰白色他们现在的蓝色阴影。即,背景线性渐变画笔是基于,而不是覆盖已施加到按钮的背景颜色。或做这些需要有单独定义的样式。我个人看不到没有一些类型的背后,这个代码可以实现的,即是从WPF标记单刷做渐变画笔。

Q3. The most difficult question til last. Is it possible to make it, so if a button has my style applied to it. Then when you set its background colour to say blue. Then the button maintains the gradients but instead of them been off-white they are now a shade of blue. i.e. the background linear gradient brush is based on, rather than overwrites the background colour that has been applied to the button. Or do these need to have separate styles defined. I personally cannot see without some type of code behind that this could be achieved, that is making gradient brushes from a single brush in WPF markup.

即。按钮下面一个蓝色按钮和一个灰色/普通按钮

i.e. buttons as below a blue button and a grey/normal button

myStyle的

<Style x:Key="GoogleMiddleButton" TargetType="{x:Type Button}">
        <Setter Property="Background">
            <Setter.Value>
                <LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
                    <GradientStop Color="#F1F1F1" Offset="0"/>
                    <GradientStop Color="#F5F5F5" Offset="1"/>
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
        <Setter Property="Foreground" Value="#666666"/>
        <Setter Property="FontFamily" Value="Arial"/>
        <Setter Property="FontSize" Value="13"/>
        <Setter Property="FontWeight" Value="Bold"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border Name="dropShadowBorder"
                        BorderThickness="0,0,0,1"
                        CornerRadius="1"
                        >
                        <Border.BorderBrush>
                            <SolidColorBrush Color="#00000000"/>
                        </Border.BorderBrush>
                    <Border Name="border" 
                    BorderThickness="{TemplateBinding BorderThickness}"
                    Padding="{TemplateBinding Padding}" 
                    CornerRadius="0" 
                    Background="{TemplateBinding Background}">
                        <Border.BorderBrush>
                            <SolidColorBrush Color="#D8D8D8"/>
                        </Border.BorderBrush>
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Border>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="BorderBrush" TargetName="border">
                                <Setter.Value>
                                    <SolidColorBrush Color="#939393"/>
                                </Setter.Value>
                            </Setter>
                            <Setter Property="BorderBrush" TargetName="dropShadowBorder">
                                <Setter.Value>
                                    <SolidColorBrush Color="#EBEBEB"/>
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Foreground" Value="#333333"/>
            </Trigger>
            <Trigger Property="IsPressed" Value="True">
                <Setter Property="Background">
                    <Setter.Value>
                        <LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
                            <GradientStop Color="#F1F1F1" Offset="1"/>
                            <GradientStop Color="#F5F5F5" Offset="0"/>
                        </LinearGradientBrush>
                    </Setter.Value>
                </Setter>
            </Trigger>
        </Style.Triggers>
    </Style>



P.S。如果你发现以上在WPF任何初学者的失误,随意点出来给我。

p.s. If you spot any beginner mistakes in the WPF above, feel free to point them out to me.

推荐答案

我做这个在过去的定义附加属性称为 ExtendedProperties.CornerRadius 。然后我就可以把它在我的风格:

I've done this in the past by defining an attached property called ExtendedProperties.CornerRadius. I can then set it in my style:

<Style TargetType="Button">
    <Setter Property="local:ExtendedProperties.CornerRadius" Value="0"/>
    ...

和模板中使用它:

<Border CornerRadius="{Binding Path=(local:ExtendedProperties.CornerRadius), RelativeSource={RelativeSource TemplatedParent}">



我可能然后在本地重写它以同样的方式我重写任何其他属性:

I might then override it locally in the same way I override any other property:

<Button Content="Archive" local:ExtendedProperties.CornerRadius="5,0,0,5"/>
<Button Content="Span"/>
<Button Content="Delete" local:ExtendedProperties.CornerRadius="0,5,5,0"/>

在我的情况,这给了我(很明显,我的主题是暗的):

In my case, this gives me (obviously, my theme is dark):

和刚刚调整了几个我的主题的附加属性,我创造了这个效果:

And just by tweaking a couple of my theme's attached properties, I created this effect:

这种方法的优点是没有必要的子类按钮。您也可以使用相同的附加属性来定义其他控件(如文本框)圆角半径。而你不仅限于圆角半径,当然。你可以为各种具体到你的主题的东西都是不存在的基础控件定义附加属性。

The advantage of this approach is that there's no need to subclass Button. You can also use that same attached property to define corner radii for other controls (such as TextBox). And you're not limited to just corner radius, of course. You could define attached properties for all sorts of things specific to your theme that aren't present on base controls.

的缺点是,它是一个附加的属性,因而更难发现。 。记录你的主题将有助于在这方面

The disadvantage is that it's an attached property and thus harder to discover. Documenting your theme will help in this respect.

因此​​,要回答你的具体问题:

So, to answer your specific questions:

Q1。是的,看到我的回答以上。你可以在本地覆盖或定义新的样式重写属性。

Q1. Yes, see my answer above. You can either override locally or define new styles that override the property.

Q2。这是一个灰色地带。在我看来,如果是纯粹的视觉(不行为),那么样式是要走的路。当然,如果失控,你也可能会希望继承所有内置控件,并添加特定的属性。但是,让你的主题很难再利用和你的应用更加繁重的发展(因为你需要使用你的控制设置,而不是标准的)。

Q2. It's a gray area. In my opinion, if it's purely visual (not behavioural) then styles are the way to go. Of course, if it gets out of hand you may instead wish to subclass all the built-in controls and add your specific properties. But that makes your theme harder to re-use and your application more onerous to develop (because you need to use your control set rather than the standard ones).

Q3。我会说这是可能的代码,但不直观作为控制消费者使用。我想你会更好界定额外的附加属性 - 例如。 ExtendedProperties.HoverBackground ExtendedProperties.PressedBackground - 在完全相同的方式使用这些从您的模板。然后,你无法控制的消费者则有超过使用刷子更多的控制权,当你控制的是各种状态。我已经在过去做到了这一点,但使用了更通用的属性名称( SecondaryBackground TernaryBackground ),所以我可以重用在其他环境中的那些性质。同样,记录你的主题是很有帮助的。

Q3. I'd say it's possible in code, but not intuitive to use as a control consumer. I think you'd be better off defining extra attached properties - eg. ExtendedProperties.HoverBackground, ExtendedProperties.PressedBackground - and using those from your template in exactly the same way. Then consumers of your control then have more control over the brushes used when your control is in its various states. I've done this in the past but have used more generic property names (SecondaryBackground, TernaryBackground) so I can reuse those properties in other contexts. Again, documenting your theme is helpful.

这篇关于WPF样式/模板继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆