2

我有一个 WPF 应用程序,它附带一组由项目类型定义的标签、文本框等默认样式(未定义显式键)。

在应用程序中,使用了两个主要容器,一个具有深色背景,一个具有浅色背景,因此有时使用黑色作为标签的前景色是正确的,有时则大错特错。另一方面,编辑器的样式总是比较传统的浅色背景和深色前景,所以我不能只将所有子元素的前景设置为相反。

有没有一种优雅的方法可以让我的标签(也许还有 TextBlocks)根据“他们的”背景来决定他们的前景色?我只想在两种颜色之间切换,因此不需要自动对比度最大化,只需要一些阈值来避免白色背景上的白色字体。

我也不想定义两组默认​​样式,我强烈寻找某种方法来使我的单个 Label-Default-Style 适合两种背景变体。

是否有可能(并且在没有太多性能影响的情况下可行)将触发器/绑定添加到评估当前背景颜色的样式?

或者,我会对如何为某些 FrameworkElements(尤其是容器/面板)干净地设置背景颜色而不遇到上述问题的最佳实践感兴趣。

这是我尝试过的(当然是简化的):

  <UniformGrid>
  <UniformGrid.Resources>
  <!-- SimpleStyles: Label -->
     <Style x:Key="{x:Type Label}" TargetType="{x:Type Label}">
        <Setter Property="HorizontalContentAlignment" Value="Left"/>
        <Setter Property="VerticalContentAlignment" Value="Top"/>
        <Setter Property="Template">
           <Setter.Value>
              <ControlTemplate TargetType="{x:Type Label}">
                 <Border>
                    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/>
                 </Border>
                 <ControlTemplate.Triggers>
                    <Trigger Property="Background" Value="Black">
                       <Setter Property="Foreground" Value="Red"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                       <Setter Property="Foreground" Value="#888888"/>
                    </Trigger>
                 </ControlTemplate.Triggers>
              </ControlTemplate>
           </Setter.Value>
        </Setter>
     </Style>
  </UniformGrid.Resources>
  <Label x:Name="bgSetExplicitly" Background="Black">abc
  </Label>
  <Border Background="Black">
     <Label x:Name="bgInheritedFromParent" >abc
     </Label>
  </Border>
  <Label>abc
  </Label>
  <Label>abc
  </Label>

您可以看到标签的背景选择得很好,如果标签具有明确的背景集 (x:Name=bgSetExplicitly),但如果背景是从 VisualTree 中的父级“继承”的 (x:Name="bgInheritedFromParent") , 它不是。我希望这种风格可以评估“有效背景”(无论它来自哪里)并为此背景选择合适的前景画笔。

4

3 回答 3

4

这个问题似乎暗示了一个更深层次的问题。我猜你还没有整合前景色的管理,所以你有一个应用程序,它的代码或样式可以在所有地方设置前景色。现在你正在处理其中的一个影响。

我会面对更深层次的问题并解决它。我真的不明白你为什么反对创建默认样式的想法,但假设你有充分的理由不这样做(除了“我应该在某个时候创建​​默认样式,但现在我没有,而且我的应用程序变得很大,这太难了,”在这种情况下,我有一个不同的建议),创建全球资源怎么样?

在应用程序的资源字典中为控件的前景色和背景色创建对象,并修复 XAML,以便它不直接引用画笔,而是使用DynamicResource标记扩展从资源字典中获取它们。在代码中,不是Foreground直接将控件上的属性设置为画笔,而是使用GetResource获取画笔。并以同样的方式设置背景。

完成此操作后,如果要在应用程序中全局更改前景色/背景色,只需更改资源即可。

这基本上是您开始使 WPF 应用程序可换肤的方式,这似乎是您要走的路。

于 2011-05-31T16:15:39.850 回答
3

最简单的方法是将 TextBox 等的前景色绑定到其包含元素的背景,并使用值转换器进行更改。如果您只使用两种颜色,这尤其容易。

举个例子....

  public class ColorSwapper : IValueConverter
  {
    public object Convert(object value, Type targetType, object parameter, 
System.Globalization.CultureInfo culture)
    {
      if (value == null) { return DependencyProperty.UnsetValue; }

      Color srcColor = (value as SolidColorBrush).Color;
      if (srcColor == Colors.Black)
      {
        return new SolidColorBrush(Colors.White);
      }
      else
      {
        return new SolidColorBrush(Colors.Black);
      }
    }
...

还有一些示例 XAML....

<Grid Grid.Column="1" Name="RightGrid" Background="White">
  <TextBlock Text="Hello Nurse!" Foreground="{Binding ElementName=RightGrid, Path=Background, Converter={StaticResource ColorSwapper}}"/>
</Grid>

当然,您可能希望根据您的特定需求进行一些调整和清理,但这会做到。

于 2011-05-31T11:59:17.243 回答
0

这是另一种可能的方法。如果您的应用程序只有所有深色/浅色背景及其赞美,您可以尝试这样的方法,使用我在其他答案中提到的“ColorSwapper”。

<Window>
  <Window.Resources>
    <local:ColorSwapper x:Key="swapper"/>

    <SolidColorBrush x:Key="BackBrush" Color="Black"/>
    <!--<SolidColorBrush x:Key="BackBrush" Color="White"/>-->

    <Style TargetType="{x:Type TextBlock}">
      <Setter Property="Foreground" Value="{Binding Source={StaticResource BackBrush}, Converter={StaticResource swapper}}"/>
    </Style>

  </Window.Resources>

  <Grid Background="{StaticResource BackBrush}">
    <TextBlock FontSize="24" FontWeight="Bold">ABC</TextBlock>
  </Grid>
</Window>

现在,每当您更改“BackBrush”的颜色值时,所有相关的前景色都会自动更新。根据您的讨论,我认为这也将满足您的风格要求。无论如何,您可能必须制作小型模组以确保这种方法适合您的确切场景。

于 2011-06-01T12:32:54.403 回答