我正在使用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 工具中检查的可视树是相同的 (Button -> ContentPresenter -> TextBlock),但第一版创建的 TextBlock 的数据上下文设置为“Hello, World”,而第二版中的 TextBlock 只是设置了其文本属性。我认为这可能与控件创建的顺序有关 (在第一个版本中,按钮创建 TextBlock,在第二个版本中,TextBlock 可能先创建?对此真的不确定)。在研究过程中,我看到了一些在 Silverlight 中起作用的解决方案 (比如用 ContentControl 替换 ContentPresenter),但在 WPF 中不起作用 (程序会崩溃)。
由于这是在按钮的控件模板中,如果可能,我想使用 VSM,这也排除了显式更改按钮自身的前景属性 (我不知道怎样从模板内部访问它?)。
我非常感谢任何人能给予的帮助和建议。