.NET4 WPF - 前台样式设置器仅在控件隐藏/显示后工作

发布于 2024-11-18 03:00:40 字数 2126 浏览 2 评论 0原文

我对名为 HeadTextTargetType = "TextBlock" 的某种 WPF 样式有问题。该样式定义了ForegroundFontSizeEffect。第一次显示 TextBlock 时,仅不会触发 Foreground setter(文本颜色保持黑色),正常应用 FontSize 和 Effect。当我从父级中删除 TextBlock 并将其返回时,前景也会按应有的方式更改。

情况:

Presenter.dll 程序集

  • Presenter:Window 加载并显示我的用户控件。
  • Generic.xaml - 包含样式的资源字典。
  • Presenter.dll 不直接引用TestPresentable.dll

TestPresentable.dll 程序集

  • TestPresentable: UserControl 具有样式化的 TextBlock
  • TestPresentable.dll 不直接引用 Presenter.dll

MainApp.exe

  • 引用之前的两个程序集,
  • Presenter.dll 程序集实例化 MainWindow
  • TestPresentable 程序集实例化 TestPresentable
  • 设置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>
...

TestPresentable.dll

// TestPresentable.xaml
...
<TextBlock Text="{Binding SomeData}" Style="{DynamicResource HeadText}"/>
...

I have a problem with a certain WPF style called HeadText with TargetType = "TextBlock". The style defines Foreground, FontSize and Effect. The first time a TextBlock is shown only the Foreground setter is not fired (text color stays black), FontSize and Effect are applied normally. When I remove the TextBlock from parent and return it back, then the foreground is also changed as it should.

Situation:

Presenter.dll assembly

  • class Presenter: Window, loads and displays my usercontrols.
  • Generic.xaml - Resource dictionary that contains styles.
  • Presenter.dll does not directly reference TestPresentable.dll.

TestPresentable.dll assembly

  • TestPresentable: UserControl, has a styled TextBlock.
  • TestPresentable.dll does not directly reference Presenter.dll.

MainApp.exe

  • references both previous assemblies,
  • instantiates MainWindow from Presenter.dll assembly,
  • instantiates TestPresentable from TestPresentable assembly,
  • sets MainWindow.ContentHost.Content = testPresentable

Relevant code:

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>
...

TestPresentable.dll

// TestPresentable.xaml
...
<TextBlock Text="{Binding SomeData}" Style="{DynamicResource HeadText}"/>
...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

赠我空喜 2024-11-25 03:00:40

从 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">

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

// Generic.xaml.cs
partial class Generic { }

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

<!-- Generic.xaml -->
<Style TargetType="{x:Type TextBlock}" x:Key="HeadText">
    <EventSetter Event="Loaded" Handler="OnHeadTextLoaded"/>
    <Setter .../>
    <Setter .../>
    <Setter .../>
</Style>

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

//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);
}

It seems that there is something strange with TextBlock.Foreground in WPF since 3.5, see:

I've came up with a workaround using EventSetters and some codebehind for a ResourceDictionary. It's not pretty but will have to do if I want to have my styles independant of the main app. I'll post it here since it might be useful to someone and I'll keep the question open if someone post the right (or better) answer.

Workaround

In the ResorceDictionary XAML (e.g. Generic.xaml) add a Class property like so:

<!-- 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">

Then add a codebehind cs file (e.g. Generic.xaml.cs) with the partial class you specified in the Class property of the ResourceDictionary:

// Generic.xaml.cs
partial class Generic { }

In the relevant style of the ResourceDictionary add an EventSetter for the Loaded event:

<!-- Generic.xaml -->
<Style TargetType="{x:Type TextBlock}" x:Key="HeadText">
    <EventSetter Event="Loaded" Handler="OnHeadTextLoaded"/>
    <Setter .../>
    <Setter .../>
    <Setter .../>
</Style>

In the Generic.xaml.cs add a handler for the Loaded event and set the desired 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);
}
我不在是我 2024-11-25 03:00:40

我有一个类似的问题,第一次加载页面时前景色没有拉出来。我发现,在我的例子中,如果您在 TextBlock 所在的 xaml 文件中硬编码 FontFamily 属性,那么前景色第一次就会正确地显示出来。

但是,如果您只是将 FontFamily 属性放置在样式表中,那么 TextBlock 第一次将再次显示为黑色。

例如

// TestPresentable.xaml

...
Style="{DynamicResource HeadText}" **FontFamily="Arial"**... 

I have a similar problem with the foreground colour not pulling through the first time the page loads. I've found that in my case if you hard code the FontFamily property in the xaml file where the TextBlock is located, then the foreground colour pulls through correctly the first time.

If you however just place the FontFamily property in the stylesheet, then the TextBlock will again just be black first time.

e.g.

// TestPresentable.xaml

...
Style="{DynamicResource HeadText}" **FontFamily="Arial"**... 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文