在Silverlight里面建自定义控件(Templated Control),会在工程下生成一个Themes文件夹,并在其中包含一个generic.xaml文件。这是一个ResourceDictionary文件,所有的自定义控件的默认样式(Default Style)都必须放在这里。
最原始的办法就是把所有样式都直接写在generic.xaml文件里,但如果自定义控件足够多,generic.xaml 达到了好几千行,管理起来当然十分麻烦。后来在同事的推荐下,得到两种方法可以将各自定义控件的样式分开管理,总算解决了这一令人头疼的问题。
MergeDefaultStyle方法
如果研究过Silverlight Toolkit的源代码,会发现里面所有的自定义控件都有一个单独的xaml文件来保存控件的默认样式,当然这些文件是不起作用的。最初以为是先用单独的xaml文件来写控件样式,然后再拷贝到generic.xaml里,也就是人工同步。
然而现在发现MergeDefaultStyle方法。MergeDefaultStyle就是通过给所有单独的xaml文件应用一种特殊的 Build 方法,在 Build 工程的时候,自动把 xaml 文件的内容整合到 generic.xaml 里去。
重点步骤是:
1. 拷贝里面的代码或者直接下载MergeDefaultStyle.dll。
2. 在VS里面Unload你的工程,然后编辑工程文件,或者直接用文本编辑器打开csproj文件。
3. 在最后加上下面这段代码:
- <UsingTask
- TaskName="Engineering.Build.Tasks.MergeDefaultStylesTask"
- AssemblyFile="$(EngineeringResources)\Engineering.Build.dll" />
注意:AssemblyFile 的值是你放MergeDefaultStyle.dll的位置,可以用相对路径。
4. 再在后面加上这一段代码:
- <!-- Add "DefaultStyle" as a Build Action in Visual Studio -->
- <ItemGroup Condition="'$(BuildingInsideVisualStudio)'=='true'">
- <AvailableItemName Include="DefaultStyle" />
- </ItemGroup>
- <!--
- Merge the default styles of controls
- (only if any of the DefaultStyle files is
- more recent than the project's generic.xaml file)
- before compilation
- dependencies are processed.
- -->
- <PropertyGroup>
- <PrepareResourcesDependsOn>
- MergeDefaultStyles;
- $(PrepareResourcesDependsOn);
- </PrepareResourcesDependsOn>
- </PropertyGroup>
- <Target
- Name="MergeDefaultStyles"
- Inputs="@(DefaultStyle)"
- Outputs="$(MSBuildProjectDirectory)\generic.xaml">
- <MergeDefaultStylesTask
- DefaultStyles="@(DefaultStyle)"
- ProjectDirectory="$(MSBuildProjectDirectory)" />
- </Target>
- <!--
- Touch DefaultStyles on Rebuild to force generation of generic.xaml.
- -->
- <PropertyGroup>
- <RebuildDependsOn>
- TouchDefaultStyles;
- $(RebuildDependsOn);
- </RebuildDependsOn>
- </PropertyGroup>
- <Target Name="TouchDefaultStyles">
- <Touch Files="@(DefaultStyle)" ForceTouch="true" />
- </Target>
5. 重新 Load 你的工程。
6. 选择有默认样式的单独的xaml,在属性窗口的 Build Action 里面选择 DefaultStyle 。
7. 编译整个工程,再打开generic.xaml文件,你会发现 xaml 文件里的内容已经拷到generic.xaml里面了。
这一方法适用于Silverlight 3及Silverlight 4 。
MergedDictionary方法
上面的方法可谓是一劳永逸了,但多少有点不官方。而且其实还是generic.xaml掌控全局,一旦一个xaml文件出了纰漏,会影响所有的控件跟着出错。这样排查起来也麻烦的很。
于是在Silverlight 3里就出来了一个更简单更官方的方法。如前所述,generic.xaml文件包含了一个ResourceDictionary,而Silverlight 3里面的ResourceDictionary 多了一个MergedDictionaries的属性,可以把其他ResourceDictionary通过资源路径整合到一个ResourceDicionary里面。
其实新建一个Silverlight导航应用时,就可以在App.xaml 里面看到这一属性的应用。需要注意的是,在 App.xaml 里面是可以用相对路径的,而在 generic.xaml 里面,不可以用相对路径,而应当用 "/AssemblyName;component/path”的方法说明文件路径。
比如你的工程的AssemblyName是Slippor.Controls,而xaml的路径是CustomControl文件夹下的CustomControl.xaml 。则应该在generic.xaml里面如下写:
- <ResourceDictionary xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
- <ResourceDictionary.MergedDictionaries>
- <ResourceDictionary Source="/Slippor.Controls;component/CustomControl/CustomControl.xaml"/>
- </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>这一方法适用于Silverlight 3及Silverlight 4。
原文作者:smjack
原文地址:http://www.cnblogs.com/smjack/archive/2010/08/24/1807706.html
【编辑推荐】