【问题标题】:How do I change the text color of a button for different states in Expression Blend?如何在 Expression Blend 中针对不同状态更改按钮的文本颜色?
【发布时间】:2013-07-09 09:10:47
【问题描述】:

我还在学习 Blend,所以请多多包涵。我在 WPF 项目中有一个切换按钮,我需要更改不同状态的文本颜色,例如鼠标悬停和选中。但是,当我在编辑模板并选择 contentPresenter 时,唯一的画笔是 OpacityMask,它不受任何画笔颜色变化的影响。

我当然可以通过编辑样式来更改文本颜色,但这没有用,因为它在我感兴趣的状态中编辑。

基本上,我只是想让按钮的文本在鼠标悬停、悬停等时改变,这似乎是一个合理的做法,但是 ContentPresenter 的 OpacityMask Brush 无法编辑。

有人提到将 ContentPresenter 更改为 ContentControl。这确实有效,但我现在无法编辑按钮实例的文本。我是否必须将 ContentControl 链接到某些东西?

非常感谢您的帮助。我被困在这里几个小时,我一直在到处寻找答案,但无济于事

【问题讨论】:

  • 我不明白你为什么不能这样做。
  • 嗨 Viktor,非常感谢您的回答,但是我想尽可能避免触发,因为我正在寻找更灵活的东西(即设置并忘记它),因为我正在做很多事情使用文本属性,并且不想每次都设置触发器。 Viv 的答案是我遵循的答案,不过是更新部分,因为这让我可以像处理普通文本框一样处理文本。非常感谢您的帮助

标签: wpf user-interface expression-blend blend


【解决方案1】:

您无需使用ContentControl,只需使用VisualStateManager,即可完成您所寻找的工作

我当然可以通过编辑样式来更改文本颜色,但这没什么用,因为它在我感兴趣的编辑状态中。

例如,将新的Foreground 颜色应用于Button 的文本的状态是MouseOver

  • 首先,在编辑 Button 模板时,Blend 不会为 Button.MouseOver.Foreground 创建 Brush 资源。

所以让我们创建一个。 (只需添加以下行以及其他画笔资源)

<SolidColorBrush x:Key="Button.MouseOver.Foreground" Color="Tomato" />
  • 现在我们可以将Storyboard 应用于contentPresenterTextElement.Foreground

所以您的 VSM 将如下所示:

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

就是这样。

请注意我们在这里所做的事情只有ButtonContent 只是文本时,但由于这就是您在问题中提到的用法,您应该没问题。

旁注:

您只需将ContentPresenter 中的TextBlock 切换为ControlTemplate 中的TextBlock,即可完成完全相同的操作。

如果您需要Foreground 可用于Button 中的任何Content,那么您只需将ContentPresenter 切换为ContentControl,您仍然可以以非常相似的方式使用您的VSM Storyboard。

更新

要将ContentPresenter 切换为ContentControl,只需在ControlTemplate 中将实际元素切换为新元素即可。

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

到:

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

您必须相应地更新它们的属性,例如ContentControl 不支持RecognizesAccessKeys,它还需要在其上设置Content="{TemplateBinding Content}" 才能实际显示内容。对于ContentPresenterContent 属性是隐式设置的。

【讨论】:

  • 嗨 Viv,非常感谢,我现在正在尝试。只有一件事 - 是否可以将 ContentPresenter 更改为 ContentControl,我该怎么做?或者,如果我在控件模板中添加了一个 ContentControl 或文本块,我该如何使文本块现在成为按钮的内容部分?
  • @JohnRooney 在帖子底部查看我的更新。也只需搜索自定义Button.Style 的其他示例,您会找到一些关于这些的不错示例。如果我把我能想到的每一点都加进去,我们会在这里待上几个小时。使用像wpf button ContentPresenter vs ContentControlwpf button Apply dynamic color to child controlswpf why use templateBinding 这样的谷歌搜索词,你应该有很多东西可以阅读:)
  • 非常感谢 viv,我关注了你的上次更新,我需要对文本做更多的事情,所以将它直接换成内容控件是一个更好的选择。谢谢,你帮我省了很多麻烦,我在任何地方都找不到解决方案
  • viv,你介意帮我解决我的新问题:创建自定义标题栏吗?谢谢
  • Viv,我遇到了很多问题,并且还想了解更多有关 Blend 和 WPF 的信息。你愿意和我一起做半天/全天的付费咨询吗?
【解决方案2】:

Style 中存在 Foreground 属性。因此您可以编辑样式并在那里设置Foreground。可能是这样的

<Style.Triggers>
    <Trigger Property="IsChecked" Value="False">
        <Setter Property="Foreground" Value="Blue"/>
    </Trigger>
</Style.Triggers>

或者如果你想在ControlTemplate 中更改它,那么你可以这样做。

<Trigger Property="IsChecked" Value="True">
   <Setter Property="TextBlock.Foreground" TargetName="contentPresenterName" Value="White"/>
</Trigger>

所以在表达式混合中你可以这样做

  1. 资源面板中找到您的样式,然后单击资源旁边的编辑资源按钮。或右键单击并选择编辑
  2. 触发器面板中添加触发器。
  3. 转到属性面板并更改前景属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-19
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    相关资源
    最近更新 更多