【问题标题】:How to update the color of the ToggleButton content?如何更新 ToggleButton 内容的颜色?
【发布时间】:2012-06-19 00:27:15
【问题描述】:

对于我的 WP7 应用,当 ToggleButton 处于选中状态时,我希望内容颜色会反转(按钮从黑色变为白色,文本从白色变为黑色)。当内容是文本时,这非常有用,因为 ToggleButton 负责更改颜色。但是,对于其他类型的内容,例如 Patch 对象,情况并非如此。我用一个 Path 对象替换了 ToggleButton 的内容,它的颜色没有改变(当处于选中状态时,ToggleButton 背景从黑色变为白色,而 Path 对象保持白色而不是黑色)。

我做的第一件事是将 Path 对象的 Fill 属性绑定到它的父前景色。但这也没有用。我可以尝试使用 DataTrigger,但 Silverlight/WP 不支持它们。

我更新了文本以使用路径(绘制暂停符号),并且路径的颜色与文本的行为不同。知道为什么吗?我该如何解决?

<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>

【问题讨论】:

    标签: c# wpf silverlight xaml


    【解决方案1】:

    使用CheckedUnchecked 事件:

    <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>
    

    并应用ToogleButton 背景和Path 填充:

    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;
    }
    

    ToggleButtonStyle 用于(如果需要)在光标悬停或按下按钮时禁用 Microsoft_Windows_Themes:ButtonChrome 行为:

    <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>
    

    【讨论】:

    • 为什么我没有想到使用 Checked 和 Unchecked 事件?我正在尝试点击/点击事件。它工作得很好。我会更喜欢使用 XAML 的解决方案,但它现在可以完成这项工作。谢谢镀金风筝!
    • @Martin 如果您不想使用后面的代码,您可以在 IsChecked 上使用转换器和绑定(切换按钮的自己的值或祖先的 IsChecked小路)。然后转换器将布尔值转换为颜色。
    【解决方案2】:

    我不得不猜测在某处定义了文本行为的样式(TextBlock)。

    您可以通过对路径使用以下样式来实现相同的效果:

        <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>
    

    【讨论】:

    • 很遗憾,WP7/Silverlight 不支持 DataTrigger。
    【解决方案3】:

    尝试在您的风格中使用 VisualStates,您可以使用 Expression Blend 轻松完成。

    在我的帖子末尾是我的风格示例,我将内容演示者的前景在禁用时设置为另一种颜色。

    Button 和 ToggleButton 之间的唯一区别在于它具有 Toggled 状态,您必须在其中添加状态并更改前景。 状态看起来有点像这样:

    <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>
    

    所以这是我的按钮样式的一个例子。只需创建您自己的并将其分配给您的 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>
    

    【讨论】:

      【解决方案4】:

      尝试下一步:

      <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>
      

      它应该可以工作。

      【讨论】:

      • 或者试试这个:Fill="{Binding Foreground, RelativeSource={RelativeSource Self}}"
      • 这是我尝试的第一件事,但它不起作用。当 ToggleButton 处于 Checked 状态时,Foreground 值不会更新。
      猜你喜欢
      • 1970-01-01
      • 2021-03-21
      • 2019-04-29
      • 1970-01-01
      • 2019-07-30
      • 1970-01-01
      • 2021-12-14
      • 2015-03-04
      • 2015-04-17
      相关资源
      最近更新 更多