65.9K
CodeProject 正在变化。 阅读更多。
Home

在 Blend 中对 WPF 应用进行皮肤化

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (34投票s)

2010年5月4日

CPOL

11分钟阅读

viewsIcon

89305

downloadIcon

1962

了解如何在 Expression Blend 中为 WPF 应用程序换肤。

引言

在本教程中,我将向您展示如何在 Expression Blend 中为 WPF 应用程序换肤。您将创建的应用程序将具有非常简单的 UI,但您将学到的概念将使您能够为具有更广泛用户界面的 WPF 应用程序换肤。

背景

换肤是指向应用程序添加功能的过程,该功能使用户能够在运行时更改其外观和感觉。为 WPF 应用程序换肤需要考虑某些因素,您将在过程中熟悉这些因素。

设计

开始换肤

  1. 启动 Expression Blend 并创建一个名为 Skinning 的新 WPF 项目。确保在 Language(语言)组合框中将 Language(语言)设置为 Visual Basic。
  2. 在 Objects and Timeline(对象和时间轴)中选择 Window 元素,然后在 Properties(属性)面板的 Layout(布局)部分,将宽度设置为 400,高度设置为 300。
  3. 从 Toolbox(工具箱)中选择 Rectangle(矩形)工具,并在窗口上绘制一个矩形。将矩形的 Vertical Alignment(垂直对齐)设置为 top(顶部)。
  4. Image01.jpg

    Image02.jpg

  5. 将矩形重命名为 Header,并为其设置蓝色渐变 Fill(填充)。将其 Stroke(笔触)设置为 No brush(无画笔)。
  6. Image03.jpg

  7. 选择 Window 元素,并在 Properties(属性)面板的 Brushes(画笔)部分,将其 Background(背景)设置为渐变画笔。
  8. Image04.jpg

  9. 选择 Button(按钮)工具,并在 Window 元素中绘制一个按钮。
  10. Image05.jpg

接下来,我们将通过将当前蓝色外观更改为红色来为应用程序换肤。换肤涉及使用 ResourceDictionary,其中包含您希望为应用程序提供的不同外观和感觉。ResourceDictionary 本质上是资源的集合。资源可以是对象的所有属性,或者像按钮这样的控件,可以是样式或模板。要使属性在添加新的 ResourceDictionary 时发生更改,必须为其分配 DynamicResourceDynamicResource 在运行时,当您从一个 ResourceDictionary 切换到另一个时会发生更改。

如果您查看应用程序的 XAML 代码,您会注意到应用程序中元素的任何属性都没有分配 DynamicResource。随着我们继续,这种情况将会改变。

ResourceDictionaries 和 Resources(资源字典和资源)

