Reputation: 117
I'm still learning Blend, so please bear with me. I have a toggle button in a WPF project and I need to change the text color for different states such as mouseover and checked. However, when I'm editing the template and I select the contentPresenter, the only brush is OpacityMask and it is not affected by any brush color changes.
I can of course change the text color by editing the style, but this is not useful as it is within the states I'm interesting in editing.
Basically, I simply want the text of the button to change on mouseover, hover, etc, this seems a reasonable thing to do, but the OpacityMask Brush of the ContentPresenter cannot be edited.
Someone mentioned to change the ContentPresenter into a ContentControl. This does work, but I now cannot edit the text for an instance of the button. Do I have to link the ContentControl to something?
Many thanks for any help. I'm stuck right here for a few hours and I've been searching everywhere for the answer, to no avail
Upvotes: 4
Views: 13867
Reputation: 17398
You can do what your looking for without having to use a ContentControl
and by just using the VisualStateManager
I can of course change the text color by editing the style, but this is not useful as it is within the states I'm interesting in editing.
So say for example the state to apply a new Foreground
color to the text of your Button
is MouseOver
,
Brush
resource for Button.MouseOver.Foreground
when editing a Button
template.so let's create one. (Just add the following line along with the other brush resources)
<SolidColorBrush x:Key="Button.MouseOver.Foreground" Color="Tomato" />
Storyboard
to the TextElement.Foreground
of the contentPresenter
.so your VSM will look like:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="contentPresenter"
Storyboard.TargetProperty="(TextElement.Foreground)">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush Color="{Binding Source={StaticResource Button.MouseOver.Foreground}, Path=Color}" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed"/>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
and that's it.
Do note what we're doing here would be fine only when the Content
of the Button
is just text, but since that's what your usage is as mentioned in your question, you should be fine.
Sidenote:
You can do the exact same thing by just switching the ContentPresenter
to a TextBlock
in the ControlTemplate
.
If you need the Foreground
to be available for any Content
of the Button
, then yeh just switch the ContentPresenter
to a ContentControl
and you can still your VSM Storyboard's in a very similar way.
Update:
To switch the ContentPresenter
to a ContentControl
, in your ControlTemplate
just switch the actual element with the new one.
<ControlTemplate TargetType="{x:Type Button}">
...
<ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/>
...
</ControlTemplate>
to:
<ControlTemplate TargetType="{x:Type Button}">
...
<ContentControl x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Content="{TemplateBinding Content}"/>
...
</ControlTemplate>
you would have to update their properties accordingly like for eg ContentControl
does not support RecognizesAccessKeys
and it also needs Content="{TemplateBinding Content}"
set on it to actually show the content. With a ContentPresenter
the Content
property is set implicitly.
Upvotes: 1
Reputation: 4538
Foreground property is present in Style. So you can edit Style and there you can set Foreground
. It could be something like this
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Foreground" Value="Blue"/>
</Trigger>
</Style.Triggers>
Or if you want to change it in ControlTemplate
then you can do it like this.
<Trigger Property="IsChecked" Value="True">
<Setter Property="TextBlock.Foreground" TargetName="contentPresenterName" Value="White"/>
</Trigger>
So in expression blend you do it like this
Upvotes: 1