wpf 如何使用 VisualStateManager 设置按钮样式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27551107/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to style a button with VisualStateManager
提问by MorgoZ
i want to define the style of some buttons of my WPF application at the Window level. Here is the code:
我想在窗口级别定义我的 WPF 应用程序的某些按钮的样式。这是代码:
<Style x:Key="MainButtonStyle" TargetType="Button">
<Setter Property="Width" Value="120"/>
<Setter Property="Height" Value="60"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Background" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid x:Name="ButtonGrid">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<!--Take one half second to transition to the MouseOver state.-->
<VisualTransition To="MouseOver" GeneratedDuration="0:0:0.5" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0" Storyboard.TargetName="ButtonGrid" Storyboard.TargetProperty="Background" To="Cyan"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Duration="0" Storyboard.TargetName="ButtonGrid" Storyboard.TargetProperty="Background" To="Red"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
What i want to do is to define some style properties of the button like Width or Color and also set a VisualState to stablish the behaviour of the button on Pressed, MouseOver, etc.
我想要做的是定义按钮的一些样式属性,如宽度或颜色,并设置一个 VisualState 以稳定按钮在按下、鼠标悬停等时的行为。
But that code does not work, because once the "Template" property is defined, all other properties (Width, Margin, etc) are forgotten, what is the proper way to make it work? Should i define all the button properties inside the "Grid" Properties of the Template?
但是该代码不起作用,因为一旦定义了“模板”属性,所有其他属性(宽度、边距等)都会被遗忘,使其工作的正确方法是什么?我应该在模板的“网格”属性中定义所有按钮属性吗?
Thank you.
谢谢你。
EDIT: A SOLUTION. BUT I DON'T UNDERSTAND WHY
编辑:一个解决方案。但我不明白为什么
Ok, i have a solution, now it is working fine but i still don't understand why does WPF behaves this way. I'm new in this language and it is realy hard to know what property to work with in different Controls and how to implement it... I'm finding it zero intuitive in many cases... I hope it is just that i'm a newbie.
好的,我有一个解决方案,现在它工作正常,但我仍然不明白为什么 WPF 会这样。我是这种语言的新手,很难知道在不同的控件中使用什么属性以及如何实现它......我发现在许多情况下它的直观性为零......我希望这只是我我是新手。
Any case, the problem was twice:
无论如何,问题是两次:
First: All the properties set by the "MainButtonStyle" works fine except the "Background", which seems to be overriden by the Grid at the ControlTemplate, so i had to set the BackGround property at the Grid in place of setting it at the Button... I don't finish to understand why is it happening.
第一:“MainButtonStyle”设置的所有属性都可以正常工作,除了“Background”,它似乎被 ControlTemplate 中的 Grid 覆盖,所以我必须在 Grid 中设置 BackGround 属性,而不是在 Button 上设置它......我不明白为什么会这样。
Second: The "StoryBoard.TargetProperty="Background" can't be assigned to a Color object, i had to specify "StoryBoard.TargetProperty="BackGround.Color" to properly assign a Color object. And like before, i don't understand why. If in other Controls i can set the BackGround property directly to a Color value like "BackGround = "Red", why in a StoryBoard i have to set it "BackGround.Color="Red"?
第二:不能将“StoryBoard.TargetProperty="Background”分配给颜色对象,我必须指定“StoryBoard.TargetProperty="BackGround.Color”才能正确分配颜色对象。和以前一样,我不明白为什么。如果在其他控件中我可以将 BackGround 属性直接设置为“BackGround =“Red”之类的颜色值,为什么在 StoryBoard 中我必须将其设置为“BackGround.Color =“Red”?
Ok, now the code working:
好的,现在代码工作:
<Style x:Key="MainButtonStyle" TargetType="Button">
<Setter Property="Width" Value="120"/>
<Setter Property="Height" Value="60"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Background="White" x:Name="ButtonGrid">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0:0:0.3" Storyboard.TargetName="ButtonGrid" Storyboard.TargetProperty="Background.Color" To="Cyan"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Duration="0:0:0.2" Storyboard.TargetName="ButtonGrid" Storyboard.TargetProperty="Background.Color" To="DarkSalmon"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
So, there is the solution, but if someone could explain better WHY, i would appreciate it.
所以,有解决方案,但如果有人能更好地解释为什么,我将不胜感激。
回答by user2825546
When you are defining a style for a control and you are also overriding the default control template the button no longer has its default layout. It only contains those elements you define in the control template. IN THE ABOVE CASE THE BUTTON ONLY CONTAINS ONE GRID.
当您为控件定义样式并且还覆盖默认控件模板时,按钮不再具有其默认布局。它只包含您在控制模板中定义的那些元素。在上述情况下,按钮仅包含一个网格。