在接下来的步骤中,我们将创建 ResourceDictionary 和资源。

  1. 单击 Resources(资源)选项卡以打开 Resources(资源)面板,然后单击 Create new resource dictionary(创建新资源字典)按钮。
  2. Image06.jpg

  3. New Item(新项)对话框中,将新的 ResourceDictionary 的名称更改为 BlueSkin.xaml。单击 OK(确定)。BlueSkin.xaml 已添加到 Resources(资源)面板的列表中。
  4. 在 Objects and Timeline(对象和时间轴)中选择 Window 元素,并打开 Properties(属性)面板。
  5. 单击 Brushes(画笔)部分 Background 属性旁边的“Advanced options”(高级选项)按钮。从上下文菜单中选择 Convert to New Resource(转换为新资源)。这将打开 Create Brush Resource(创建画笔资源)对话框。
  6. Create Brush Resource(创建画笔资源)对话框中,将名称更改为 WindowBackground,并选择 Resource Dictionary(资源字典)选项按钮。确保在组合框中将 BlueSkin.xaml 作为目标。单击 OK(确定)。如果您现在切换到 XAML 视图,您会注意到 Window 元素的 Background 属性已分配了一个名为 WindowBackgroundDynamicResource
  7. 选择我们添加的矩形。在 Properties(属性)面板中,单击 Fill 属性的 Advanced options(高级选项)按钮,然后从上下文菜单中选择 Convert to New Resource(转换为新资源)。
  8. 将新资源命名为 ‘HeaderFill’,并选择 ‘Resource dictionary’(资源字典)选项按钮。单击 OK(确定)。
  9. 选择 Resources(资源)选项卡以打开 Resources(资源)面板。创建一个新的 Resource Dictionary(资源字典)并将其命名为 RedSkin.xaml
  10. 选择 Window 元素,并将其 Background 的渐变画笔更改为红色渐变。
  11. Image07.jpg

  12. 单击 Background 属性的“Advanced options”(高级选项)按钮,然后从上下文菜单中选择 Convert to new Resource(转换为新资源)。
  13. Create Brush Resource(创建画笔资源)对话框中,将名称更改为 WindowBackground,并选择 Resource dictionary(资源字典)选项按钮。从组合框中选择 RedSkin.xaml,然后单击 OK(确定)。忽略警告。如果您现在查看 Resources(资源)面板并展开 BlueSkinRedSkin.xaml,您会注意到两个资源字典都具有同名的资源。
  14. Image08.jpg

    由于 BlueSkin 中的 WindowBackgroundDynamicResource,因此当切换资源字典时,它将与 RedSkin 中的 WindowBackground 交换。如果名称不同,背景颜色将不会改变,因为您的应用程序不知道应从新的资源字典中应用哪个资源。

  15. Objects and Timeline(对象和时间轴)中选择 Header,并为其 Fill 设置红色渐变。
  16. Image09.jpg

  17. 单击 Fill 属性的“Advanced options”(高级选项)按钮,然后从上下文菜单中选择 Convert to New Resource(转换为新资源)。
  18. 在 ‘Create Brush Resource’(创建画笔资源)对话框中,将名称更改为 HeaderFill,并选择 Resource dictionary(资源字典)选项按钮。从组合框中选择 RedSkin.xaml,然后单击 OK(确定)。

现在我们已经完成了资源字典的创建,让我们添加必要的代码以允许我们在运行时切换到红色主题。

编码

  1. 选择添加到应用程序中的按钮,然后在 Properties(属性)面板中,单击 Events(事件)按钮。
  2. Image10.jpg

  3. 在 Click(单击)事件文本框中,键入 ‘Btn1_Click’,然后按 Enter。Blend 的代码编辑器将打开,供您添加按钮单击事件所需的代码。
  4. Image11.jpg

  5. Btn1_Click 事件中,键入以下代码:
  6. Dim RedSkin as New ResourceDictionary
    RedSkin.Source = New Uri("RedSkin.xaml", UriKind.Relative)
    Me.Resources.MergedDictionaries.Clear()
    Me.Resources.MergedDictionaries.Add(RedSkin)

    上述代码创建了一个名为 RedSkin 的新资源字典,并将其源属性设置为我们之前创建的资源字典 RedSkin.xaml。然后,我们清空 MergedDictionaries 集合,并添加一个新的资源字典。MergedDictionariesResourceDictionary 对象集合。如果您的应用程序需要维护与现有资源字典的链接,请避免清空 MergedDictionaries 集合,而是使用 Add 方法,键入以下代码:

     Me.Resources.MergedDictionaries(0) = RedSkin

    此代码将资源字典放置在 MergedDictionaries 集合的第一个位置。

  7. 选择 Resource(资源)面板选项卡,然后展开 App.xaml
  8. 由于我们的应用程序目前链接到 RedSkin.xaml,因此我们将删除此链接。右键单击 ‘Linked To: RedSkin.xaml’,然后从上下文菜单中选择 Delete(删除)。在弹出的对话框中单击 Yes(是)。
  9. 运行应用程序。单击按钮。请注意,界面已更改为红色外观。
  10. 关闭应用程序。

到目前为止,我们已经成功更改了应用程序中部分元素的显示效果。即使切换主题后,按钮对象的外观仍然保持不变。更改控件的外观与更改矩形或椭圆形等形状对象的外观略有不同。要更改控件对象的外观,我们必须使用样式或模板。

