最近作的项目用了个漂亮的开源UI库,结果项目临近结尾发现要支持.Net 3.5, 然而那个UI库却最低支持4.0。欲哭无泪,最后决定拿掉那个库,本身改改style得了。深入的教训。程序员
做为程序员通常都比较惧怕搞界面,这下硬着头皮上,折腾折腾Blend,抄抄改改各类style,弄着弄着竟然能看懂个大概了。最后在本身创建的UI库项目中如何组织资源有了一些总结,进入正题:app
“Generic.xaml” 早有耳闻,不清楚究竟有什么做用。此次Google之,stackoverflow上早已有人发问。What is so special about Generic.xaml?ide
第一个答案清晰明了。code
Every Control in WPF has a default Style that provides, among other things, the Control's default
ControlTemplate
. WPF looks for the default style in a special resource dictionary in the Themes folder in the same assembly as the control. The key for the default style is provided by theControl.DefaultStyleKey
dependency property, the default value of which is overridden in each sub-class of Control.ormThe name of the resource dictionary depends on the current Windows theme e.g. on Vista using the Aero theme, the dictionary is called Aero.NormalColor.xaml, on XP using the default theme it is Luna.NormalColor.xaml. If the style is not found in the theme dictionary, it looks in Generic.xaml i.e for controls whose look doesn't depend on the theme.blog
This only applies to any custom controls you have defined i.e. classes derived from Control, directly or indirectly. You can change the default style for a standard control by deriving from it and calling
DefaultStyleKeyProperty.OverrideMetadata
in the static constructor, but you then have to supply the full style including ControlTemplate.ciNote that you can tell WPF to look in an external assembly for your default style by using the ThemeInfo attribute. The external assembly must be named
<
YourAssembly>
.<
ThemeName>
.dll e.g. PresententationFramework.Aero.dll.资源
讲解了Generic.xaml的前因后果。顺便提了如何使用DefaultStyleKeyProperty.OverrideMetadata 来改变WPF查找一个control的默认style时用的类型。还提到了 ThemeInfo.get
下面这篇文章,Structuring Your XAML Sources,代码演示的很是清晰。经过它还能了解建立一个Custom Control的典型作法,颇有帮助。整体来讲,Generic.xaml在UI Library中的好处就是,使用这个library的项目不用再引用library的resource dictionary,UI Library中定义的custom control也能自动地找到它的默认style。it
看文章附带的源代码,以及开源库的代码,发现它们都在AssemblyInfo.cs中有ThemeInfo. 这是必不可少的。
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]