WPF:ContentPresenter 根据样式的位置意外更改前景

Posted

技术标签:

【中文标题】WPF:ContentPresenter 根据样式的位置意外更改前景【英文标题】:WPF: ContentPresenter changing Foreground unexpectedly depending on where styles are located 【发布时间】:2011-02-27 07:40:31 【问题描述】:

我遇到了 ContentPresenter 基于样式是否位于窗口中的异常行为的问题。资源或在 ResourceDictionary 中。具体来说,我将默认 TextBlock 的 Foreground 设置为 Black,然后将我的默认按钮样式中的 Foreground 值设置为 White。

如果页面上存在这样的样式,它们可以正常工作:

<Window
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
 x:Class="TestBed.MainWindow"
 x:Name="Window"
 Title="MainWindow"
 Width="640" Height="480">
 <Window.Resources>
  <Style TargetType="x:Type TextBlock">
     <Setter Property="Foreground" Value="Black" />
   </Style>
  <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 TargetType="x:Type Button">
   <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="White"/>
   <Setter Property="HorizontalContentAlignment" Value="Center"/>
   <Setter Property="VerticalContentAlignment" Value="Center"/>
   <Setter Property="Padding" Value="1"/>
   <Setter Property="Template">
    <Setter.Value>
     <ControlTemplate TargetType="x:Type Button">
      <Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" SnapsToDevicePixels="true" Background="TemplateBinding Background" BorderBrush="TemplateBinding BorderBrush" RenderDefaulted="TemplateBinding IsDefaulted" RenderMouseOver="TemplateBinding IsMouseOver" RenderPressed="TemplateBinding IsPressed">
       <ContentPresenter HorizontalAlignment="TemplateBinding HorizontalContentAlignment" Margin="TemplateBinding Padding" VerticalAlignment="TemplateBinding VerticalContentAlignment" SnapsToDevicePixels="TemplateBinding SnapsToDevicePixels" RecognizesAccessKey="True"/>
      </Microsoft_Windows_Themes:ButtonChrome>
      <ControlTemplate.Triggers>
       <Trigger Property="IsKeyboardFocused" Value="true">
        <Setter Property="RenderDefaulted" TargetName="Chrome" Value="true"/>
       </Trigger>
       <Trigger Property="ToggleButton.IsChecked" Value="true">
        <Setter Property="RenderPressed" TargetName="Chrome" Value="true"/>
       </Trigger>
       <Trigger Property="IsEnabled" Value="false">
        <Setter Property="Foreground" Value="#ADADAD"/>
       </Trigger>
      </ControlTemplate.Triggers>
     </ControlTemplate>
    </Setter.Value>
   </Setter>
  </Style>
 </Window.Resources>
 <StackPanel x:Name="LayoutRoot">
  <Button Content="Button"  />  
 </StackPanel>
</Window>

但是,如果我将这些相同的样式移至 ResourceDictionary,按钮的前景将变为黑色。

更新主窗口:

<Window
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
 x:Class="TestBed.MainWindow"
 x:Name="Window"
 Title="MainWindow"
 Width="640" Height="480">

 <StackPanel x:Name="LayoutRoot">
  <Button Content="Button" />  
 </StackPanel>
</Window>

资源字典:

<ResourceDictionary
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
 xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" 
 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
 mc:Ignorable="d">

  <Style TargetType="x:Type TextBlock">
  <Setter Property="Foreground" Value="Black" />
  </Style>
  <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 TargetType="x:Type Button">
   <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="White"/>
   <Setter Property="HorizontalContentAlignment" Value="Center"/>
   <Setter Property="VerticalContentAlignment" Value="Center"/>
   <Setter Property="Padding" Value="1"/>
   <Setter Property="Template">
    <Setter.Value>
     <ControlTemplate TargetType="x:Type Button">
      <Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" SnapsToDevicePixels="true" Background="TemplateBinding Background" BorderBrush="TemplateBinding BorderBrush" RenderDefaulted="TemplateBinding IsDefaulted" RenderMouseOver="TemplateBinding IsMouseOver" RenderPressed="TemplateBinding IsPressed">
       <ContentPresenter HorizontalAlignment="TemplateBinding HorizontalContentAlignment" Margin="TemplateBinding Padding" VerticalAlignment="TemplateBinding VerticalContentAlignment" SnapsToDevicePixels="TemplateBinding SnapsToDevicePixels" RecognizesAccessKey="True"/>
      </Microsoft_Windows_Themes:ButtonChrome>
      <ControlTemplate.Triggers>
       <Trigger Property="IsKeyboardFocused" Value="true">
        <Setter Property="RenderDefaulted" TargetName="Chrome" Value="true"/>
       </Trigger>
       <Trigger Property="ToggleButton.IsChecked" Value="true">
        <Setter Property="RenderPressed" TargetName="Chrome" Value="true"/>
       </Trigger>
       <Trigger Property="IsEnabled" Value="false">
        <Setter Property="Foreground" Value="#ADADAD"/>
       </Trigger>
      </ControlTemplate.Triggers>
     </ControlTemplate>
    </Setter.Value>
   </Setter>
  </Style>
</ResourceDictionary>

还有我的 App.xaml,因为有人会要求它:

<Application
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 x:Class="TestBed.App"
 StartupUri="MainWindow.xaml">
 <Application.Resources>
  <!-- Resources scoped at the Application level should be defined here. -->
  <ResourceDictionary>
   <ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="ResourceDictionary.xaml"/>
   </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>
 </Application.Resources>
</Application>

任何帮助将不胜感激:)

【问题讨论】:

【参考方案1】:

刚刚意识到我从来没有回答过这个问题。简短的版本是您应该始终使用标签而不是文本块,因为文本块实际上并不是控件。

【讨论】:

感谢您的信息,我一直在努力更改自定义 dataGrid 的前景色【参考方案2】:

我们是在说它在设计时或运行时表现得奇怪吗?我之前在使用 Visual Studio 设计器时遇到过问题……尤其是 App.Xaml 在我运行之前无法正常工作。

【讨论】:

对不起,我可能对这个问题不够清楚 - 这是在运行时。如果样式在 Window 上,则按钮的文本颜色按预期工作并且为白色。一旦我将它移出窗口并进入 ResourceDictionary,文本就会变成黑色。

以上是关于WPF:ContentPresenter 根据样式的位置意外更改前景的主要内容,如果未能解决你的问题,请参考以下文章

WPF TabItem 标题样式

WPF WindowChrome ContentPresenter 不显示内容

WPF -- DataTemplate与ControlTemplate结合使用

ContentPresenter理解

wpfcombobox数据展示丢失下划线

WPF TreeViewItem 水平对齐