【发布时间】:2011-04-20 21:13:06
【问题描述】:
使用 Silverlight 4 和 WPF 4,我正在尝试创建一个按钮样式,当按钮被鼠标悬停时,它会改变任何包含文本的文本颜色。由于我试图使其与 Silverlight 和 WPF 兼容,因此我正在使用可视状态管理器:
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="outerBorder" CornerRadius="4" BorderThickness="1" BorderBrush="#FF757679">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0" To="#FFFEFEFE"
Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)"
Storyboard.TargetName="contentPresenter"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Border x:Name="Background" CornerRadius="3" BorderThickness="1" BorderBrush="Transparent">
<Grid>
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}"/>
</Grid>
</Border>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
由于这是一个普通旧按钮的模板,我知道不能保证里面甚至有一个文本块,起初我不确定这是否可能。奇怪的是,如果按钮声明如下,文本颜色确实会改变:
<Button Content="Hello, World!" />
但如果按钮声明如下,它不会改变:
<Button>
<TextBlock Text="Hello, World!" /> <!-- Same result with <TextBlock>Hello, World </TextBlock> -->
</Button>
尽管可视化树(在 snoop 中检查时)是相同的(按钮 -> ContentPresenter -> TextBlock),但需要注意的是,在第一个版本中创建的文本块的数据上下文设置为“Hello, World”,而第二个版本中的文本块只设置了它的文本属性。我假设这与控件创建的顺序有关(第一个版本的按钮创建 TextBlock,在第二个版本中可能首先创建文本块?真的不确定)。
在研究此问题的过程中,我看到了一些在 Silverlight 中有效的解决方案(例如将 ContentPresenter 替换为 ContentControl),但在 WPF 中不起作用(程序实际上崩溃了)。
由于这是在按钮的控件模板中,如果可能的话我想使用 VSM,我认为这也排除了显式更改按钮自己的 Foreground 属性(我不知道如何从内部访问它模板?)
我非常感谢任何人提供的任何帮助和建议。
【问题讨论】:
-
考虑到 TextElement 与 TextBlock 没有任何关系,我很惊讶它完全有效。
标签: wpf silverlight button controltemplate visualstatemanager