2

我被文件中的ThemeInfo属性困住了AssemblyInfo.cs。我正在尝试编写自定义控件。自定义控件位于名为“MyCustomControls.dll”的 dll 中。此外,控件本身源自另一个自定义控件,该控件位于另一个名为“MyAnotherCustomControls.dll”的 dll 中。

我在 MSDN 上读到必须使用 2 个参数声明 ThemeInfo,这些参数负责控制主题特定位置和通用特定位置,尽管我不知道什么是“主题”和什么是“通用”。我怎样才能更好地理解这两个?

如果有人可以从头开始向我解释一个例子,什么是“通用”,什么是“主题”。此外,何时使用“通用”或“主题”。WPF系统如何使用这两个?我真的需要用简单的英语进行解释,所以如果您要向我发布 MSDN 链接,请节省您的时间。我阅读了有关 ThemeInfo 的 msdn 文档,但我不明白。

也有人可以告诉我如何通过ThemeInfo告诉我的“MyCustomControls.dll”来使用“MyAnotherCustomControls.dll”中定义的字典资源吗?这是否可以仅通过 ThemeInfo 完成,还是我必须处理“MyCustomControls.dll”中的 MergedDirectories?我希望 WPF 系统负责定位资源,以便我可以使用“MyAnotherCustomControls.dll”中的样式键,而无需在“MyCustomControls.dll”中添加合并目录。

4

1 回答 1

5

我在 MSDN 上读到必须使用 2 个参数声明 ThemeInfo,这些参数负责控制主题特定位置和通用特定位置,尽管我不知道什么是“主题”和什么是“通用”。我怎样才能更好地理解这两个?

基本上,WPF 框架将查找名称与 OS 主题名称匹配的 xaml 资源。因此,如果您在 XP 上运行蓝色主题为“luna.normal.xaml”。如果找不到具有该确切名称的名称,它将查找“generic.xaml”。实际上,我认为如果他们找不到与特定于操作系统的匹配项,他们首先会查找“classic.xaml”,然后他们会查找generic.xaml。您可以将 generic.xaml 视为默认资源。

ThemeInfo 属性只是告诉 WPF这些资源是在哪里定义的。有 3 个选项:

  • - 您没有提供“主题”或“通用”资源。这确实是一种优化,因此 WPF 框架不会费心寻找它们。您通常不会将其用于GenericDictionaryLocation,但您可以将其用于ThemeDictionaryLocation,以防您不打算定义操作系统主题特定的资源(即您不希望您的控件在不同的操作系统主题下看起来不同)。通常,控件供应商将为每个可能的操作系统主题定义一个资源字典,以便控件看起来与该操作系统中运行的其他控件和窗口一致。
  • ExternalAssembly - 这意味着您正在为资源定义一个单独的程序集。因此,如果您查看 WPF 框架,您会发现他们将其用于ThemeDictionaryLocation的PresentationFramework程序集。然后他们为他们想要支持的每个操作系统主题定义了一个单独的程序集(例如 PresentationFramework.Aero.dll、PresentationFramework.Luna.dll 等)。它将搜索的程序集的名称是定义程序集的名称加上主题的名称。
  • SourceAssembly - 这意味着资源是在程序集本身内定义的。因此,在该程序集中,您将拥有一个包含资源字典的“主题”文件夹。

MSDN 上关于控件创作的这篇文章对于提供有关此信息的信息确实还不错。

也有人可以告诉我如何通过使用 ThemeInfo 告诉我的“MyCustomControls.dll”使用“MyAnotherCustomControls.dll”中定义的字典资源吗?这是否可以仅通过 ThemeInfo 完成,还是我必须处理“MyCustomControls.dll”中的 MergedDirectories?我希望 WPF 系统负责定位资源,以便我可以使用“MyAnotherCustomControls.dll”中的样式键,而无需在“MyCustomControls.dll”中添加合并目录。

您不能使用 ThemeInfo 告诉 WPF 它应该在某个任意程序集中查找您的资源。话虽如此,如果您不设置或覆盖DefaultStyleKey,就像在定义自定义控件时通常所做的那样,那么它应该继续使用为默认资源设置/覆盖了 DefaultStyleKey 的基类的资源。

然而,应该注意的是本地样式解析(即,当您的控件的样式属性未设置并且 WPF 从元素所在的位置查找并沿着视觉/逻辑树查找可能隐式影响的样式时元素)将永远查找 Key 与类的确切类型匹配的 Style。因此,如果有一个 Style,其 TargetType(因此放置在 ResourceDictionary 中时的默认键)是在窗口的资源中定义的 TextBox,它将影响该窗口中的所有 TextBox 实例(除非它们在视觉中具有更接近的样式树 - 即在其自身之间的某个元素的资源中定义了某个祖先 - 或者它的 Style 属性已设置)。但是,如果您有一个派生自 TextBox 的类(例如 MyTextBox 类:TextBox),那么它将不会选择/使用该样式。相反,它将寻找 TargetType/Key 为 typeof(MyTextBox) 的 Style。解决这个问题的一种方法是将 Style 属性设置为 DynamicResource 为基本类型。例如

public MyTextBox()
{
  this.SetResourceReference(StyleProperty, typeof(TextBox));
}

基本上,这会在控件的 Style 属性上设置一个本地值,该属性正在为一个 Style 进行动态资源查找,该 Style 的 Key(以及未设置 x:Key 的 Styles 的 TargetType)是指定的类型(在本例中为 TextBox)。

正如您所指出的,替代方法是在您的程序集中本地为基类程序集定义的每个主题定义 xaml 文件,然后将 ResourceDictionary 添加到其 MergedDictionaries 中,使用pack uri 表示法来引用基类程序集中的资源。如果您要设置 DefaultStyleKey,那么您可能需要在每个 ResourceDictionaries 中定义 TargetType 是您的类类型的 Style,然后将 BasedOn 设置为 StaticResource,其中资源键是基类的类型。听起来您不需要这样做。

于 2013-04-19T14:25:31.100 回答