WPF中ThemeInfo的困难?

sno*_*hog 2 wpf xaml wpf-controls

我坚持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"中添加合并目录.

小智 5

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

基本上,WPF框架将查找名称与OS主题名称匹配的xaml资源.所以,如果你在XP上运行蓝色主题将是"luna.normal.xaml".如果找不到具有该确切名称的名称,则会查找"generic.xaml".实际上我认为他们首先寻找"classic.xaml",如果他们找不到与特定操作系统匹配的那个,那么他们会寻找generic.xaml.您可以将generic.xaml视为默认资源.

ThemeInfo属性只是告诉WPF 定义了哪些资源.有3种选择:

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

关于控件创作的MSDN上的这篇文章对于提供有关这方面的信息并没有那么糟糕.

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

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

然而,应该注意本地样式分辨率(即,当未设置控件的Style属性时,WPF从元素所在的位置查看并沿着视觉/逻辑树向上查找可能隐含影响该样式的样式element)将始终查找其Key与类的确切类型匹配的Style.因此,如果具有一个Style,其TargetType(以及放置在ResourceDictionary中的默认Key)是在Window的Resources中定义的TextBox,它将影响该Window中的所有TextBox实例(除非它们在视觉中更接近Style)树 - 即在元素之间的资源中定义的一些祖先 - 或其Style属性设置).但是,如果您有一个派生自TextBox的类(例如,类MyTextBox:TextBox),那么它将不会拾取/使用该Style.相反,它将寻找TargetType/Key为typeof(MyTextBox)的Style.解决这个问题的一种方法是将Style属性设置为基本类型的DynamicResource.例如

public MyTextBox()
{
  this.SetResourceReference(StyleProperty, typeof(TextBox));
}
Run Code Online (Sandbox Code Playgroud)

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

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