样式允许我们更改控件的外观,但会限制我们,因为我们无法直接访问构成控件的元素。另一方面,模板允许我们直接操作构成控件的元素。在模板中,您可以添加、删除或修改构成控件整体结构的元素。因此,在为控件换肤时,您可以选择使用样式或模板。

控件换肤

在接下来的步骤中,我们将使用模板为按钮控件换肤。

  1. 选择按钮对象。右键单击按钮,然后选择 Edit Template > Create Empty(编辑模板 > 创建空白)。
  2. 在 ‘Create ControlTemplate Resource’(创建 ControlTemplate 资源)对话框中,保留名称不变,然后选择 Resource dictionary(资源字典)选项按钮。BlueSkin.xaml 应该是组合框中的唯一值,因为我们删除了与 RedSkin 的链接。单击 OK(确定)。
  3. 放大空的 Control Template(控件模板)。
  4. 在空的网格中绘制一个矩形,然后右键单击它并选择 Auto Size > Fill(自动调整大小 > 填充)。矩形应该填充整个网格。
  5. 将矩形重命名为 BtnBackground,并为其设置圆角。
  6. 在 Properties(属性)面板中,确保 Properties(属性)按钮处于活动状态,而不是 Events(事件)按钮。将 StrokeThickness(笔触粗细)更改为 2,并将笔触颜色更改为白色实心画笔。
  7. 选择 Fill(填充),并将其更改为蓝色渐变画笔。
  8. Image12.jpg

  9. 选择工具箱中的 Assets(资源)按钮,然后在 Assets(资源)窗口的 Controls(控件)部分选择 ContentPresenterContentPresenter 将添加到工具箱。
  10. 双击工具箱中的 ContentPresenter 工具将其添加到控件的网格中。将其 Horizontal and Vertical alignments(水平和垂直对齐)设置为 center(居中)。
  11. 再绘制一个矩形。将其笔触设置为 No Brush(无画笔),然后调整其外观,使其看起来像下图所示。如果对齐线阻碍了您的操作,请关闭捕捉。
  12. Image13.jpg

  13. 将两个渐变停止点都更改为白色,并调整最后一个渐变停止点的 alpha 属性为零。
  14. Image14.jpg

    Image15.jpg

  15. 在 Objects and Timeline(对象和时间轴)面板中,单击 Up One Level(上一级)按钮以返回到 Window(窗口)。
  16. Image16.jpg

  17. 在选中按钮对象的情况下,将其 Content(内容)属性更改为 ‘Red’,然后按 Enter。然后将其 Foreground(前景)属性更改为 White(白色)。保存项目。
  18. Image17.jpg

  19. 在 Resources(资源)面板中,右键单击 App.xaml,然后选择 Link to ResourceDictionary > RedSkin.xaml(链接到 ResourceDictionary > RedSkin.xaml)。链接到 RedSkin 会使其在 ‘Create ControlTemplate Resource’(创建 ControlTemplate 资源)对话框的 Resource dictionary(资源字典)组合框中可见。
  20. 选择按钮。右键单击按钮,然后选择 Edit Template > Edit a Copy(编辑模板 > 编辑副本)。
  21. 在 ‘Create ControlTemplate Resource’(创建 ControlTemplate 资源)对话框中,将名称更改为 ButtonControlTemplate1,然后选择 Resource dictionary(资源字典)选项按钮,并从组合框中选择 RedSkin.xaml。单击 OK(确定)。
  22. 在按钮控件模板中,将 BtnBackground 的 Fill(填充)更改为红色渐变。
  23. Image18.jpg

  24. 返回主窗口。在 Resources(资源)面板的 App.xaml 部分删除到 RedSkin.xaml 的链接。在弹出的对话框中单击 Yes(是)。
  25. 运行项目并单击按钮。现在请注意,应用程序中的所有元素都已换肤。一点动画效果可以让我们的按钮在鼠标悬停事件中看起来更像是在点亮,但这可以在您空闲时完成。

