练习:创建第一个 XAML 页
电力公司的工程师会定期拜访客户,修理电器和执行其他电力维护任务。 该应用的部分功能使工程师能够记录有关拜访的信息。 它可显示简单的编辑器,工程师可以在其中输入详细信息并保存这些信息。
Android 端的应用如下所示:
系统要求在此页面中添加一些其他功能。 在开始之前,如果需要了解页面的创建方式,请查看源代码。 你会注意到 UI 完全是用 C# 代码创建的。 虽然此方法有效,但它会将处理布局的代码与控制 UI 工作方式的代码混合在一起。 你意识到,过不了多久,应用的这两方面内容会存在锁定在一起的风险,使未来的维护变得困难,而且随着更多功能的增加,应用可能会变得更加脆弱。 因此你决定通过从应用中提取定义布局的 C# 代码,并用 XAML 页面替换它,从而将 UI 设计与 UI 逻辑分开。
本模块使用 .NET 8.0 SDK。 通过在首选命令终端中运行以下命令,确保你已安装 .NET 8.0:
dotnet --list-sdks
将显示类似于以下示例的输出:
6.0.317 [C:\Program Files\dotnet\sdk]
7.0.401 [C:\Program Files\dotnet\sdk]
8.0.100 [C:\Program Files\dotnet\sdk]
确保列出了以 8
开头的版本。 如果未列出任何版本或未找到命令,请安装最新的 .NET 8.0 SDK。
查看现有应用
在计算机上本地克隆此练习的 GitHub 存储库。
注意
最好将练习内容克隆或下载到较短的文件夹路径(例如 C:\dev),以避免生成进程生成的文件超过最大路径长度。
移动到存储库本地副本中的 exercise1 文件夹。
打开此文件夹或 Visual Studio Code 中文件夹中的 Notes.sln Visual Studio 解决方案文件。
在解决方案资源管理器窗口中,展开 Notes 项目,展开 MainPage.xaml 文件,然后打开 MainPage.xaml.cs 文件。
查看此文件中定义的 MainPage 类。 构造函数包含用于创建 UI 的以下代码:
public MainPage() { var notesHeading = new Label() { Text = "Notes", HorizontalOptions = LayoutOptions.Center, FontAttributes = FontAttributes.Bold }; editor = new Editor() { Placeholder = "Enter your note", HeightRequest = 100 }; editor.Text = File.Exists(_fileName) ? File.ReadAllText(_fileName) : string.Empty; var buttonsGrid = new Grid() { HeightRequest = 40.0 }; buttonsGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1.0, GridUnitType.Auto) }); buttonsGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(30.0, GridUnitType.Absolute) }); buttonsGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1.0, GridUnitType.Auto) }); var saveButton = new Button() { WidthRequest = 100, Text = "Save" }; saveButton.Clicked += OnSaveButtonClicked; Grid.SetColumn(saveButton, 0); buttonsGrid.Children.Add(saveButton); var deleteButton = new Button() { WidthRequest = 100, Text = "Delete" }; deleteButton.Clicked += OnDeleteButtonClicked; Grid.SetColumn(deleteButton, 2); buttonsGrid.Children.Add(deleteButton); var stackLayout = new VerticalStackLayout { Padding = new Thickness(30, 60, 30, 30), Children = { notesHeading, editor, buttonsGrid } }; this.Content = stackLayout; }
UI 包括一个
VerticalStackLayout
,其中含有一个Label
、一个Editor
和一个三列的Grid
。 第一列包含“saveButton”控件,第二列是空格,第三列包含“deleteButton”控件。下图演示了 UI 结构:
请注意,MainPage 类还包含按钮的事件处理方法,以及一些用于初始化
Editor
控件的代码。 此代码与 UI 定义没有区别。在 Windows 上生成并运行应用,只为查看它的外观。 选择 F5 以生成并运行应用。
完成后关闭应用并返回到 Visual Studio 或 Visual Studio Code。
创建一个 XAML 版本的 UI
打开 MainPage.xaml 文件。 此页中的标记表示空的 MAUI 内容页:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Notes.MainPage"> </ContentPage>
将
VerticalStackLayout
控件添加到内容页:<ContentPage ...> <VerticalStackLayout Margin="30,60,30,30"> </VerticalStackLayout> </ContentPage>
将
Label
控件添加到VerticalStackLayout
。 设置此控件的 Text、HorizontalTextAlignment 和 FontAttributes 属性,如下所示:<ContentPage ...> <VerticalStackLayout ...> <Label Text="Notes" HorizontalOptions="Center" FontAttributes="Bold" /> </VerticalStackLayout> </ContentPage>
将
Editor
控件添加到VerticalStackLayout
:<ContentPage ...> <VerticalStackLayout ...> <Label .../> <Editor x:Name="editor" Placeholder="Enter your note" HeightRequest="100" /> </VerticalStackLayout> </ContentPage>
将子级
Grid
添加到VerticalStackLayout
。 该Grid
应该有三列;第一列和第三列的大小能自动调整,而第二列有固定宽度 - 30:<ContentPage ...> <VerticalStackLayout ...> <Label .../> <Editor .../> <Grid ColumnDefinitions="Auto, 30, Auto"> </Grid> </VerticalStackLayout> </ContentPage>
向子
Grid
的第一列添加一个Button
。 这是“保存”按钮:<ContentPage ...> <VerticalStackLayout ...> <Label .../> <Editor .../> <Grid ...> <Button Grid.Column="0" Text="Save" WidthRequest="100" Clicked="OnSaveButtonClicked" /> </Grid> </VerticalStackLayout> </ContentPage>
向子
Grid
的第三列再添加一个Button
。 这是“删除”按钮:<ContentPage ...> <VerticalStackLayout ...> <Label .../> <Editor .../> <Grid ...> <Button ... /> <Button Grid.Column="2" Text="Delete" WidthRequest="100" Clicked="OnDeleteButtonClicked" /> </Grid> </VerticalStackLayout> </ContentPage>
从代码隐藏文件中删除布局代码
在“解决方案资源管理器”窗口中展开 MainPage.xaml 节点并打开 MainPage.xaml.cs 文件。
从 MainPage 类中删除 Editor 字段。
在 MainPage.xaml.cs 文件的 MainPage 构造函数中,删除创建用户界面元素的所有代码,并将其替换为对 InitializeComponent 方法的调用。 添加检查用于存储备注的文件是否存在的代码,如果文件存在,则读取内容并填充“编辑器”控件的“文本”字段。 构造函数应如下所示:
public partial class MainPage : ContentPage { string _fileName = Path.Combine(FileSystem.AppDataDirectory, "notes.txt"); public MainPage() { InitializeComponent(); if (File.Exists(_fileName)) { editor.Text = File.ReadAllText(_fileName); } } ... }
在“生成”菜单中,选择“重新生成解决方案”。 验证应用生成时是否未出现任何错误。
运行该应用程序。 它应像以前一样运作。
如果有时间,请使用 Android 仿真器部署和运行应用。 应用 UI 应类似于本练习开始时的图像中的内容。