연습: 첫 번째 XAML 페이지 만들기

완료됨

다니고 있는 전력 유틸리티 회사의 엔지니어가 정기적으로 고객을 방문하여 가전제품을 수리하고 다른 전기 유지관리 작업을 수행합니다. 앱의 일부에서 엔지니어가 방문에 대한 메모를 작성하도록 지원합니다. 앱은 엔지니어가 세부 정보를 입력하고 저장할 수 있는 간단한 편집기를 표시합니다.

Android 앱은 다음과 같습니다.

The engineer's app running on Android, showing the editor page.

이 페이지에 몇 가지 추가 기능을 추가해달라는 요청을 받았습니다. 시작하기 전에 페이지가 만들어진 방식을 이해하여 소스 코드를 살펴보려고 합니다. 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.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는 3개의 열이 포함된 Label, EditorGrid가 포함된 VerticalStackLayout으로 구성됩니다. 첫 번째 열에는 saveButton 컨트롤이 있고, 두 번째 열은 스페이서이고, 세 번째 열에는 deleteButton 컨트롤이 있습니다.

    다음 다이어그램에서는 UI 구조를 보여 줍니다.

    A diagram of the UI structure for the Notes app.

    MainPage 클래스에는 단추에 대한 이벤트 처리 메서드와 Editor 컨트롤을 초기화하는 일부 코드도 포함되어 있습니다. 이 코드는 UI 정의와 구별되지 않습니다.

  6. 모양이 어떤지 확인하기 위해 Windows 앱을 빌드하고 실행합니다. F5를 선택하여 앱을 빌드하고 실행합니다.

  7. 완료되면 앱을 닫고 Visual Studio 또는 Visual Studio Code로 돌아갑니다.

UI의 XAML 버전 만들기

  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. VerticalStackLayoutLabel 컨트롤을 추가합니다. 아래와 같이 이 컨트롤의 Text, HorizontalTextAlignmentFontAttributes 속성을 설정합니다.

    <ContentPage ...>
        <VerticalStackLayout ...>
            <Label Text="Notes"
                   HorizontalOptions="Center"
                   FontAttributes="Bold" />
        </VerticalStackLayout>
    </ContentPage>
    
  4. VerticalStackLayoutEditor 컨트롤을 추가합니다.

    <ContentPage ...>
        <VerticalStackLayout ...>
            <Label .../>
    
            <Editor x:Name="editor"
                    Placeholder="Enter your note"
                    HeightRequest="100" />
        </VerticalStackLayout>
    </ContentPage>
    
  5. 자녀 GridVerticalStackLayout에 추가합니다. 이 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 클래스에서 편집기 필드를 제거합니다.

  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는 이 연습의 시작 부분에 있는 이미지에 표시된 것과 유사해야 합니다.