gpt4 book ai didi

wpf - 自动应用在单独的程序集中定义的默认样式

转载 作者:行者123 更新时间:2023-12-02 05:23:22 24 4
gpt4 key购买 nike

我有以下要求:

  1. 我的 WPF 应用程序包含几个模块(程序集),其中一些与 UI 相关。

  2. 我想为某些控件(例如自定义默认按钮样式)创建一个包含通用样式集的程序集,这些控件应自动应用于所有其他 UI 相关程序集,只需包含那个程序集,而无需我指定显式资源键。

  3. 我不会为每种控件提供样式,因此那些没有自定义样式的控件应该保持默认的 Aero 主题(包括内容模板等)。

    <
  4. 不想编写我自己的扩展 Button 类或类似的东西。

  5. 我希望它在 Visual Studio 设计时也能在最终应用和其他 UI 相关模块中运行。

由于样式是在程序集中定义的,我显然 cannot have an App.xaml there .因此,我假设我必须从 Generic.xaml 中包含它们。由于 Generic.xaml 仅在标准 (Aero) 主题中未定义样式时用作后备,WPF 会忽略我在 Generic.xaml 中的样式。

下一步可能是创建我自己的主题(以某种方式合并默认的 Aero 样式)。但是我如何告诉 VS 在应用程序和模块中使用该主题,而不是例如航空?我想我必须以声明方式执行此操作,因为我需要为我的自定义样式提供设计时支持。

最佳答案

简单地添加对样式程序集的引用是不够的;您必须做些什么才能使 WPF 合并资源。但是我们可以这样做,您只需添加一行 C#(或几行XAML) 到您的应用程序程序集。

最直接的解决方案可能是在您的共享样式程序集中创建一个强类型的 ResourceDictionary,并在启动时将其添加到您的应用级 ResourceDictionary 中。

例如,在您的共享样式程序集中创建一个 CustomStyles.xaml,并将所有样式资源拉入该文件(直接或通过 MergedDictionaries)。确保 Build Action 设置为“Page”,并将 x:Class 指令添加到 ResourceDictionary 元素,如下所示:

<ResourceDictionary x:Class="YourNamespace.CustomStyles"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Your styles declared or imported here -->
</ResourceDictionary>

对于旨在替换内置或第三方控件样式的样式,您可以将样式声明为隐式样式,即完全关闭 x:Key,或使用控件的类型作为键,例如 x:Key="{x:Type ComboBox}"

添加 x:Class 指令可能不足以使 Visual Studio 生成实际加载 XAML 内容的 CustomStyles() 构造函数,因此您将可能需要手动添加 CustomStyles.xaml.cs 文件并为其提供调用 InitializeComponent() 的构造函数(VS 仍应生成此文件):

namespace YourNamespace
{
partial class CustomStyles
{
public CustomStyles()
{
InitializeComponent();
}
}
}

在您的应用程序中,您需要将此字典合并到您的Application.Resources 字典中。如果您愿意,可以从 App.xaml 文件执行此操作:

<Application x:Class="YourNamespace.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cs="clr-namespace:YourNamespace;assembly=YourCustomStylesAssembly">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<cs:CustomStyles />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

...您可以在 C# 端执行此操作:

public partial class App
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
this.Resources.MergedDictionaries.Add(new CustomStyles());
}
}

现在,棘手的部分是让这些样式在 XAML 设计器中发挥作用。我想到的一种解决方案是添加一个自定义附加属性,您可以在所有 View 上设置该属性,并且在设计器中运行时应用:

partial class CustomStyles
{
public static readonly DependencyProperty EnableDesignTimeStylesProperty =
DependencyProperty.RegisterAttached(
"EnableDesignTimeStyles",
typeof(bool),
typeof(CustomStyles),
new PropertyMetadata(
default(bool),
OnEnableDesignTimeStylesChanged));

private static CustomStyles DesignTimeResources;

private static void OnEnableDesignTimeStylesChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
if (!DesignerProperties.GetIsInDesignMode(d))
return;

var element = d as FrameworkElement;
if (element == null)
return;

if (DesignTimeResources == null)
DesignTimeResources = new CustomStyles();

if ((bool)e.NewValue)
element.Resources.MergedDictionaries.Add(DesignTimeResources);
else
element.Resources.MergedDictionaries.Remove(DesignTimeResources);
}

public static void SetEnableDesignTimeStyles(
DependencyObject element,
bool value)
{
element.SetValue(EnableDesignTimeStylesProperty, value);
}

public static bool GetEnableDesignTimeStyles(DependencyObject element)
{
return (bool)element.GetValue(EnableDesignTimeStylesProperty);
}
}

然后,在您的 View 中,只需设置 CustomStyles.EnableDesignTimeStyles="True" 即可强制设计器合并样式资源。在运行时,DesignerProperties.GetIsInDesignMode(d) 的计算结果为 false,您最终不会在每个 View 中加载样式的新副本;您只需从应用级资源继承它们即可。

关于wpf - 自动应用在单独的程序集中定义的默认样式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13499575/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com