7
votes

For my WP7 app, when a ToggleButton is in a checked state, I expect the content color to reverse (button turns from black to white and text from white to black). This work great when the content is text since the ToggleButton takes care of changing the color. However, this isn’t the case for other type of content such as a Patch object. I replaced the content of my ToggleButton with a Path object and it’s color isn’t changing (when in a checked state, the ToggleButton background turns from black to white and the Path object stays white instead of turning black).

The first thing I did is to bind the Fill property of the Path object to it's parent foreground color. But that didn't work either. I could be trying to use DataTrigger, but Silverlight/WP doesn't support them.

I updated the text to use a Path (drawing of pause symbol) and the color of the path doesn't follow the same behavior of the text. Any idea why? How could I fix that?

<ToggleButton Grid.Column="0" x:Name="PauseButton">
    <ToggleButton.Content>
        <Path Name="PauseIcon" Fill="White" 
                Data="M0,0 0,27 8,27 8,0z M14,0 14,27 22,27 22,0" />
    </ToggleButton.Content>
</ToggleButton>
4

4 Answers

7
votes

Use Checked and Unchecked events:

<ToggleButton Grid.Column="0" x:Name="PauseButton" 
              Background="Black"
              Checked="PauseButton_Checked"
              Unchecked="PauseButton_Unchecked" 
              Style="{DynamicResource ToggleButtonStyle}">
    <Path x:Name="PauseIcon" Fill="White" 
        Data="M0,0 0,27 8,27 8,0z M14,0 14,27 22,27 22,0" />
</ToggleButton>

And apply the ToogleButton background and the Path fill:

private void PauseButton_Checked(object sender, RoutedEventArgs e)
{
    (sender as ToggleButton).Background = Brushes.White;
    PauseIcon.Fill = Brushes.Black;
}

private void PauseButton_Unchecked(object sender, RoutedEventArgs e)
{
    (sender as ToggleButton).Background = Brushes.Black;
    PauseIcon.Fill = Brushes.White;
}

The ToggleButtonStyle is used (if you want) to disable the Microsoft_Windows_Themes:ButtonChrome behavior when the cursor is over the button, or it's pressed:

<Style x:Key="ButtonFocusVisual">
    <Setter Property="Control.Template">
        <Setter.Value>
            <ControlTemplate>
                <Rectangle Stroke="Black" StrokeDashArray="1 2"
                            StrokeThickness="1" Margin="2" 
                            SnapsToDevicePixels="true"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
    <GradientStop Color="#F3F3F3" Offset="0"/>
    <GradientStop Color="#EBEBEB" Offset="0.5"/>
    <GradientStop Color="#DDDDDD" Offset="0.5"/>
    <GradientStop Color="#CDCDCD" Offset="1"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/>
<Style x:Key="ToggleButtonStyle" TargetType="{x:Type ToggleButton}">
    <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
    <Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
    <Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Padding" Value="1"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ToggleButton}">
                <Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" SnapsToDevicePixels="true" 
                                                        Background="{TemplateBinding Background}" 
                                                        BorderBrush="{TemplateBinding BorderBrush}" 
                                                        RenderDefaulted="{TemplateBinding Button.IsDefaulted}">
                    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                        Margin="{TemplateBinding Padding}" 
                                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                        RecognizesAccessKey="True"/>
                </Microsoft_Windows_Themes:ButtonChrome>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="#ADADAD"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
1
votes

I would have to guess that there is a style somewhere defining the behavior for the text (TextBlock).

You can achieve the same by using the following style for the path:

    <ToggleButton Grid.Column="0" x:Name="PauseButton">
        <ToggleButton.Content>
            <Path Name="PauseIcon" Data="M0,0 0,27 8,27 8,0z M14,0 14,27 22,27 22,0">
                <Path.Style>
                    <Style TargetType="{x:Type Path}">
                        <Setter Property="Fill" Value="White"></Setter>
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding ElementName=PauseButton, Path=IsChecked}" Value="True">
                                <Setter Property="Fill" Value="Black"></Setter>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </Path.Style>
            </Path>
        </ToggleButton.Content>
    </ToggleButton>
1
votes

Try using VisualStates in your style, You can do it very easily with Expression Blend.

At the end of my post is an example of my style where I put the foreground of my content presenter on another color when it is disabled.

The single difference between a Button and ToggleButton is that is has a Toggled-state where you'll have to add a state and change your foreground. The state will look somewhat like this :

<VisualState x:Name="Disabled">
                                        <Storyboard>
                                            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle">
                                                <EasingColorKeyFrame KeyTime="0" Value="#FF7052A8"/>
                                            </ColorAnimationUsingKeyFrames>
                                        <ColorAnimation Duration="0" To="#FFbab0c7" Storyboard.TargetName="contentPresenter"
                                                                        Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)" />
                                        </Storyboard>
                                    </VisualState>

So this a an example of my Button-style. Just create your own and assign it to your ToggleButton.

<Style TargetType="{x:Type Button}">
        <Setter Property="Padding" Value="1"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal">
                                <Storyboard>
                                    <ColorAnimation Duration="0" To="White" Storyboard.TargetName="contentPresenter"
                                                                    Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)" />
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="MouseOver">
                                    <Storyboard>
                                        <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle">
                                            <EasingColorKeyFrame KeyTime="0" Value="#FF532B8C"/>
                                        </ColorAnimationUsingKeyFrames>
                                </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.HorizontalAlignment)" Storyboard.TargetName="contentPresenter">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static HorizontalAlignment.Center}"/>
                                    </ObjectAnimationUsingKeyFrames> 
                                    <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle">
                                        <EasingColorKeyFrame KeyTime="0" Value="#FF6137ae"/>
                                    </ColorAnimationUsingKeyFrames>
                                </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Disabled">
                                    <Storyboard>
                                        <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle">
                                            <EasingColorKeyFrame KeyTime="0" Value="#FF7052A8"/>
                                        </ColorAnimationUsingKeyFrames>
                                    <ColorAnimation Duration="0" To="#FFbab0c7" Storyboard.TargetName="contentPresenter"
                                                                    Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)" />
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>

                        <Rectangle x:Name="rectangle" Fill="#FF371C69" RadiusX="10" RadiusY="10"/>

                    <ContentPresenter x:Name="contentPresenter" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center"/>

                </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsKeyboardFocused" Value="true"/>
                        <Trigger Property="ToggleButton.IsChecked" Value="true"/>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
0
votes

Try do next:

<ToggleButton Grid.Column="0" x:Name="PauseButton">
    <ToggleButton.Content>
        <Path Name="PauseIcon" Fill="{Binding ElementName=PauseButton, Path=Foreground}" 
                Data="M0,0 0,27 8,27 8,0z M14,0 14,27 22,27 22,0" />
    </ToggleButton.Content>
</ToggleButton>

It should work.