【问题标题】:Generic style with specific trigger values具有特定触发值的通用样式
【发布时间】:2017-10-02 12:26:31
【问题描述】:

我的 UserControl 中有几个 TextBlock,我想在触发属性时将其更改为粗体并具有红色字体。问题是它们中的每一个都被不同的属性改变。我看到了一个带有标签的解决方案here,但无法让它为我工作。如果这是重复的,我深表歉意,但我找不到任何解决我的问题的解决方案。

我的风格是这样的:

<Style x:Key="TextBlockTrigger" TargetType="{x:Type TextBlock}">
  <Style.Triggers>
    <Trigger Property="Tag" Value="true">
      <Setter Property="FontWeight" Value="Bold"/>
      <Setter Property="Foreground" Value="Red"/>
    </Trigger>
  </Style.Triggers>
</Style>

这是我尝试使用的 TextBlock:

<TextBlock Name="TextBlock1" x:Uid="TextBlock1" Text="This text should become bold and Red"
Style="{StaticResource TextBlockTrigger}" Tag="{Binding Path=TriggerProperty, UpdateSourceTrigger=PropertyChanged}"/> 

我添加了一个带有读取Tag的codebehind函数的按钮,断点显示Tag设置为true,但文本仍然是常规黑色。

TriggerProperty 由 View Constructor 中的函数调用设置,在 InitializeComponent 之后:

public MyWindow()
{
  InitializeComponent();
  UpdateServerProperties();
}

public void UpdateServerProperties()
{
    //other code
    if(ServerValue == true)
    {
        TriggerProperty = true;
        OnPropertyChanged("TriggerProperty");
    }
}

这有点简化,但实际代码过于复杂,但结果相同。 ServerValue 得到一个值,我已经确认 TriggerProperty 确实更新为 true。

【问题讨论】:

  • 您是否动态设置 TriggerProperty 属性?你实现 INotifyPropertyChanged 了吗?

标签: c# wpf xaml


【解决方案1】:

Tag 属性具有 object 类型。 Xaml 无法知道true 代表bool 值,因此它只是假设您的意思是string。假设您将 Tag 设置为布尔值,则您的 Trigger 正在评估 Equals(true, "true"),因此条件失败。

尝试使用{x:Static} 指向某个常量布尔值。我为这种事情保留了一个KnownBoxes 类:

public static class KnownBoxes
{
    public static readonly object True = true;
    public static readonly object False = false;

    // ... more common values ...
}

这些值很容易从 Xaml 中引用,例如,{x:Static ns:KnownBoxes.True}

或者,您可以使用元素语法:

<Trigger Property="Tag">
  <Trigger.Value>
    <s:Boolean xmlns:s="clr-namespace:System;assembly=mscorlib">True</s:Boolean>
  </Trigger.Value>
  <Setter Property="FontWeight" Value="Bold"/>
  <Setter Property="Foreground" Value="Red"/>
</Trigger>

或者您可以将Tag 设置为字符串"true",尽管这可能会在其他人处理您的代码时引起一些混乱:)。

【讨论】:

  • 使用s:Boolean 成功了!将Tag 设置为"true" 是第二个选项,但我需要为此创建一个 BooleanToStringConverter。这要简单得多,谢谢!
【解决方案2】:

如果您在运行时将TriggerProperty 动态设置为true,则定义此属性的类应实现INotifyPropertyChanged 接口并引发PropertyChanged 事件以供触发器触发。

如果您将Tag 属性设置为硬编码值true,您的示例标记应该可以正常工作:

<TextBlock Name="TextBlock1" x:Uid="TextBlock1" Text="This text should become bold and Red"
           Style="{StaticResource TextBlockTrigger}" Tag="true"/>

您还应该在Style 中将Value 属性设置为键入的bool 值:

<Style x:Key="TextBlockTrigger" TargetType="{x:Type TextBlock}"
       xmlns:s="clr-namespace:System;assembly=mscorlib">
    <Style.Triggers>
        <Trigger Property="Tag">
            <Trigger.Value>
                <s:Boolean>True</s:Boolean>
            </Trigger.Value>
            <Setter Property="FontWeight" Value="Bold"/>
            <Setter Property="Foreground" Value="Red"/>
        </Trigger>
    </Style.Triggers>
</Style>

【讨论】:

  • 我已经实现了 INotifyPropertyChanged 并使用该属性来触发其他 xaml 块的可见性,例如:&lt;ContentControl x:Uid="WarnIcon" Template="{StaticResource WarningIcon}" Visibility="{Binding Path=TriggerProperty, Converter={StaticResource BooleanToVisibilityConverter}}"/&gt;
  • 使用Tag="true" 将文本更改为红色。但就像我说的,我添加了一个触发 Codebehind 函数的 Button,在该函数中我在断点中读取了 Tag,它从绑定中获得了 true 值,所以我不明白这一点。
  • 您如何以及在何处设置 TriggerProperty?请包含一些演示这一点的代码。
  • 我在帖子中添加了简化。实际代码对于 SO 帖子来说太长了,几乎所有这些都无关紧要
  • Mike Strobel 也提出了同样的建议,效果很好,谢谢!
猜你喜欢
  • 2014-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-20
相关资源
最近更新 更多