.NET4 WPF - Foreground的样式设置器仅在控制隐藏/显示后工作

Bor*_* B. 0 wpf styles .net-4.0 foreground

我有一个叫WPF某一个风格问题HeadTextTargetType = "TextBlock".样式定义Foreground,FontSizeEffect.第一次显示TextBlock时,不会触发前景设置器(文本颜色保持黑色),正常应用FontSize和Effect.当我从父项中删除TextBlock并将其返回时,前景也会按原样更改.

情况:

Presenter.dll程序集

  • class Presenter: Window,加载并显示我的usercontrols.
  • Generic.xaml - 包含样式的资源字典.
  • Presenter.dll不直接参考TestPresentable.dll.

TestPresentable.dll程序集

  • TestPresentable: UserControl,有一个风格TextBlock.
  • TestPresentable.dll不直接参考Presenter.dll.

MainApp.exe

  • 引用前两个程序集,
  • MainWindowPresenter.dll汇编中实例化,
  • TestPresentableTestPresentable汇编中实例化,
  • MainWindow.ContentHost.Content = testPresentable

相关代码:

Presenter.dll

// Themes/Generic.xaml
...
<Style TargetType="{x:Type TextBlock}" x:Key="HeadText">
    <Setter Property="Foreground" Value="#FFFFFFFF" />
    <Setter Property="Effect">
        <Setter.Value>
            <DropShadowEffect ShadowDepth="0" Color="#79000000" BlurRadius="3" Opacity="1" />
        </Setter.Value>
    </Setter>
    <Setter Property="FontSize" Value="24"/>
</Style>
...


// MainWindow.xaml
...
<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Presenter.dll;component/Themes/Generic.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>
<Grid>
    <ContentPresenter Name="ContentHost"/>
</Grid>
...
Run Code Online (Sandbox Code Playgroud)

TestPresentable.dll

// TestPresentable.xaml
...
<TextBlock Text="{Binding SomeData}" Style="{DynamicResource HeadText}"/>
...
Run Code Online (Sandbox Code Playgroud)

Bor*_* B. 7

从3.5开始,WPF中的TextBlock.Foreground似乎有些奇怪,请参阅:

我想出了一个使用EventSetters的解决方法和一些ResourceDictionary的代码隐藏.它不漂亮,但如果我希望我的风格独立于主应用程序,则必须这样做.我会在这里发布,因为它可能对某人有用,如果有人发布正确(或更好)的答案,我会保持问题开放.

解决方法

在ResorceDictionary XAML(例如Generic.xaml)中添加一个Class属性,如下所示:

<!-- Generic.xaml -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Presenter.Themes.Generic">
Run Code Online (Sandbox Code Playgroud)

然后添加一个codebehind cs文件(例如Generic.xaml.cs),其中包含您在ResourceDictionary的Class属性中指定的分部类:

// Generic.xaml.cs
partial class Generic { }
Run Code Online (Sandbox Code Playgroud)

在ResourceDictionary的相关样式中,为Loaded事件添加一个EventSetter:

<!-- Generic.xaml -->
<Style TargetType="{x:Type TextBlock}" x:Key="HeadText">
    <EventSetter Event="Loaded" Handler="OnHeadTextLoaded"/>
    <Setter .../>
    <Setter .../>
    <Setter .../>
</Style>
Run Code Online (Sandbox Code Playgroud)

在Generic.xaml.cs中为Loaded事件添加一个处理程序并设置所需的Foreground

//Generic.xaml.cs
public void OnHeadTextLoaded(object sender, EventArgs args)
{
    var textBlock = sender as TextBlock;
    if (textBlock == null) return;
    textBlock.Foreground = new SolidColorBrush(Colors.White);
}
Run Code Online (Sandbox Code Playgroud)