Microsoft Expression Blend 的工作方式是生成 Extensible Application Markup Language (XAML),随后进行编译以生成可执行程序。 如果宁愿直接使用 XAML,则还有另一个演练,它使用 XAML 和 Visual Studio(而不是 Blend)创建与此相同的应用程序。 有关详细信息,请参阅 使用 XAML 创建按钮

下图显示了将要创建的自定义按钮。

将形状转换为按钮

在本演练的第一部分,将创建自定义按钮的自定义外观。 为此,首先将矩形转换为按钮。 然后将其他形状添加到按钮的模板,从而创建具有更复杂外观的按钮。 为什么不从常规按钮开始并对其进行自定义? 因为按钮具有不需要的内置功能;对于自定义按钮,从矩形开始会更加轻松。

在 Expression Blend 中创建新项目

  • 启动 Expression Blend。 (单击“开始”,指向“所有程序”,指向“Microsoft Expression”,然后单击“Microsoft Expression Blend”。)

  • 在需要时使应用程序最大化。

  • 在“文件”菜单上,单击“新建项目”。

  • 选择“标准应用程序(.exe)”。

  • 将项目命名为 CustomButton ,然后按“确定”。

    此时,你有一个空白 WPF 项目。 可以按 F5 运行该应用程序。 如你所料,应用程序仅包含一个空白窗口。 接下来,创建一个圆角矩形并将其转换为按钮。

    将矩形转换为按钮

  • 将窗口背景属性设置为黑色:选择窗口,单击“属性”选项卡,然后将 Background 属性设置为 Black

  • 在窗口上绘制一个大约为按钮大小的矩形:选择左侧工具面板中的矩形工具,然后将矩形拖到窗口上。

  • 使矩形的各个角成为圆角:拖动矩形的控制点或直接设置 RadiusX RadiusY 属性。 将 RadiusX RadiusY 的值设置为 20。

  • 将矩形更改为按钮:选择矩形。 在“工具”菜单上,单击“生成按钮”。

  • 指定样式/模板的范围:会显示如下所示的对话框。

    对于“资源名(关键字)”,请选择“全部应用”。 这会使生成的样式和按钮模板应用于所有按钮对象。 对于“定义位置”,请选择“应用程序”。 这会使生成的样式和按钮模板的作用域是整个应用程序。 在这两个框中设置值时,按钮样式和模板会应用于整个应用程序中的所有按钮,在应用程序中创建的任何按钮都会默认使用此模板。

    编辑按钮模板

    你现在有一个已更改为按钮的矩形。 在本部分中,你将修改按钮的模板,并进一步自定义其外观。

    编辑按钮模板以更改按钮外观

  • 进入编辑模板视图:若要进一步自定义按钮的外观,需要编辑按钮模板。 此模板是在将矩形转换为按钮时创建的。 若要编辑按钮模板,请右键单击按钮,选择“编辑控件部件(模板)”,然后选择“编辑模板”。

    在模板编辑器中,请注意,按钮现在分隔为 Rectangle ContentPresenter ContentPresenter 用于在按钮中呈现内容(例如字符串“Button”)。 矩形和 ContentPresenter 都处于 Grid 内部。

  • 更改模板组件的名称:右键单击模板清单中的矩形,将 Rectangle 名称从“[Rectangle]”更改为“outerRectangle”,并将“[ContentPresenter]”更改为“myContentPresenter”。

  • 更改矩形,使其内部为空(类似于圆环):选择“outerRectangle”,将 Fill 设置为“Transparent”,将 StrokeThickness 设置为 5。

    然后将 Stroke 设置为模板将采用的任何颜色。 为此,请单击“笔划”旁的白色小框,选择“CustomExpression”,然后在对话框中键入“{TemplateBinding Background}”。

  • 创建内部矩形:现在,创建另一个矩形(将它命名为“innerRectangle”),并将它对称地放置在 outerRectangle 内部。 对于此类工作,你可能希望进行缩放以使按钮在编辑区域中更大。

    你的矩形看起来可能与图中的矩形不同(例如,它可能具有圆角)。

  • 将 ContentPresenter 移动到上层:此时,文本“Button”可能不再可见。 如果是这样,这是因为 innerRectangle 处于 myContentPresenter 的上层。 若要解决此问题,请拖动 innerRectangle 下层的 myContentPresenter。 重新定位矩形和 myContentPresenter,使其类似于下面这样。

    或者,也可以通过右键单击 myContentPresenter 并按 “向前移动”将其置于顶层。

  • 更改 innerRectangle 的外观:将 RadiusX RadiusY StrokeThickness 值设置为 20。 此外,使用自定义表达式“{TemplateBinding Background}”将 Fill 设置为模板的背景,并将 Stroke 设置为“transparent”。 请注意,innerRectangle 的 Fill Stroke 设置与 outerRectangle 的这些设置相反。

  • 在顶层添加玻璃层:自定义按钮外观的最后一部分是在顶层添加玻璃层。 此玻璃层由第三个矩形组成。 由于玻璃会覆盖整个按钮,因此玻璃矩形在尺寸上类似于 outerRectangle。 因此,只需创建 outerRectangle 的副本即可创建矩形。 突出显示 outerRectangle 并使用 CTRL+C 和 CTRL+V 创建副本。 将此新矩形命名为“glassCube”。

  • 在需要时重新定位 glassCube:如果 glassCube 的位置尚未使其覆盖整个按钮,请将其拖动到位。

  • 为 glassCube 提供与 outerRectangle 略有不同的形状:更改 glassCube 的属性。 首先将 RadiusX RadiusY 属性更改为 10,并将 StrokeThickness 更改为 2。

  • 使 glassCube 看起来像玻璃:使用线性渐变将 Fill 设置为玻璃外观,该渐变为 75% 不透明,在 6 个大致均匀的间隔之间交替使用白色和透明颜色。 下面是渐变停止点的设置内容:

  • 渐变停止点 1:Alpha 值为 75% 的白色

  • 渐变停止点 2:透明

  • 渐变停止点 3:Alpha 值为 75% 的白色

  • 渐变停止点 4:透明

  • 渐变停止点 5:Alpha 值为 75% 的白色

  • 渐变停止点 6:透明

    这会创建“波浪”玻璃外观。

  • 隐藏玻璃层:现在可看到玻璃层的外观,进入“属性”面板的“外观”窗格,将不透明度设置为 0% 以隐藏它。 在接下来的部分中,我们将使用属性触发器和事件来显示和操作玻璃层。

    自定义按钮行为

    此时,你已通过编辑按钮模板自定义了按钮的呈现,但按钮不会如同典型按钮一样响应用户操作(例如,在鼠标悬停在上方、获得焦点和单击时更改外观。)接下来的两个过程演示了如何在自定义按钮中构建此类行为。 我们将从简单的属性触发器开始,然后添加事件触发器和动画。

    设置属性触发器

  • 创建新的属性触发器:选中 glassCube 后,单击“触发器”面板中的“+ 属性”(请参阅下一步后面的图)。 这会创建具有默认属性触发器的属性触发器。

  • 使 IsMouseOver 成为触发器使用的属性:将属性更改为 IsMouseOver 。 这可在 IsMouseOver 属性为 true 时(用户使用鼠标指向按钮时)使属性触发器激活。

  • IsMouseOver 为 glassCube 触发 100% 的不透明度:请注意“触发器记录已开启”(请参阅上图)。 这意味着,在记录开启期间对 glassCube 的属性值进行的任何更改都会成为在 IsMouseOver true 时进行的操作。 在记录期间,将 glassCube 的 Opacity 更改为 100%。

    现在创建了第一个属性触发器。 请注意,编辑器的“触发器”面板 记录了 Opacity 已更改为 100%。

    按 F5 运行应用程序,然后将鼠标指针移到按钮上方并移走。 你应看到,玻璃层会在鼠标悬停在按钮上方出现,在鼠标离开时消失。

  • IsMouseOver 触发笔划值更改:让我们将其他一些操作与 IsMouseOver 触发器关联。 在记录继续进行期间,将所选内容从 glassCube 切换到 outerRectangle。 然后将 outerRectangle 的 Stroke 设置为自定义表达式“{DynamicResource {x:Static SystemColors.HighlightBrushKey}}”。 这会将 Stroke 设置为按钮使用的典型突出显示颜色。 按 F5 以查看鼠标位于按钮上方时的效果。

  • IsMouseOver 触发模糊文本:让我们将另一个操作关联到 IsMouseOver 属性触发器。 当玻璃出现在按钮上时,使按钮的内容显得有点模糊。 为此,我们可以将模糊 BitmapEffect 应用于 ContentPresenter (myContentPresenter)。

    若要使“属性”面板恢复为对 BitmapEffect 进行搜索之前的内容,请清除“搜索”框中的文本。

    此时,我们使用具有多个关联操作的属性触发器创建了鼠标指针进入并离开按钮区域时的突出显示行为。 按钮的另一个典型行为是在它获得焦点时(如单击它后)突出显示。 可以通过为 IsFocused 属性添加另一个属性触发器来添加此类行为。

  • 为 IsFocused 创建属性触发器:使用与 IsMouseOver 相同的过程(请参阅本部分的第一步),为 IsFocused 属性创建另一个属性触发器。 在“触发器记录已开启”期间,将以下操作添加到触发器:

  • glassCube 获取 100% 的 Opacity

  • outerRectangle 获取 Stroke 自定义表达式值“{DynamicResource {x:Static SystemColors.HighlightBrushKey}}”。

  • 创建动画时间线:接下来,将动画时间线关联到 MouseEnter 事件。

    按“确定”创建新时间线后,将显示时间线面板,“时间线记录已开启”会在设计面板中可见。 这意味着我们可以开始在时间线中记录属性更改(对属性更改进行动画处理)。

    可能需要重设窗口和/或面板的大小才能查看显示。

  • 创建关键帧:若要创建动画,请选择要进行动画处理的对象,在时间线上创建两个或更多关键帧,并为这些关键帧设置希望动画在它们之间内插的属性值。 下图指导你创建关键帧。

  • 在此关键帧处缩小 glassCube:选择第二个关键帧后,使用“大小转换”将 glassCube 的大小缩小到其完整大小的 90%。

    按 F5 运行该应用程序。 将鼠标指针移到按钮上。 请注意,玻璃层在按钮上层缩小。

  • 创建另一个事件触发器并将其他动画与它关联:让我们添加另一个动画。 使用与用于创建上一个事件触发器动画类似的过程:

  • 使用 Click 事件创建新的事件触发器。

  • 将新时间线与 Click 事件关联。

  • 对于此时间线,创建两个关键帧,一个帧在 0.0 秒,第二个帧在 0.3 秒。

  • 在 0.3 秒的关键帧突出显示后,将“旋转转换角度”设置为 360 度。

  • 按 F5 运行该应用程序。 单击按钮。 请注意,玻璃层会旋转。

    你已完成了自定义按钮。 你是使用应用于应用程序中所有按钮的按钮模板完成了此任务。 如果离开模板编辑模式(请参阅下图)并创建更多按钮,你会看到其外观和行为类似于自定义按钮,而不是默认按钮。

    按 F5 运行该应用程序。 单击按钮并注意到它们的行为方式全都相同。

    请记住,在自定义模板期间,将 innerRectangle 的 Fill 属性和 outerRectangle 的 Stroke 属性设置为模板背景 ({TemplateBinding Background})。 因此,当你设置各个按钮的背景色时,你设置的背景将用于这些各自的属性。 现在尝试更改背景。 在下图中,使用了不同的渐变。 因此,尽管模板可用于控件(如按钮)的整体自定义,但仍可修改使用模板的控件,使其外观彼此不同。

    总之,在自定义按钮模板的过程中,你已了解如何在 Microsoft Expression Blend 中执行以下操作:

  • 自定义控件的外观。

  • 设置属性触发器。 属性触发器非常有用,因为它们可用于大多数对象,而不仅仅是控件。

  • 设置事件触发器。 事件触发器非常有用,因为它们可用于大多数对象,而不仅仅是控件。

  • 创建动画。

  • 其他:创建渐变、添加 BitmapEffect、使用转换以及设置对象的基本属性。

  • 使用 XAML 创建按钮
  • 样式设置和模板化
  • 使用纯色和渐变进行绘制概述
  • 位图效果概述
  •