8

我有一些 XAML 直接设置前景色:

<Style x:Key="HomeHeaderText" TargetType="TextBlock">
    <Setter Property="FontSize" Value="24" />
    <Setter Property="FontFamily" Value="Segoe Light UI" />
    <Setter Property="Foreground" Value="#FF606060" />
    <Setter Property="Margin" Value="0,50,0,30" />
</Style>

我想在样式中检测系统是否处于高对比度模式,如果是,则回退到系统颜色之一。

如何使用样式来做到这一点?


我尝试使用触发器设置它,但这会XamlParseException在运行时导致:

<Style x:Key="HomeHeaderText" TargetType="TextBlock">
    <Setter Property="FontSize" Value="24" />
    <Setter Property="FontFamily" Value="Segoe Light UI" />
    <Setter Property="Foreground" Value="#FF606060" />
    <Setter Property="Margin" Value="0,50,0,30" />
    <Style.Triggers>
        <DataTrigger Binding="{x:Static SystemParameters.HighContrast}" Value="True">
           <Setter Property="Foreground"
               Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
        </DataTrigger>
    </Style.Triggers>
</Style>
4

3 回答 3

12

您尝试的问题是DataTrigger.Binding需要绑定,但您给了它一个直接值。您可以通过设置绑定源来解决此问题:

{Binding Source={x:Static SystemParameters.HighContrast}}

但是,这不会是动态的——如果有人在应用程序运行时切换高对比度,则样式不会更新。理想情况下,有这样的东西会很好:

{Binding Source={x:Static SystemParameters}, Path=HighContrast}

但不幸的是,这是不可能的,因为它是一个静态属性。因此,绑定到HighContrastKey资源是更好的选择。Tag您可以将其绑定到附加属性,而不是使用。想一想,微软可能应该SystemParameters首先将其实现为附加属性。尝试这样的事情:

public static class SystemParameterProperties {
    public static readonly DependencyProperty HighContrastProperty =
        DependencyProperty.RegisterAttached("HighContrast", typeof(bool), typeof(SystemParameterProperties),
            new FrameworkPropertyMetadata() {Inherits = true});

    public static bool GetHighContrast(DependencyObject obj) {
        return (bool)obj.GetValue(HighContrastProperty);
    }

    public static void SetHighContrast(DependencyObject obj, bool value) {
        obj.SetValue(HighContrastProperty, value);
    }
}

Inherits = true在属性上使用了,这样我们就可以将它设置在最外面的容器上,让它在任何地方都可以访问,即:

<Window ...
        xmlns:attachedProperties="..."
        attachedProperties:SystemParameterProperties.HighContrast="{DynamicResource ResourceKey={x:Static Member=SystemParameters.HighContrastKey}}">
    ...
</Window>

最后,您的触发器将是:

<Trigger Property="attachedProperties:SystemParameterProperties.HighContrast" Value="True">
     <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
</Trigger>
于 2013-09-20T04:59:57.047 回答
3

我已经解决了利用助手的问题:

public class HighContrastHelper
    : DependencyObject
{
    #region Singleton pattern

    private HighContrastHelper()
    {
        SystemParameters.StaticPropertyChanged += SystemParameters_StaticPropertyChanged;
    }

    private static HighContrastHelper _instance;

    public static HighContrastHelper Instance
    {
        get
        {
            if (_instance == null)
                _instance = new HighContrastHelper();

            return _instance;
        }
    }

    #endregion

    void SystemParameters_StaticPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        Console.WriteLine(e.PropertyName);
        if (e.PropertyName == "HighContrast")
        {
            HighContrastHelper.Instance.IsHighContrast = SystemParameters.HighContrast;
        }
    }

    #region DP IsHighContrast

    public static readonly DependencyProperty IsHighContrastProperty = DependencyProperty.Register(
        "IsHighContrast",
        typeof(bool),
        typeof(HighContrastHelper),
        new PropertyMetadata(
            false
            ));

    public bool IsHighContrast
    {
        get { return (bool)GetValue(IsHighContrastProperty); }
        private set { SetValue(IsHighContrastProperty, value); }
    }

    #endregion  
 }

之后,代码中的用法很简单:

<Style x:Key="HomeHeaderText" TargetType="TextBlock">
    <Setter Property="FontSize" Value="24" />
    <Setter Property="FontFamily" Value="Segoe Light UI" />
    <Setter Property="Foreground" Value="#FF606060" />
    <Setter Property="Margin" Value="0,50,0,30" />
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=IsHighContrast, Source={x:Static local:HighContrastHelper.Instance}}" Value="True">
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
        </DataTrigger>
    </Style.Triggers>
</Style>

希望能帮助到你。

于 2013-09-20T04:53:39.477 回答
1

您可以将其绑定到 textblock 的 Tag 属性并在 DataTrigger 中使用它,如下所示:

  <Style x:Key="MyTextBoxStyle" TargetType="{x:Type TextBlock}">
     <Setter Property="Tag" Value="{DynamicResource {x:Static SystemParameters.HighContrastKey}}"/>
     <Style.Triggers>
         <DataTrigger Binding="{Binding Path=Tag , RelativeSource= {x:Static RelativeSource.Self}}" Value="True">
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
         </DataTrigger>
     </Style.Triggers>
  </Style>
于 2013-09-10T02:38:43.790 回答