跨平台WPF框架Avalonia教程 三
控件
在 Avalonia UI 中,控件是创建用户界面的基本构建块。它们代表各种交互元素,如按钮、文本框、滑块等。了解控件对于使用 Avalonia UI 开发应用程序至关重要。
什么是控件?
控件是用户界面元素,允许用户与应用程序交互。它们提供输入、显示和操作数据的功能。根据其目的和行为,控件可以分为多种类型。
- 按钮(Button):按钮常用于在单击或触摸时触发操作。它们可以包含文本、图标或两者,并经常用于提交表单、打开对话框或执行命令等任务。
- 文本框(TextBox):文本框允许用户输入和编辑文本。它们用于捕获用户输入,例如用户名、密码或任何形式的文本信息。文本框还可以根据特定输入模式和验证进行自定义。
- 标签(Label):标签用于显示静态文本或其他控件的标题。它们为用户提供额外的信息或上下文,通常是不可交互的。
- 复选框(CheckBox)和单选按钮(RadioButton):复选框和单选按钮用于选择和多选项。复选框允许用户选择一个或多个选项,而单选按钮允许用户从一组选项中选择一个。
- 滑动条(Slider):滑动条用于从范围中选择一个值。它们提供了一个可视化表示值的方式,可以通过拖动滑块的手柄来调整值。滑块通常用于设置诸如音量控制或图像调整等设置。
- 列表框(ListBox)和下拉列表框(ComboBox):列表框和下拉列表框允许用户从列表或下拉菜单中选择项目。列表框同时显示多个项目,而下拉列表框在初始状态下显示一个项目,并在点击时展开显示列表。
这些只是 Avalonia UI 中众多可用控件的一些例子。每个控件都有自己的一组属性、方法和事件,允许开发人员根据应用程序的需求自定义其外观和行为。
开始使用内置控件
要开始使用 Avalonia UI 中的控件,您可以参考每种控件类型的文档。文档提供了详细的解释、示例和代码片段,帮助您有效地理解和使用这些控件。
- 按钮控件文档
- 文本框控件文档
- 标签控件文档
- 复选框控件文档
- 滑动条控件文档
- 列表框控件文档
通过探索这些资源,您将对 Avalonia UI 中的控件使用建立坚实的基础,并能够为应用程序创建丰富且交互性强的用户界面。
内置控件的类型
Avalonia UI 的内置控件可以大体分类为以下类型:
- 绘制控件(Drawn Controls)
- 布局控件(Layout Controls)
- 用户控件(User Controls)*
- 模板化控件(Templated Controls)
- 完全可定制(Fully Customizable)
- 部分可定制(Partially Customizable)
*User controls are only available for apps.
备注
这些分类与 选择自定义控件类型 中的讨论有一定关联。
绘制控件
绘制控件负责生成其自己的几何图形或位图并进行渲染。这些控件的示例包括 Border
、TextBlock
和 Image
。绘制控件是用于构建其他所有内容的基础控件。
大多数绘制控件具有可以用于调整其外观和大小的标准属性,但它们不允许重新模板化。这意味着作为应用程序开发人员,您不能在不陷入 C#、派生新版本的控件并拦截渲染方法的情况下更改这些控件的功能或样式。
布局控件
布局控件是特殊的,因为它们本身没有外观。像 Grid
、StackPanel
等布局控件负责定义其子元素的布局,并充当父容器。子控件负责渲染 UI,而布局父控件只设置大小和位置(它们本身没有外观)。
应用程序开发人员很少修改框架提供的布局控件。
备注
某些布局控件,如 Grid
,具有诸如 Background
之类的属性,以简化常见用例。使用这些属性确实为这些控件提供了一些外观。
用户控件
Avalonia UI 自身不会提供 UserControl
,因为这不通用。有关在应用程序中创建和使用 UserControl
的更多信息,请参阅 选择自定义控件类型。
模板化控件
Avalonia UI 中的大多数标准控件都是模板化控件,这意味着它们的视觉外观是在与功能分离的 XAML 控件模板中定义的。这是 WPF 中起源的无外观控件概念的基础。
应用程序开发人员可以更改模板化控件的 XAML 模板,使其外观完全不同。这种功能并非所有 UI 框架都具备的,是基于 XAML 的 UI 框架中最强大的功能之一。
备注
重新模板化控件是应用程序开发人员的最后手段。这还意味着您将负责将模板与上游的任何更改保持同步。相反,更好的做法是:
- 尝试使用现有属性自定义控件
- 使用 Avalonia UI 强大的样式选择器创建新样式,以修改现有模板中所需的内容
- 作为最后手段,重新模板化
完全可定制
Avalonia UI 中的大多数模板化控件都是完全可定制的。这意味着可以完全替换控件的模板并更改其外观。Button
控件是一个很好的例子,但 Avalonia UI 中的所有模板化控件都试图默认情况下是完全可定制的。对于完全可定制的模板化控件,应用程序几乎可以完全自由地样式或更改 UI 中所见的一切。
部分可定制
实际上,不总是有完全可替换的控件模板。在控件设计中,在支持常见用例和使控件完全可重新模板化之间存在一种平衡。对于高复杂性控件(例如 DataGrid
),该平衡偏向于支持预期用例,并且不应该完全重新模板化控件。这些控件通常还具有非常多的模板部件(由 C# 控件实现直接使用的必需控件元素)。
在 DataGrid
这样的控件中,仍然可以重新模板化控件的各个组件或部分。只是完全改变它的外观和功能是极其困难的。
像 DataGrid
这样的部分可定制的模板化控件在由框架本身提供的第一方控件中很少见。
创建控件
在 Avalonia 中,您可以灵活地根据应用程序的特定要求创建所有类型的自定义控件。有关更多信息,请参阅创建控件。
内置控件
以下是一些常用的 Avalonia 控件,按类别列出:
布局控件
控件 | 描述 |
---|---|
Border | 用边框和背景装饰单个子元素。 |
Canvas | 在指定位置显示子控件。 |
Dock Panel | 将子控件沿指定边缘(顶部、底部、左侧、右侧)排列,并使其中一个填充剩余空间。 |
Expander | 具有标题区域(始终可见)和可折叠的内容区域(单个子元素)。 |
Grid | 将子控件排列在网格的单元格中,按行和列定位。单元格可以跨行和跨列。 |
Grid Splitter | 可以添加到网格中,允许用户在运行时调整行或列大小。 |
Panel | 将子控件堆叠在一起。 |
Relative Panel | 允许多个子控件。子控件的位置和对齐方式可以相对于面板本身指定,也可以相对于其他子控件指定。可以指定子控件的大小,也可以根据关系和对齐方式计算大小。 |
Scroll Viewer | 如果(单个)子控件大于可用空间,则添加滚动条和滚动行为。 |
Split View | 在其(单个子控件)内容区域的边缘添加可折叠的窗格。 |
Stack Panel | 允许多个子控件,按顺序水平或垂直排列。 |
Tab Control | 标签控件允许将视图细分为标签项。 |
Uniform Grid | 允许多个子控件,以网格形式排列,单元格具有统一的列和行大小。 |
Wrap Panel | 将子控件从左到右按顺序排列,当宽度不足时,换行显示。 |
按钮
控件 | 描述 |
---|---|
Button | 基本按钮控件 - 可以显示文本、图标或两者。具有标准的“点击”行为。 |
Repeat Button | 按钮在按下并保持按住时重复引发其点击事件。 |
Radio Button | 按钮具有选中状态。它可以放置在一组中,以使一个按钮的选择取消所有其他按钮的选择。 |
Toggle Button | 按钮具有选中状态和未选中状态。后续点击“切换”此状态。通过“checked”伪类可以为选中状态和未选中状态分配不同的样式。 |
Button Spinner | 一个带有两个旋转按钮和内容区域的控件。 |
Split Button | 此按钮具有主要和次要部分,可以独立按下。主要部分的行为类似于标准按钮,而次要部分则打开一个带有附加操作的弹出菜单。 |
Toggle Split Button | 此按钮具有主要和次要部分,可以独立按下。主要部分的行为类似于切换按钮,而次要部分打开一个带有附加操作的弹出菜单。 |
重复数据控件
这些控件以表格或列表格式显示重复数据:
控件 | 描述 |
---|---|
Data Grid | 在可自定义的网格中显示数据。 |
Items Control | 显示来自绑定数据源的项目集合。 |
Items Repeater | 显示来自绑定数据源的重复数据。它具有布局模板和数据模板。 |
List Box | 一个包含可选择项的控件。 |
Combo Box | 一个带有下拉列表的控件,其中的项目可以选择。 |
文本显示和编辑
Control | Description |
---|---|
Auto Complete Box | 一个显示文本框用于用户输入和一个下拉框,其中包含根据已输入内容可能匹配的项的控件。 |
Text Block | 用于显示文本块的控件。只读。 |
Text Box | 用于显示或编辑文本的控件,没有格式限制。 |
Masked Text Box | 用于在掩码中显示文本;或用于使用掩码编辑文本,以防止无效的用户输入。 |
值选择
控件 | 类型 | 描述 |
---|---|---|
Check Box | Boolean | 以勾选标记形式表示的 True 值。点击交互切换值。具有显示“未知”值的选项。 |
Slider | Double | 相对于最大值和最小值的相对值,以滑动条按钮在滑动条轨道上的位置表示。拖动滑动条按钮可以在最大值和最小值之间更改值。键盘和点击交互也可以微调值。 |
Calendar | DateTime | 日历是用户选择日期或日期范围的控件。 |
Calendar Date Picker | DateTime | 日期选择器的扩展,包括文本框和按钮。 |
Color Picker | Color / HsvColor | 颜色选择器支持用户使用光谱、调色板和组件滑块选择和编辑颜色。它还支持可选的 alpha 分量、RGB 或 HSV 颜色模型和十六进制颜色值。 |
Date Picker | DateTime | 日期选择器有三个“微调”控件,允许用户选择日期值。 |
Time Picker | TimeSpan | 时间选择器有三个“微调”控件,允许用户选择小时、分钟和秒钟。 |
显示图像
控件 | 描述 |
---|---|
Image | 显示位图或矢量图像。 |
Path Icon | 使用当前的Foreground 绘制矢量图像。 |
菜单和弹出框
控件 | 描述 |
---|---|
Menu | 显示应用程序菜单。 |
Flyouts | 将弹出菜单或上下文菜单附加到控件。 |
Tool Tip | 当鼠标悬停在控件上时显示工具提示。 |
选择自定义控件类型
Avalonia提供了多种方法来创建自定义控件以满足应用程序的特定需求。了解不同类型的自定义控件将帮助您选择最合适的方法来满足您的需求。在Avalonia中,常见的自定义控件类型有用户控件(UserControl
)、模板控件(TemplatedControl
)和自绘控件。
用户控件(UserControl)
用户控件是在Avalonia中创建自定义控件的一种高级方法。它允许您通过组合现有控件并使用XAML定义布局来构建一个控件。用户控件充当一个容器,封装了多个控件,并提供了一个连贯的用户界面。
信息
通常,用户控件用于表示应用程序中的专用视图,比如“用户详细信息视图”,而不是用作通用的用户界面元素。
创建用户控件需要以下步骤:
-
定义XAML:创建一个新的
UserControl
XAML文件,通过放置控件、设置属性和应用样式来定义控件的布局和外观。 -
Code-behind:可选项,您可以定义额外的代码后台逻辑来处理事件、修改行为或为用户控件提供额外的功能。
-
重用和定制: 用户控件可以在应用程序中轻松重用和定制。当您希望封装一组特定的控件和行为为可重用的组件或"视图"时,它们特别有用。
信息
要了解这些概念的完整、可运行的示例,请查看示例应用程序.
模板控件(Templated/Lookless Controls)
模板控件(也称为“Lookless控件”)为在Avalonia中创建自定义控件提供了更高级和可自定义的方法。模板控件将控件的行为和逻辑与其可视外观分离,允许应用程序开发人员通过控件模板进行样式化和模板化。
对于模板控件,您在code-behind类中定义控件的行为和属性,而视觉外观则通过在XAML中定义控件模板来指定。这种分离允许应用程序开发人员自定义控件的外观和给人的感觉,而不会修改其底层行为。
信息
模板控件通常用于通用的用户界面元素,不特定于业务逻辑,可能需要不同的主题或视觉样式。Avalonia提供的大多数内置控件都是模板控件。
创建模板控件需要以下步骤:
-
定义控件类:创建一个新的类,该类派生自
TemplatedControl
。这个类定义了控件的行为、属性和事件。 -
控件模板:在XAML中创建一个ControlTheme,指定控件的视觉外观和结构。控件模板定义了控件的部分以及它们应该如何被样式化。
-
样式和模板化:应用程序开发人员可以通过修改控件模板或应用样式来自定义控件的外观。这样可以实现应用程序中统一和统一的视觉设计。
模板控件提供了更大的灵活性和可重用性,使它们非常适合您希望提供一个可以根据不同视觉主题进行样式化或适应各种用户偏好的控件的场景。
自绘控件
自绘控件在Avalonia中提供了最高级别的定制。使用自绘控件,您可以完全控制控件的视觉元素的渲染,从而创建独特而复杂的视觉外观。
信息
自绘控件通常用于表示大部分非交互式的图形元素,不需要进行主题化。
要创建自绘控件,您需要重写控件的Render
方法,并使用低级别的绘制API(例如DrawingContext
)来定义控件的外观。这种方法可以对控件的每个像素进行精细控制,实现高度个性化的可视化。
创建自绘控件的步骤如下:
-
定义控件类:创建一个新的类,该类派生自
Control
。这个类将定义控件的行为和渲染逻辑。 -
重写Render方法:在控件类中重写
Render
方法,并使用DrawingContext
来绘制控件的内容。
定义属性
在Avalonia UI中,控件属性允许您公开自定义控件的可配置方面,使您的控件的用户能够定制其行为和外观。本文档将介绍如何为自定义控件定义属性。
样式化属性
Avalonia中的样式化属性为控件提供了一种强大而灵活的定义属性的方式。这些属性专门设计用于支持Avalonia的样式化系统和数据绑定。在Avalonia中,样式化属性通过使用AvaloniaProperty
类进行注册。
Avalonia的样式化属性具有以下主要特点:
-
样式支持:可以通过样式和在XAML或编程中定义的setter轻松地进行定位和修改。
-
继承:支持继承,这意味着在父控件上定义的属性值可以自动继承到其子控件上,除非明确覆盖。
-
默认值:可以在控件级别或控件模板中指定默认值,确保在多个控件实例中保持一致的行为。
-
属性值优先级:它们遵循明确定义的优先级顺序,允许根据本地值、样式setter、触发器和默认值等因素解析值。
-
验证和强制转换:样式化属性允许控件验证和强制转换传递给它的值,确保控件永远不会处于无效状态。
在Avalonia中,样式化属性通常用于控件的属性,这些属性旨在通过样式轻松定制,从而实现基于各种条件的外观和行为的动态变化。
示例
以下是如何为假设的自定义按钮控件定义自定义样式化属性的示例:
public class MyCustomButton : Button
{
public static readonly StyledProperty<int> RepeatCountProperty =
AvaloniaProperty.Register<MyCustomButton, int>(nameof(RepeatCount), defaultValue: 1);
public int RepeatCount
{
get => GetValue(RepeatCountProperty);
set => SetValue(RepeatCountProperty, value);
}
}
在此示例中,为MyCustomButton
控件定义了一个名为RepeatCount
的自定义整数属性。该属性通过AvaloniaProperty
系统进行注册,使得用户可以访问、修改、应用样式和进行数据绑定。还定义了CLR属性,以方便使用该属性,使其在使用上与标准.NET API一致。
定义事件
在Avalonia中,事件允许您的自定义控件进行通信并通知用户特定的操作或事件发生。通过定义事件,您为控件的使用者提供了一种在其应用程序中响应和处理这些事件的方法。本文档将指导您如何为自定义控件定义事件。
路由事件
Avalonia中的路由事件提供了一种处理事件的机制,这些事件可以在控件树中传播(或“路由”),允许多个控件对相同的事件做出响应。路由事件提供以下关键特性:
-
事件路由:路由事件可以沿着树向上(冒泡)或向下(隧道)传播,使得不同级别的控件可以处理相同的事件。这允许更灵活和集中的事件处理。
-
事件处理程序:路由事件使用事件处理程序来响应事件。事件处理程序可以与特定控件关联,也可以附加到视觉树中的更高级别以处理来自多个控件的事件。
-
已处理状态:路由事件具有
Handled
属性,可用于标记事件为已处理,阻止进一步的传播。这允许对事件处理进行精细的控制。 -
事件路由策略:Avalonia支持不同的路由策略,如冒泡、隧道和直接路由。这些策略决定了控件接收和处理事件的顺序。 Avalonia的路由事件在需要处理可能发生在嵌套控件内部的事件时特别有用,或者当您希望在视觉树的较高级别集中事件处理逻辑时。
示例
以下是为假设的自定义滑块控件定义路由事件的示例:
public class MyCustomSlider : Control
{
public static readonly RoutedEvent<RoutedEventArgs> ValueChangedEvent =
RoutedEvent.Register<MyCustomSlider, RoutedEventArgs>(nameof(ValueChanged), RoutingStrategies.Direct);
public event EventHandler<RoutedEventArgs> ValueChanged
{
add => AddHandler(ValueChangedEvent, value);
remove => RemoveHandler(ValueChangedEvent, value);
}
protected virtual void OnValueChanged()
{
RoutedEventArgs args = new RoutedEventArgs(ValueChangedEvent);
RaiseEvent(args);
}
}
在此示例中,为MyCustomSlider
控件定义了一个名为ValueChangedEvent
的自定义路由事件。该事件通过RoutedEvent
系统进行注册,使得用户可以订阅它。还定义了CLR事件,以方便使用该事件,使其在使用上与标准.NET API一致。