我们无法在两个主题之间切换,这有点无趣,所以让我们启用它。

  1. 如果尚未停止应用程序,请停止它。
  2. 选择按钮对象,然后将一个新的按钮复制并粘贴到您的 Window 中。
  3. 将其拖动并放置在第一个按钮下方。
  4. 将新按钮的 Content(内容)属性更改为 ‘Blue’。
  5. Image19.jpg

  6. 选择 Properties(属性)面板的 Events(事件)按钮,然后在 Click(单击)事件文本框中键入 ‘Btn2_Click’。按 Enter 打开代码编辑器窗口。
  7. Btn2_Click 事件中,键入以下代码:
  8. Dim BlueSkin as New ResourceDictionary
    BlueSkin.Source = New Uri("BlueSkin.xaml", UriKind.Relative)
    Me.Resources.MergedDictionaries.Clear()
    Me.Resources.MergedDictionaries.Add(BlueSkin)
  9. 运行项目。请注意,单击这两个按钮允许您在两个主题之间切换。

保存状态

应用程序当前以默认主题 BlueSkin 打开,当您更改主题并关闭应用程序时。为了使应用程序能够以选定的主题打开,我们将使用应用程序设置。

  1. 在 Project(项目)面板中右键单击项目,然后从上下文菜单中选择 Edit in Visual Studio(在 Visual Studio 中编辑)。
  2. Visual Studio 打开后,在 Solution Explorer(解决方案资源管理器)中右键单击项目,然后从上下文菜单中选择 Properties(属性)。这将打开 Properties(属性)窗口。
  3. 选择 Settings(设置)选项卡。创建一个名为 SkinPath 的新设置,类型为 String,范围为 User(用户)。将 Value(值)部分留空。
  4. 双击 MainWindow.xaml.vb 进行编辑。
  5. 从 Class Name(类名)组合框中选择 ‘MainWindow Events’,从 Method Name(方法名)组合框中选择 Loaded
  6. MainWindow_Loaded 事件中,键入以下代码:
  7. 'Check whether SkinPath has a value and create
    'a resource dictionary…
    If My.Settings.SkinPath <> String.Empty Then
        Dim newDictionary As New ResourceDictionary()        
        Dim path As String
        path = My.Settings.SkinPath
        newDictionary.Source = New Uri(path, UriKind.Relative)
        Me.Resources.MergedDictionaries.Clear()
        Me.Resources.MergedDictionaries.Add(newDictionary)
    End If
  8. Btn1_Click 事件中,添加以下代码:
  9. My.Settings.SkinPath = "\RedSkin.xaml"
    My.Settings.Save()
  10. Btn2_Click 事件中,添加以下代码:
  11. My.Settings.SkinPath = "\BlueSkin.xaml"
    My.Settings.Save()

    MainWindow_Loaded 事件中,我们检查设置 SkinPath 是否包含值,并创建一个资源字典,其源属性分配了一个 URI 对象,该对象以设置作为资源字典的位置。在按钮单击事件中,我们将设置 SkinPath 赋为相关资源字典的位置。然后,我们通过调用 Save 方法来持久化设置。

  12. 运行应用程序。
  13. 将主题更改为红色并关闭应用程序。
  14. 再次运行应用程序。请注意,它现在以我们最后应用的皮肤打开。

UserControls 换肤

在换肤 UserControls 时,您可以采取几种方法。

  1. 在创建 UserControl 时,您可以公开构成控件的元素的属性,以便一旦将 UserControl 放置在窗口上,就可以将该属性转换为资源。为此,请使用依赖属性。
  2. 在创建 UserControl 时,从构成控件的元素的属性创建资源,即,当 UserControl 文件在 Blend 中打开时,选择要换肤的元素,并从感兴趣的属性创建资源。

结论

我希望本教程非常有帮助,但我无法在不考虑开发人员是否也应充当设计者的争论的情况下结束。我的想法是,既然 Blend 提供了一个戴上两顶帽子的机会,为什么不这样做呢?我个人的看法是,存在一位开发人员,他也可以成为一名优秀的设计师,反之亦然。

外部链接

历史

  • 2010 年 5 月 4 日:初次发布。
  • 2011 年 1 月 23 日:更新了文章文本。
© . All rights reserved.