默认TextBlock样式覆盖按钮文本颜色

Hol*_*dam 4 c# wpf xaml styles textblock

我的问题出现在.NET 3.5 SP1中的WPF,可以描述如下:

我有一个默认Style命中TextBlock我的UI中的所有元素.这就是它的样子:

<Style TargetType="{x:Type TextBlock}">
   <Setter Property="TextTrimming" Value="CharacterEllipsis"/>
   <Setter Property="Foreground" Value="Red"/>
</Style>
Run Code Online (Sandbox Code Playgroud)

这适用于所有人TextBlock.除此之外,我有一个Button样式,包括ControlTemplate看起来像这样(缩短):

<Style x:Key="MyButtonStyle" TargetType="{x:Type Button}" BasedOn="{x:Null}">
   <Setter Property="Foreground" Value="Green"/>
   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="{x:Type Button}">
            <Border x:Name="Border" 
                    Background="{TemplateBinding Background}" 
                    BorderThickness="{TemplateBinding BorderThickness}" 
                    Padding="{TemplateBinding Padding}" 
                    Height="24" 
                    BorderBrush="{TemplateBinding BorderBrush}">
               <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                 VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                 TextBlock.Foreground="{TemplateBinding Foreground}"/>
            </Border>
            <ControlTemplate.Triggers>...</ControlTemplate.Triggers>
         </ControlTemplate>
      </Setter.Value>
   </Setter>
</Style>
Run Code Online (Sandbox Code Playgroud)

请注意行TextBlock.Foreground="{TemplateBinding Foreground}"ContentPresenter.这应该将按钮文本设置为绿色,实际上它在Visual Studio的设计器视图中.但是当我编译并运行程序时,按钮文本为红色,文本颜色由默认TextBlock样式设置.我用Snoop验证了这一点.

如何防止默认TextBlock样式覆盖该TextBlock.Foreground值?在这种情况下,OverridesDefaultStyle财产ContentPresenter没有帮助.

任何的想法?

Fre*_*lad 11

请参阅此链接的答案5

发生这种情况是因为ContentPresenter为字符串内容创建了一个TextBlock,并且由于该TextBlock不在可视树中,因此它将查找到应用程序级资源.如果在应用程序级别为TextBlock定义样式,则它将应用于ContentControl中的这些TextBlock

解决方法是为System.String定义DataTemplate,我们可以在其中显式使用默认TextBlock来显示内容.您可以将DataTemplate放在定义TextBlock样式的同一个字典中,以便将此DataTemplate应用于受样式影响的任何ContentPresenter.

尝试将其添加到ResourceDictionary

<DataTemplate DataType="{x:Type sys:String}">
    <TextBlock Text="{Binding}">
        <TextBlock.Resources> 
            <Style TargetType="{x:Type TextBlock}"/>
        </TextBlock.Resources>
    </TextBlock>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)

  • 覆盖System.String的数据模板是一个糟糕的想法,因为它失去了下划线到键盘的快捷方式和ContentStringFormat功能.这让我陷入了热水.在此处查看更多详细信息:http://www.ikriv.com/dev/dotnet/wpftextstyle/StringTemplate.shtml (3认同)
  • 谢谢您的回答.有两点我不明白:1.即使ContentPresenter创建的TextBlock不在VisualTree中,它仍然应该接受我放在TextBlock.Foreground中的值,对吧?2.通过使用您描述的DataTemplate,我仅限于ContentPresenter元素中所有文本的一种样式,对吗? (2认同)

Iva*_*kov 5

最好不要覆盖 TextBlock 的默认样式。到目前为止,我能想到的最好的想法是为 Control 创建一个样式并将其应用到所有顶级窗口。

<!-- App.xaml -->
<Application.Resources>
    <Style x:Key="RedStyle" TargetType="{x:Type Control}">
        <Setter Property="TextTrimming" Value="CharacterEllipsis"/>
        <Setter Property="Foreground" Value="Red"/>
    </Style>
</Application.Resources>

<!-- MainWindow.xaml -->
<Window Style="{StaticResource RedStyle}" ...>
    ...
</Window>
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请参见此处:http : //www.ikriv.com/dev/dotnet/wpftextstyle/