练习:创建第一个 XAML 页

已完成

电力公司的工程师会定期拜访客户,修理电器和执行其他电力维护任务。 该应用的部分功能使工程师能够记录有关拜访的信息。 它可显示简单的编辑器,工程师可以在其中输入详细信息并保存这些信息。

Android 端的应用如下所示:

在 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

查看现有应用

  1. 在计算机上本地克隆此练习的 GitHub 存储库

    注意

    最好将练习内容克隆或下载到较短的文件夹路径(例如 C:\dev),以避免生成进程生成的文件超过最大路径长度。

  2. 移动到存储库本地副本中的 exercise1 文件夹

  3. 打开此文件夹或 Visual Studio Code 中文件夹中的 Notes.sln Visual Studio 解决方案文件。

  4. 在解决方案资源管理器窗口中,展开 Notes 项目,展开 MainPage.xaml 文件,然后打开 MainPage.xaml.cs 文件。

  5. 查看此文件中定义的 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 结构:

    示意图显示了 Notes 应用的 UI 结构。

    请注意,MainPage 类还包含按钮的事件处理方法,以及一些用于初始化 Editor 控件的代码。 此代码与 UI 定义没有区别。

  6. 在 Windows 上生成并运行应用,只为查看它的外观。 选择 F5 以生成并运行应用。

  7. 完成后关闭应用并返回到 Visual Studio 或 Visual Studio Code。

创建一个 XAML 版本的 UI

  1. 打开 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>
    
  2. VerticalStackLayout 控件添加到内容页:

    <ContentPage ...>
        <VerticalStackLayout Margin="30,60,30,30">
    
        </VerticalStackLayout>
    </ContentPage>
    
  3. Label 控件添加到 VerticalStackLayout。 设置此控件的 Text、HorizontalTextAlignment 和 FontAttributes 属性,如下所示

    <ContentPage ...>
        <VerticalStackLayout ...>
            <Label Text="Notes"
                   HorizontalOptions="Center"
                   FontAttributes="Bold" />
        </VerticalStackLayout>
    </ContentPage>
    
  4. Editor 控件添加到 VerticalStackLayout

    <ContentPage ...>
        <VerticalStackLayout ...>
            <Label .../>
    
            <Editor x:Name="editor"
                    Placeholder="Enter your note"
                    HeightRequest="100" />
        </VerticalStackLayout>
    </ContentPage>
    
  5. 将子级 Grid 添加到 VerticalStackLayout。 该 Grid 应该有三列;第一列和第三列的大小能自动调整,而第二列有固定宽度 - 30:

    <ContentPage ...>
        <VerticalStackLayout ...>
            <Label .../>
    
            <Editor .../>
    
            <Grid ColumnDefinitions="Auto, 30, Auto">
    
            </Grid>
        </VerticalStackLayout>
    </ContentPage>
    
  6. 向子 Grid 的第一列添加一个 Button。 这是“保存”按钮

    <ContentPage ...>
        <VerticalStackLayout ...>
            <Label .../>
    
            <Editor .../>
    
            <Grid ...>                    
                <Button Grid.Column="0"
                        Text="Save" 
                        WidthRequest="100"
                        Clicked="OnSaveButtonClicked" />
            </Grid>
        </VerticalStackLayout>
    </ContentPage>
    
  7. 向子 Grid 的第三列再添加一个 Button。 这是“删除”按钮

    <ContentPage ...>
        <VerticalStackLayout ...>
            <Label .../>
    
            <Editor .../>
    
            <Grid ...>                    
                <Button ... />
    
                <Button Grid.Column="2"
                        Text="Delete" 
                         WidthRequest="100"
                        Clicked="OnDeleteButtonClicked" />
            </Grid>
        </VerticalStackLayout>
    </ContentPage>
    

从代码隐藏文件中删除布局代码

  1. 在“解决方案资源管理器”窗口中展开 MainPage.xaml 节点并打开 MainPage.xaml.cs 文件

  2. 从 MainPage 类中删除 Editor 字段

  3. 在 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);
            }
        }
    
        ...
    }
    
  4. 在“生成”菜单中,选择“重新生成解决方案”。 验证应用生成时是否未出现任何错误。

  5. 运行该应用程序。 它应像以前一样运作。

  6. 如果有时间,请使用 Android 仿真器部署和运行应用。 应用 UI 应类似于本练习开始时的图像中的内容。