Compartilhar via


Criar um aplicativo .NET MAUI

Este tutorial foi projetado para demonstrar como criar um aplicativo de interface do usuário do aplicativo .NET multiplataforma (.NET MAUI) que usa apenas código multiplataforma. Ou seja, o código que você escreve não será específico para Windows, Android, iOS ou macOS. O aplicativo que você criará será um aplicativo de anotação, no qual o usuário pode criar, salvar e carregar várias anotações.

Neste tutorial, você aprenderá como:

  • Crie um aplicativo .NET MAUI Shell.
  • Execute seu aplicativo na plataforma escolhida.
  • Defina a interface do usuário com xAML (linguagem de marcação de aplicativo eXtensible) e interaja com elementos XAML por meio do código.
  • Crie exibições e associe-as aos dados.
  • Use a navegação para mover de e para páginas.

Você usará o Visual Studio 2022 para criar um aplicativo com o qual você pode inserir uma nota e salvá-la no armazenamento do dispositivo. O aplicativo final é mostrado aqui:

Captura de tela final do aplicativo de anotações, listando as anotações. Captura de tela final do aplicativo de anotações, adicionando uma anotação.

Criar um projeto

Antes de começar este tutorial, você deve seguir Criar seu primeiro artigo de aplicativo. Ao criar o projeto, use as seguintes configurações:

  • Nome do Projeto

    Isso deve ser definido como Notes. Se o projeto tiver o nome de algo diferente, o código que você copiar e colar deste tutorial poderá resultar em erros de build.

  • Coloque a solução e o projeto no mesmo diretório

    Desmarque essa configuração.

Defina o nome do projeto MAUI do .NET como Anotações no Visual Studio.

Escolha a versão mais recente do .NET ao criar seu projeto.

Selecionar o dispositivo de destino

Os aplicativos .NET MAUI são projetados para serem executados em vários sistemas operacionais e dispositivos. Você precisará selecionar qual destino deseja testar e depurar seu aplicativo.

Defina o Destino de Depuração na barra de ferramentas do Visual Studio para o dispositivo com o qual você deseja depurar e testar. As etapas a seguir demonstram como definir o Destino de Depuração para Android:

Selecionando o destino de depuração do Android para um aplicativo MAUI do .NET no Visual Studio.

  1. Selecione o botão suspenso Destino de Depuração.
  2. Selecione o item Android Emulators.
  3. Selecione o dispositivo emulador.

Personalizar o shell do aplicativo

Quando o Visual Studio cria um projeto MAUI do .NET, quatro arquivos de código importantes são gerados. Elas podem ser vistas no painel Gerenciador de Soluções do Visual Studio:

Gerenciador de Soluções mostrando os arquivos de um projeto MAUI do .NET no Visual Studio.

Esses arquivos ajudam a configurar e executar o aplicativo MAUI do .NET. Cada arquivo serve a uma finalidade diferente, descrita abaixo:

  • MauiProgram.cs

    Este é um arquivo de código que inicializa seu aplicativo. O código nesse arquivo serve como o ponto de entrada entre plataformas do aplicativo, que configura e inicia o aplicativo. O código de inicialização do modelo aponta para a classe App definida pelo arquivo App.xaml.

  • App.xaml e App.xaml.cs

    Apenas para manter as coisas simples, ambos os arquivos são conhecidos como um único arquivo. Geralmente, há dois arquivos com qualquer arquivo XAML, o arquivo .xaml em si e um arquivo de código correspondente que é um item filho dele no Gerenciador de Soluções. O arquivo .xaml contém marcação XAML e o arquivo de código contém o código criado pelo usuário para interagir com a marcação XAML.

    O arquivo App.xaml contém recursos XAML em todo o aplicativo, como cores, estilos ou modelos. O arquivo App.xaml.cs geralmente contém código que cria uma instância do aplicativo Shell. Neste projeto, ele aponta para a classe AppShell.

  • AppShell.xaml e AppShell.xaml.cs

    Esse arquivo define a classe AppShell, que é usada para definir a hierarquia visual do aplicativo.

  • MainPage.xaml e MainPage.xaml.cs

    Esta é a página de inicialização exibida pelo aplicativo. O arquivo MainPage.xaml define a interface do usuário (interface do usuário) da página. MainPage.xaml.cs contém o code-behind para o XAML, como código para um evento de clique de botão.

Adicionar uma página "sobre"

A primeira personalização que você fará é adicionar outra página ao projeto. Esta página é uma página "sobre", que representa informações sobre esse aplicativo, como o autor, a versão e talvez um link para obter mais informações.

  1. No painel Gerenciador de Soluções do Visual Studio, clique com o botão direito do mouse no projeto >Adicionar>Novo Item.

    Clique com o botão direito do mouse em um projeto no Visual Studio e selecione Novo Item.

  2. Na caixa de diálogo Adicionar Novo Item, selecione .NET MAUI na lista de modelos no lado esquerdo da janela. Em seguida, selecione o modelo do .NET MAUI ContentPage (XAML). Nomeie o arquivo AboutPage.xaml e selecione Adicionar.

    Adicionando um novo ContentPage ao projeto. O ContentPage se chama AboutPage.xaml.

  3. O arquivo AboutPage.xaml abrirá uma nova guia de documento, exibindo toda a marcação XAML que representa a interface do usuário da página. Substitua a marcação XAML pela marcação a seguir:

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="Notes.AboutPage">
        <VerticalStackLayout Spacing="10" Margin="10">
            <HorizontalStackLayout Spacing="10">
                <Image Source="dotnet_bot.png"
                       SemanticProperties.Description="The dot net bot waving hello!"
                       HeightRequest="64" />
                <Label FontSize="22" FontAttributes="Bold" Text="Notes" VerticalOptions="End" />
                <Label FontSize="22" Text="v1.0" VerticalOptions="End" />
            </HorizontalStackLayout>
    
            <Label Text="This app is written in XAML and C# with .NET MAUI." />
            <Button Text="Learn more..." Clicked="LearnMore_Clicked" />
        </VerticalStackLayout>
    </ContentPage>
    
  4. Salve o arquivo pressionando CTRL+S ou selecionando o menu Arquivo>Salvar AboutPage.xaml.

Vamos especificar as partes principais dos controles XAML colocados na página:

  • <ContentPage> é o objeto raiz da classe AboutPage.

  • <VerticalStackLayout> é o único objeto filho do ContentPage. ContentPage só pode ter um objeto filho. O tipo VerticalStackLayout pode ter vários filhos. Este controle de layout organiza seus elementos filhos verticalmente, um após o outro.

  • <HorizontalStackLayout> opera da mesma forma que um <VerticalStackLayout>, exceto que seus filhos são organizados horizontalmente.

  • <Image> exibe uma imagem, nesse caso, ela está usando a imagem dotnet_bot.png que vem com todos os projetos do .NET MAUI.

    Importante

    O arquivo adicionado ao projeto é, na verdade, dotnet_bot.svg. O .NET MAUI converte arquivos SVG (Gráficos vetoriais escalonáveis) em arquivos PNG (Portable Network Graphic) com base no dispositivo de destino. Portanto, ao adicionar um arquivo SVG ao seu projeto de aplicativo .NET MAUI, ele deve ser referenciado de XAML ou C# com uma extensão .png . A única referência ao arquivo SVG deve estar no arquivo de projeto.

  • <Label> controla o texto de exibição.

  • <Button> controles podem ser pressionados pelo usuário, o que gera o evento Clicked. Você pode executar o código em resposta ao evento Clicked.

  • Clicked="LearnMore_Clicked"

    O evento Clicked do botão é atribuído ao manipulador de eventos LearnMore_Clicked, que será definido no arquivo code-behind. Você criará esse código na próxima etapa.

Manipular o evento Clicked

O próximo passo é adicionar o código do evento Clicked do botão.

  1. No painel Solution Explorer do Visual Studio, expanda o arquivo AboutPage.xaml para revelar seu arquivo code-behind AboutPage.xaml.cs. Em seguida, clique duas vezes no arquivo AboutPage.xaml.cs para abri-lo no editor de código.

    Uma imagem da janela do Gerenciador de Soluções no Visual Studio, com uma caixa vermelha realçando o ícone expandir.

  2. Adicione o seguinte código de manipulador de eventos LearnMore_Clicked, que abre o navegador do sistema em um URL específico:

    private async void LearnMore_Clicked(object sender, EventArgs e)
    {
        // Navigate to the specified URL in the system browser.
        await Launcher.Default.OpenAsync("https://aka.ms/maui");
    }
    

    Observe que a palavra-chave async foi adicionada à declaração do método, que permite o uso da palavra-chave await ao abrir o navegador do sistema.

  3. Salve o arquivo pressionando CTRL+S ou selecionando o menu Arquivo>Salvar AboutPage.xaml.cs.

Agora que o XAML e o code-behind do AboutPage estão concluídos, você precisará exibi-lo no aplicativo.

Adicionar recursos de imagem

Alguns controles podem usar imagens, o que aprimora a forma como os usuários interagem com seu aplicativo. Nesta seção, você baixará duas imagens que usará em seu aplicativo, juntamente com duas imagens alternativas para uso com o iOS.

Baixe as seguintes imagens:

Depois de baixar as imagens, você pode movê-las com o Explorador de Arquivos para a pasta Recursos\Imagens do projeto. Qualquer arquivo nessa pasta é incluído automaticamente no projeto como um recurso MauiImage. Você também pode usar o Visual Studio para adicionar as imagens ao seu projeto. Se você mover as imagens manualmente, ignore o procedimento a seguir.

Importante

Não ignore o download das imagens específicas do iOS, elas são necessárias para concluir este tutorial.

Mover as imagens com o Visual Studio

  1. No painel Gerenciador de Soluções do Visual Studio, expanda a pasta Recursos, que revela a pasta Imagens.

    Dica

    Você pode usar o Explorador de Arquivos para arrastar e soltar as imagens diretamente no painel Gerenciador de Soluções, na parte superior da pasta Imagens. Isso move automaticamente os arquivos para a pasta e os inclui no projeto. Se você optar por arrastar e soltar os arquivos, ignore o restante deste procedimento.

  2. Clique com o botão direito do mouse em imagens e selecione Adicionar>Item Existente.

  3. Navegue até a pasta que contém as imagens baixadas.

  4. Altere o filtro para tipo de arquivo para os Arquivos de Imagem.

  5. Mantenha pressionada a tecla CTRL e clique em cada uma das imagens que você baixou e pressione Adicionar

Adicione quatro imagens de ícone ao projeto MAUI do .NET.

Modificar o shell do aplicativo

Conforme observado no início deste artigo, a classe define a AppShell hierarquia visual de um aplicativo, a marcação XAML usada na criação da interface do usuário do aplicativo. Atualize o XAML para adicionar um controle TabBar:

  1. Clique duas vezes no arquivo AppShell.xaml no painel Gerenciador de Soluções para abrir o editor XAML. Substitua a marcação XAML pelo código a seguir:

    <?xml version="1.0" encoding="UTF-8" ?>
    <Shell
        x:Class="Notes.AppShell"
        xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:local="clr-namespace:Notes"
        Shell.FlyoutBehavior="Disabled">
    
        <TabBar>
            <ShellContent
                Title="Notes"
                ContentTemplate="{DataTemplate local:MainPage}"
                Icon="{OnPlatform 'icon_notes.png', iOS='icon_notes_ios.png', MacCatalyst='icon_notes_ios.png'}" />
    
            <ShellContent
                Title="About"
                ContentTemplate="{DataTemplate local:AboutPage}"
                Icon="{OnPlatform 'icon_about.png', iOS='icon_about_ios.png', MacCatalyst='icon_about_ios.png'}" />
        </TabBar>
    
    </Shell>
    
  2. Salve o arquivo pressionando CTRL+S ou selecionando o menu Arquivo>Salvar AppShell.xaml.

Vamos dividir as partes principais do XAML:

  • <Shell> é o objeto raiz da marcação XAML.
  • <TabBar> é o conteúdo do Shell.
  • Dois objetos <ShellContent> dentro do <TabBar>. Antes de substituir o código do modelo, havia um único objeto <ShellContent>, apontando para a página MainPage.

O TabBar e seus filhos não representam elementos de interface do usuário, mas sim a organização da hierarquia visual do aplicativo. O Shell usa esses objetos e produz a interface do usuário para o conteúdo, com uma barra na parte superior representando cada página. A propriedade ShellContent.Icon para cada página usa a extensão de marcação OnPlatform. Essa extensão de marcação XAML é usada para especificar valores diferentes para plataformas diferentes. Neste exemplo, cada plataforma usa o ícone icon_about.png por padrão, mas o iOS e o MacCatalyst usam icon_about_ios.png.

Cada objeto <ShellContent> está apontando para uma página a ser exibida. Isso é definido pela propriedade ContentTemplate.

Executar o aplicativo

Execute o aplicativo pressionando F5 ou pressionando o botão reproduzir na parte superior do Visual Studio:

Botão Depurar Destino do Visual Studio com o texto Windows Machine.

Você verá que há duas guias: Anotações e sobre. Pressione a guia Sobre e o aplicativo navega até o AboutPage que você criou. Pressione o botão Saiba mais para abrir o navegador da Web.

Sobre a página do tutorial do aplicativo .NET MAUI.

Feche o aplicativo e retorne ao Visual Studio. Se você estiver usando o emulador do Android, encerre o aplicativo no dispositivo virtual ou pressione o botão parar na parte superior do Visual Studio:

Botão parar de depuração do Visual Studio.

Criar uma página para uma anotação

Agora que o aplicativo contém o MainPage e AboutPage, você pode começar a criar o restante do aplicativo. Primeiro, você criará uma página que permite que um usuário crie e exiba a anotação e, em seguida, você escreverá o código para carregar e salvar a nota.

A página de anotação exibirá a nota e permitirá que você a salve ou exclua. Primeiro, adicione a nova página ao projeto:

  1. No painel Gerenciador de Soluções do Visual Studio, clique com o botão direito do mouse no projeto >Adicionar>Novo Item.

  2. Na caixa de diálogo Adicionar Novo Item, selecione .NET MAUI na lista de modelos no lado esquerdo da janela. Em seguida, selecione o modelo do .NET MAUI ContentPage (XAML). Nomeie o arquivo NotePage.xaml e selecione Adicionar.

  3. O arquivo NotePage.xaml será aberto em uma nova guia, exibindo toda a marcação XAML que representa a interface do usuário da página. Substitua a marcação de código XAML na seguinte marcação:

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="Notes.NotePage"
                 Title="Note">
        <VerticalStackLayout Spacing="10" Margin="5">
            <Editor x:Name="TextEditor"
                    Placeholder="Enter your note"
                    HeightRequest="100" />
    
            <Grid ColumnDefinitions="*,*" ColumnSpacing="4">
                <Button Text="Save"
                        Clicked="SaveButton_Clicked" />
    
                <Button Grid.Column="1"
                        Text="Delete"
                        Clicked="DeleteButton_Clicked" />
            </Grid>
        </VerticalStackLayout>
    </ContentPage>
    
  4. Salve o arquivo pressionando CTRL + S ou selecionando o menu Salvar>Salvar NotePage.xaml.

Vamos especificar as partes principais dos controles XAML colocados na página:

  • <VerticalStackLayout> organiza seus controles filhos verticalmente, um abaixo do outro.

  • <Editor> é um controle de editor de texto de várias linhas e é o primeiro controle dentro de VerticalStackLayout.

  • <Grid> é um controle de layout e é o segundo controle dentro de VerticalStackLayout.

    Esse controle define colunas e linhas para criar células. Os controles filho são colocados dentro dessas células.

    Por padrão, o controle Grid contém uma única linha e coluna, criando uma única célula. As colunas são definidas com uma largura e o valor * para largura informa à coluna para preencher o máximo de espaço possível. O snippet de código anterior definiu duas colunas, ambas usando o máximo de espaço possível, que distribui uniformemente as colunas no espaço alocado: ColumnDefinitions="*,*". Os tamanhos de coluna são separados por um caractere ,.

    Colunas e linhas definidas por um Grid são indexadas a partir de 0. Portanto, a primeira coluna seria o índice 0, a segunda coluna é o índice 1 e assim por diante.

  • Dois controles <Button> estão dentro do <Grid> e atribuídos a uma coluna. Se um controle filho não definir uma atribuição de coluna, ele será atribuído automaticamente à primeira coluna. Nesta marcação, o primeiro botão é o botão "Salvar" e atribuído automaticamente à primeira coluna, coluna 0. O segundo botão é o botão "Excluir" e atribuído à segunda coluna, coluna 1.

    Observe que os dois botões têm o evento Clicked manipulado. Você adicionará o código para esses manipuladores na próxima seção.

Carregar e salvar uma anotação

Abra o arquivo NotePage.xaml.cs code-behind. Você pode abrir o code-behind para o arquivo NotePage.xaml de três maneiras:

  • Se o NotePage.xaml estiver aberto e for o documento ativo que está sendo editado, pressione F7.
  • Se o NotePage.xaml estiver aberto e for o documento ativo que está sendo editado, clique com o botão direito do mouse no editor de texto e selecione Exibir Código.
  • Use o Gerenciador de Soluções para expandir a entrada NotePage.xaml, revelando o arquivo NotePage.xaml.cs. Faça duplo clique no ficheiro para o abrir.

Quando você adiciona um novo arquivo XAML, o code-behind contém uma única linha no construtor, uma chamada ao método InitializeComponent:

namespace Notes;

public partial class NotePage : ContentPage
{
    public NotePage()
    {
        InitializeComponent();
    }
}

O método InitializeComponent lê a marcação XAML e inicializa todos os objetos definidos pela marcação. Os objetos são conectados em suas relações pai-filho e os manipuladores de eventos definidos no código são anexados a eventos definidos no XAML.

Agora que você entende um pouco mais sobre arquivos code-behind, você adicionará código ao arquivo NotePage.xaml.cs code-behind para lidar com o carregamento e salvamento de anotações.

  1. Quando uma anotação é criada, ela é salva no dispositivo como um arquivo de texto. O nome do arquivo é representado pela variável _fileName. Adicione a seguinte declaração de variável string à classe NotePage:

    public partial class NotePage : ContentPage
    {
        string _fileName = Path.Combine(FileSystem.AppDataDirectory, "notes.txt");
    

    O código acima constrói um caminho para o arquivo, armazenando-o no diretório de dados local do aplicativo. O nome do arquivo é notes.txt.

  2. No construtor da classe, depois que o método InitializeComponent for chamado, leia o arquivo do dispositivo e armazene seu conteúdo na propriedade TextEditor do controle Text:

    public NotePage()
    {
        InitializeComponent();
    
        if (File.Exists(_fileName))
            TextEditor.Text = File.ReadAllText(_fileName);
    }
    
  3. Em seguida, adicione o código para lidar com os eventos de Clicked definidos no XAML:

    private void SaveButton_Clicked(object sender, EventArgs e)
    {
        // Save the file.
        File.WriteAllText(_fileName, TextEditor.Text);
    }
    
    private void DeleteButton_Clicked(object sender, EventArgs e)
    {
        // Delete the file.
        if (File.Exists(_fileName))
            File.Delete(_fileName);
    
        TextEditor.Text = string.Empty;
    }
    

    O método SaveButton_Clicked grava o texto no controle Editor, no arquivo representado pela variável _fileName.

    O método DeleteButton_Clicked primeiro verifica se o arquivo representado pela variável _fileName e, se existir, o exclui. Em seguida, o texto do controle Editor é limpo.

  4. Salve o arquivo pressionando CTRL + S ou selecionando o menu Salvar>Salvar NotePage.xaml.cs.

O código final do arquivo code-behind deve ser semelhante ao seguinte:

namespace Notes;

public partial class NotePage : ContentPage
{
    string _fileName = Path.Combine(FileSystem.AppDataDirectory, "notes.txt");

    public NotePage()
    {
        InitializeComponent();

        if (File.Exists(_fileName))
            TextEditor.Text = File.ReadAllText(_fileName);
    }

    private void SaveButton_Clicked(object sender, EventArgs e)
    {
        // Save the file.
        File.WriteAllText(_fileName, TextEditor.Text);
    }

    private void DeleteButton_Clicked(object sender, EventArgs e)
    {
        // Delete the file.
        if (File.Exists(_fileName))
            File.Delete(_fileName);

        TextEditor.Text = string.Empty;
    }
}

Testar a anotação

Agora que página de notas está concluída, você precisa de uma maneira de apresentá-la ao usuário. Abra o arquivo AppShell.xaml e altere a primeira entrada ShellContent para apontar para o NotePage em vez de MainPage:

<?xml version="1.0" encoding="UTF-8" ?>
<Shell
    x:Class="Notes.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:Notes"
    Shell.FlyoutBehavior="Disabled">

    <TabBar>
        <ShellContent
            Title="Notes"
            ContentTemplate="{DataTemplate local:NotePage}"
            Icon="{OnPlatform 'icon_notes.png', iOS='icon_notes_ios.png', MacCatalyst='icon_notes_ios.png'}" />

        <ShellContent
            Title="About"
            ContentTemplate="{DataTemplate local:AboutPage}"
            Icon="{OnPlatform 'icon_about.png', iOS='icon_about_ios.png', MacCatalyst='icon_about_ios.png'}" />
    </TabBar>

</Shell>

Salve o arquivo e execute o aplicativo. Tente digitar na caixa de entrada e pressione o botão Salvar. Feche o aplicativo e reabra-o. A anotação inserida deve ser carregada do armazenamento do dispositivo.

Observe a página de entrada no aplicativo MAUI do .NET.

Associar dados à interface do usuário e navegar em páginas

Esta parte do tutorial apresenta os conceitos de exibições, modelos e navegação no aplicativo.

Nas etapas anteriores do tutorial, você adicionou duas páginas ao projeto: NotePage e AboutPage. As páginas representam uma exibição de dados. O NotePage é uma "exibição" que exibe "dados de anotação" e o AboutPage é uma "exibição" que exibe "dados de informações do aplicativo". Ambas as exibições têm um modelo desses dados codificados ou inseridos neles, e você precisará separar o modelo de dados da exibição.

Qual é o benefício de separar o modelo da exibição? Ele permite que você projete a exibição para representar e interagir com qualquer parte do modelo sem se preocupar com o código real que implementa o modelo. Isso é feito usando a associação de dados, algo que será apresentado posteriormente neste tutorial. Por enquanto, porém, vamos reestruturar o projeto.

Separar a exibição e o modelo

Refatore o código existente para separar o modelo da exibição. As próximas etapas organizarão o código para que os modos de exibição e os modelos sejam definidos separadamente entre si.

  1. Exclua MainPage.xaml e MainPage.xaml.cs do seu projeto, eles não são mais necessários. No painel Gerenciador de Soluções, localize a entrada para MainPage.xaml, clique com o botão direito do mouse e selecione Excluir.

    Dica

    Excluir o item MainPage.xaml também deve excluir o item MainPage.xaml.cs. Se MainPage.xaml.cs não tiver sido excluído, clique com o botão direito do mouse nele e selecione Excluir.

  2. Clique com o botão direito do mouse no projeto Notes e selecione Adicionar>Nova Pasta. Nomeie a pasta Models.

  3. Clique com o botão direito do mouse no projeto Notes e selecione Adicionar>Nova Pasta. Nomeie a pasta Views.

  4. Localize o item NotePage.xaml e arraste-o para a pasta Views. O NotePage.xaml.cs deve se mover com ele.

    Importante

    Quando você move um arquivo, o Visual Studio geralmente solicita um aviso sobre como a operação de movimentação pode levar muito tempo. Isso não deve ser um problema aqui, pressione OK se você vir este aviso.

    O Visual Studio também pode perguntar se você deseja ajustar o namespace do arquivo movido. Selecione Não, pois as próximas etapas alterarão o namespace.

  5. Localize o item AboutPage.xaml e arraste-o para a pasta Views. O AboutPage.xaml.cs deve se mover com ele.

Atualizar o namespace de exibição

Agora que as exibições foram movidas para a pasta Views, você precisará atualizar os namespaces para corresponder. O namespace para os arquivos XAML e code-behind das páginas é definido como Notes. Isso precisa ser atualizado para Notes.Views.

  1. No painel Gerenciador de Soluções, expanda NotePage.xaml e AboutPage.xaml para revelar os arquivos code-behind:

    O projeto Anotações com a pasta Exibições e as exibições de página expandidas.

  2. Clique duas vezes no item NotePage.xaml.cs para abrir o editor de código. Altere o namespace para Notes.Views:

    namespace Notes.Views;
    
  3. Repita as etapas anteriores do item AboutPage.xaml.cs.

  4. Clique duas vezes no item NotePage.xaml para abrir o editor XAML. O namespace antigo é referenciado por meio do atributo x:Class, que define qual tipo de classe é o code-behind do XAML. Essa entrada não é apenas o namespace, mas o namespace com o tipo. Altere o valor x:Class para Notes.Views.NotePage:

    x:Class="Notes.Views.NotePage"
    
  5. Repita a etapa anterior do item AboutPage.xaml, mas defina o valor x:Class como Notes.Views.AboutPage.

Corrigir a referência de namespace no Shell

O AppShell.xaml define duas guias, uma para o NotesPage e outra para AboutPage. Agora que essas duas páginas foram movidas para um novo namespace, o mapeamento de tipo no XAML agora é inválido. No painel Gerenciador de Soluções, clique duas vezes na entrada AppShell.xaml para abri-la no editor XAML. Ele deve se parecer com o seguinte snippet:

<?xml version="1.0" encoding="UTF-8" ?>
<Shell
    x:Class="Notes.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:Notes"
    Shell.FlyoutBehavior="Disabled">

    <TabBar>
        <ShellContent
            Title="Notes"
            ContentTemplate="{DataTemplate local:NotePage}"
            Icon="{OnPlatform 'icon_notes.png', iOS='icon_notes_ios.png', MacCatalyst='icon_notes_ios.png'}" />

        <ShellContent
            Title="About"
            ContentTemplate="{DataTemplate local:AboutPage}"
            Icon="{OnPlatform 'icon_about.png', iOS='icon_about_ios.png', MacCatalyst='icon_about_ios.png'}" />
    </TabBar>

</Shell>

Um namespace .NET é importado para o XAML por meio de uma declaração de namespace XML. Na marcação XAML anterior, é o atributo xmlns:local="clr-namespace:Notes" no elemento raiz: <Shell>. O formato de declarar um namespace XML para importar um namespace do .NET no mesmo assembly é:

xmlns:{XML namespace name}="clr-namespace:{.NET namespace}"

Portanto, a declaração anterior mapeia o namespace XML de local para o namespace .NET de Notes. É uma prática comum mapear o nome local para o namespace raiz do projeto.

Remova o namespace local XML e adicione um novo. Esse novo namespace XML será mapeado para o namespace do .NET de Notes.Views; portanto, nomeie-o views. A declaração deve ser semelhante ao seguinte atributo: xmlns:views="clr-namespace:Notes.Views".

O namespace XML local foi usado pelas propriedades ShellContent.ContentTemplate, altere-os para views. Seu XAML agora deve se parecer com o seguinte snippet:

<?xml version="1.0" encoding="UTF-8" ?>
<Shell
    x:Class="Notes.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:views="clr-namespace:Notes.Views"
    Shell.FlyoutBehavior="Disabled">

    <TabBar>
        <ShellContent
            Title="Notes"
            ContentTemplate="{DataTemplate views:NotePage}"
            Icon="{OnPlatform 'icon_notes.png', iOS='icon_notes_ios.png', MacCatalyst='icon_notes_ios.png'}" />

        <ShellContent
            Title="About"
            ContentTemplate="{DataTemplate views:AboutPage}"
            Icon="{OnPlatform 'icon_about.png', iOS='icon_about_ios.png', MacCatalyst='icon_about_ios.png'}" />
    </TabBar>

</Shell>

Agora você deve ser capaz de executar o aplicativo sem erros do compilador e tudo ainda deve funcionar como antes.

Definir o modelo

Atualmente, o modelo são os dados inseridos na anotação e sobre exibições. Criaremos novas classes para representar esses dados. Primeiro, o modelo para representar os dados de uma página de anotação:

  1. No painel Gerenciador de Soluções , clique com o botão direito do Models mouse na pasta e selecione Adicionar>Classe.

  2. Nomeie a classe Note.cs e pressione Adicionar.

  3. Abra Note.cs e substitua o código pelo seguinte snippet:

    namespace Notes.Models;
    
    internal class Note
    {
        public string Filename { get; set; }
        public string Text { get; set; }
        public DateTime Date { get; set; }
    }
    
  4. Salve o arquivo.

Em seguida, crie o modelo da página sobre:

  1. No painel Gerenciador de Soluções , clique com o botão direito do Models mouse na pasta e selecione Adicionar>Classe.

  2. Nomeie a classe About.cs e pressione Adicionar.

  3. Abra About.cs e substitua o código pelo seguinte snippet:

    namespace Notes.Models;
    
    internal class About
    {
        public string Title => AppInfo.Name;
        public string Version => AppInfo.VersionString;
        public string MoreInfoUrl => "https://aka.ms/maui";
        public string Message => "This app is written in XAML and C# with .NET MAUI.";
    }
    
  4. Salve o arquivo.

Página Atualizar Sobre

A página sobre será a página mais rápida a ser atualizada e você poderá executar o aplicativo e ver como ele carrega dados do modelo.

  1. No painel Gerenciador de Soluções, abra o arquivo Views\AboutPage.xaml.

  2. Substitua o conteúdo pelo seguinte snippet:

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:models="clr-namespace:Notes.Models"
                 x:Class="Notes.Views.AboutPage"
                 x:DataType="models:About">
        <ContentPage.BindingContext>
            <models:About />
        </ContentPage.BindingContext>
        <VerticalStackLayout Spacing="10" Margin="10">
            <HorizontalStackLayout Spacing="10">
                <Image Source="dotnet_bot.png"
                       SemanticProperties.Description="The dot net bot waving hello!"
                       HeightRequest="64" />
                <Label FontSize="22" FontAttributes="Bold" Text="{Binding Title}" VerticalOptions="End" />
                <Label FontSize="22" Text="{Binding Version}" VerticalOptions="End" />
            </HorizontalStackLayout>
    
            <Label Text="{Binding Message}" />
            <Button Text="Learn more..." Clicked="LearnMore_Clicked" />
        </VerticalStackLayout>
    
    </ContentPage>
    

Vamos examinar as linhas alteradas, que são realçadas no snippet anterior:

  • xmlns:models="clr-namespace:Notes.Models"

    Essa linha mapeia o namespace do .NET Notes.Models para o namespace XML models.

  • x:DataType="models:About"

    Essa linha instrui o compilador XAML a compilar todas as expressões de associação para aumentar o desempenho do runtime e resolve as expressões de associação em relação ao Notes.Models.About tipo.

  • A propriedade BindingContext do ContentPage é definida como uma instância da classe Note.Models.About, usando o namespace XML e o objeto de models:About. Isso foi definido usando sintaxe de elemento de propriedade em vez de um atributo XML.

    Importante

    Até agora, as propriedades foram definidas usando um atributo XML. Isso funciona bem para valores simples, como uma propriedade Label.FontSize. Mas se o valor da propriedade for mais complexo, você deverá usar sintaxe do elemento de propriedade para criar o objeto. Considere o seguinte exemplo de criação de um rótulo com seu conjunto de propriedades FontSize:

    <Label FontSize="22" />
    

    A mesma propriedade FontSize pode ser definida usando sintaxe do elemento de propriedade:

    <Label>
        <Label.FontSize>
            22
        </Label.FontSize>
    </Label>
    
  • Três controles <Label> tiveram seu valor de propriedade Text alterado de uma cadeia de caracteres codificada para uma sintaxe de associação: {Binding PATH}.

    A sintaxe {Binding} é processada em tempo de execução, permitindo que o valor retornado da associação seja dinâmico. A parte PATH de {Binding PATH} é o caminho de propriedade ao qual associar. A propriedade vem do controle atual BindingContext. Com o controle <Label>, BindingContext não está definido. O contexto é herdado do pai quando não é definido pelo controle, o que, nesse caso, o contexto de configuração do objeto pai é o objeto raiz: ContentPage.

    O objeto no BindingContext é uma instância do modelo About. O caminho de associação de um dos rótulos associa a propriedade Label.Text à propriedade About.Title.

A última alteração na página sobre é atualizar o clique do botão que abre uma página da Web. A URL foi codificada no code-behind, mas a URL deve vir do modelo que está na propriedade BindingContext.

  1. No painel Gerenciador de Soluções, abra o arquivo Views\AboutPage.xaml.cs.

  2. Substitua o método LearnMore_Clicked pelo seguinte código:

    private async void LearnMore_Clicked(object sender, EventArgs e)
    {
        if (BindingContext is Models.About about)
        {
            // Navigate to the specified URL in the system browser.
            await Launcher.Default.OpenAsync(about.MoreInfoUrl);
        }
    }
    

Se você observar a linha realçada, o código verificará se o BindingContext é um Models.About tipo e, se for, o atribuirá à about variável. A próxima linha dentro da instrução if abre o navegador para a URL fornecida pela propriedade about.MoreInfoUrl.

Execute o aplicativo e você verá que ele é executado exatamente da mesma forma que antes. Tente alterar os valores do modelo e veja como a interface do usuário e a URL abertas pelo navegador também são alteradas.

Página Atualizar Observação

A seção anterior vinculou o modo de exibição de página about ao modelo de about e agora você fará o mesmo, associando o modo de exibição note ao modelo note. No entanto, nesse caso, o modelo não será criado no XAML, mas será fornecido no code-behind nas próximas etapas.

  1. No painel Gerenciador de Soluções, abra o arquivo Views\NotePage.xaml.

  2. Substitua o conteúdo pelo seguinte snippet:

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:models="clr-namespace:Notes.Models"
                 x:Class="Notes.Views.NotePage"
                 Title="Note"
                 x:DataType="models:Note">
        <VerticalStackLayout Spacing="10" Margin="5">
            <Editor x:Name="TextEditor"
                    Placeholder="Enter your note"
                    Text="{Binding Text}"
                    HeightRequest="100" />
    
            <Grid ColumnDefinitions="*,*" ColumnSpacing="4">
                <Button Text="Save"
                        Clicked="SaveButton_Clicked" />
    
                <Button Grid.Column="1"
                        Text="Delete"
                        Clicked="DeleteButton_Clicked" />
            </Grid>
        </VerticalStackLayout>
    </ContentPage>
    

Vamos examinar as linhas alteradas, que são realçadas no snippet anterior:

  • xmlns:models="clr-namespace:Notes.Models"

    Essa linha mapeia o namespace do .NET Notes.Models para o namespace XML models.

  • x:DataType="models:Note"

    Essa linha instrui o compilador XAML a compilar todas as expressões de associação para aumentar o desempenho do runtime e resolve as expressões de associação em relação ao Notes.Models.Note tipo.

  • Text="{Binding Text}"

    Essa linha altera o <Editor> controle adicionando a Text propriedade e associando a propriedade à Text propriedade.

As modificações para o code-behind são mais complicadas do que o XAML. O código atual está carregando o conteúdo do arquivo no construtor e definindo-o diretamente para a propriedade TextEditor.Text. Aqui está a aparência do código atual:

public NotePage()
{
    InitializeComponent();

    if (File.Exists(_fileName))
        TextEditor.Text = File.ReadAllText(_fileName);
}

Em vez de carregar a anotação no construtor, crie um novo método LoadNote. Esse método fará o seguinte:

  • Aceite um parâmetro de nome de arquivo.
  • Crie um novo modelo de anotação e defina o nome do arquivo.
  • Se o arquivo existir, carregue seu conteúdo no modelo.
  • Se o arquivo existir, atualize o modelo com a data em que o arquivo foi criado.
  • Defina o BindingContext da página como o modelo.
  1. No painel Gerenciador de Soluções, abra o arquivo Views\NotePage.xaml.cs.

  2. Adicione o seguinte método à classe :

    private void LoadNote(string fileName)
    {
        Models.Note noteModel = new Models.Note();
        noteModel.Filename = fileName;
    
        if (File.Exists(fileName))
        {
            noteModel.Date = File.GetCreationTime(fileName);
            noteModel.Text = File.ReadAllText(fileName);
        }
    
        BindingContext = noteModel;
    }
    
  3. Atualize o construtor de classe para chamar LoadNote. O nome do arquivo da anotação deve ser um nome gerado aleatoriamente para ser criado no diretório de dados local do aplicativo.

    public NotePage()
    {
        InitializeComponent();
    
        string appDataPath = FileSystem.AppDataDirectory;
        string randomFileName = $"{Path.GetRandomFileName()}.notes.txt";
    
        LoadNote(Path.Combine(appDataPath, randomFileName));
    }
    

Adicionar uma exibição e um modelo que lista todas as anotações

Esta parte do tutorial adiciona a parte final do aplicativo, uma exibição que exibe todas as anotações criadas anteriormente.

Várias anotações e navegação

Atualmente, o modo de exibição de anotação exibe uma única anotação. Para exibir várias anotações, crie uma nova exibição e um modelo: AllNotes.

  1. No painel Gerenciador de Soluções , clique com o botão direito do Views mouse na pasta e selecione Adicionar>Novo Item
  2. Na caixa de diálogo Adicionar Novo Item, selecione .NET MAUI na lista de modelos no lado esquerdo da janela. Em seguida, selecione o modelo do .NET MAUI ContentPage (XAML). Nomeie o arquivo AllNotesPage.xaml e selecione Adicionar.
  3. No painel Gerenciador de Soluções , clique com o botão direito do Models mouse na pasta e selecione Adicionar>Classe
  4. Nomeie a classe AllNotes.cs e pressione Adicionar.

Codificar o modelo do AllNotes

O novo modelo representará os dados necessários para exibir várias anotações. Esses dados serão uma propriedade que representa uma coleção de anotações. A coleção será uma ObservableCollection que é uma coleção especializada. Quando um controle que lista vários itens, como um ListView, é associado a um ObservableCollection, os dois trabalham juntos para manter automaticamente a lista de itens em sincronia com a coleção. Se a lista adicionar um item, a coleção será atualizada. Se a coleção adicionar um item, o controle será atualizado automaticamente com um novo item.

  1. No painel do Gerenciador de Soluções, abra o arquivo Models\AllNotes.cs.

  2. Substitua o código pelo seguinte snippet:

    using System.Collections.ObjectModel;
    
    namespace Notes.Models;
    
    internal class AllNotes
    {
        public ObservableCollection<Note> Notes { get; set; } = new ObservableCollection<Note>();
    
        public AllNotes() =>
            LoadNotes();
    
        public void LoadNotes()
        {
            Notes.Clear();
    
            // Get the folder where the notes are stored.
            string appDataPath = FileSystem.AppDataDirectory;
    
            // Use Linq extensions to load the *.notes.txt files.
            IEnumerable<Note> notes = Directory
    
                // Select the file names from the directory
                .EnumerateFiles(appDataPath, "*.notes.txt")
    
                // Each file name is used to create a new Note
                .Select(filename => new Note()
                {
                    Filename = filename,
                    Text = File.ReadAllText(filename),
                    Date = File.GetLastWriteTime(filename)
                })
    
                // With the final collection of notes, order them by date
                .OrderBy(note => note.Date);
    
            // Add each note into the ObservableCollection
            foreach (Note note in notes)
                Notes.Add(note);
        }
    }
    

O código anterior declara uma coleção, chamada Notes, e usa o método LoadNotes para carregar anotações do dispositivo. Esse método usa extensões LINQ para carregar, transformar e classificar os dados na coleção Notes.

Projetar a página AllNotes

Em seguida, o modo de exibição precisa ser projetado para dar suporte ao modelo AllNotes.

  1. No painel Gerenciador de Soluções, abra o arquivo Views\AllNotesPage.xaml.

  2. Substitua o código pela seguinte marcação:

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:models="clr-namespace:Notes.Models"
                 x:Class="Notes.Views.AllNotesPage"
                 Title="Your Notes"
                 x:DataType="models:AllNotes">
        <!-- Add an item to the toolbar -->
        <ContentPage.ToolbarItems>
            <ToolbarItem Text="Add" Clicked="Add_Clicked" IconImageSource="{FontImage Glyph='+', Color=Black, Size=22}" />
        </ContentPage.ToolbarItems>
    
        <!-- Display notes in a list -->
        <CollectionView x:Name="notesCollection"
                            ItemsSource="{Binding Notes}"
                            Margin="20"
                            SelectionMode="Single"
                            SelectionChanged="notesCollection_SelectionChanged">
    
            <!-- Designate how the collection of items are laid out -->
            <CollectionView.ItemsLayout>
                <LinearItemsLayout Orientation="Vertical" ItemSpacing="10" />
            </CollectionView.ItemsLayout>
    
            <!-- Define the appearance of each item in the list -->
            <CollectionView.ItemTemplate>
                <DataTemplate x:DataType="models:Note">
                    <StackLayout>
                        <Label Text="{Binding Text}" FontSize="22"/>
                        <Label Text="{Binding Date}" FontSize="14" TextColor="Silver"/>
                    </StackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </ContentPage>
    

O XAML anterior apresenta alguns novos conceitos:

  • A propriedade ContentPage.ToolbarItems contém um ToolbarItem. Os botões definidos aqui geralmente são exibidos na parte superior do aplicativo, ao longo do título da página. Dependendo da plataforma, porém, ela pode estar em uma posição diferente. Quando um desses botões é pressionado, o evento Clicked é acionado, assim como um botão normal.

    A propriedade ToolbarItem.IconImageSource define o ícone a ser exibido no botão. O ícone pode ser qualquer recurso de imagem definido pelo projeto, no entanto, neste exemplo, um FontImage é usado. Um FontImage pode usar um único glifo de uma fonte como uma imagem.

  • O controle CollectionView exibe uma coleção de itens e, nesse caso, está associado à propriedade Notes do modelo. A maneira como cada item é apresentado pelo modo de exibição de coleção é definida por meio das propriedades CollectionView.ItemsLayout e CollectionView.ItemTemplate.

    Para cada item da coleção, o CollectionView.ItemTemplate gera o XAML declarado. O BindingContext desse XAML torna-se o item de coleção em si, nesse caso, cada anotação individual. O modelo da anotação usa dois rótulos, que são associados às propriedades Text e Date da nota.

  • O CollectionView manipula o evento SelectionChanged, que é gerado quando um item no modo de exibição de coleção é selecionado.

O code-behind para a exibição precisa ser gravado para carregar as anotações e manipular os eventos.

  1. No painel Gerenciador de Soluções, abra o arquivo Views/AllNotesPage.xaml.cs.

  2. Substitua o código pelo seguinte snippet:

    namespace Notes.Views;
    
    public partial class AllNotesPage : ContentPage
    {
        public AllNotesPage()
        {
            InitializeComponent();
    
            BindingContext = new Models.AllNotes();
        }
    
        protected override void OnAppearing()
        {
            ((Models.AllNotes)BindingContext).LoadNotes();
        }
    
        private async void Add_Clicked(object sender, EventArgs e)
        {
            await Shell.Current.GoToAsync(nameof(NotePage));
        }
    
        private async void notesCollection_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.CurrentSelection.Count != 0)
            {
                // Get the note model
                var note = (Models.Note)e.CurrentSelection[0];
    
                // Should navigate to "NotePage?ItemId=path\on\device\XYZ.notes.txt"
                await Shell.Current.GoToAsync($"{nameof(NotePage)}?{nameof(NotePage.ItemId)}={note.Filename}");
    
                // Unselect the UI
                notesCollection.SelectedItem = null;
            }
        }
    }
    

Esse código usa o construtor para definir o BindingContext da página para o modelo.

O método OnAppearing é substituído da classe base. Esse método é chamado automaticamente sempre que a página é mostrada, como quando a página é navegada. O código aqui informa ao modelo para carregar as anotações. Como o CollectionView no modo de exibição AllNotes está vinculado à propriedade AllNotes do modeloNotes, que é um ObservableCollection, sempre que as notas são carregadas, o CollectionView é atualizado automaticamente.

O manipulador de Add_Clicked apresenta outro novo conceito, a navegação. Como o aplicativo está usando o Shell do .NET MAUI, você pode navegar até páginas chamando o método Shell.Current.GoToAsync. Observe que o manipulador é declarado com a palavra-chave async, que permite o uso da palavra-chave await ao navegar. Esse manipulador navega até o NotePage.

A última parte do código no snippet anterior é o manipulador de notesCollection_SelectionChanged. Esse método usa o item selecionado no momento, um modelo Note e usa suas informações para navegar até o NotePage. GoToAsync usa uma cadeia de caracteres de URI para navegação. Nesse caso, uma cadeia de caracteres é construída que usa um parâmetro de cadeia de caracteres de consulta para definir uma propriedade na página de destino. A cadeia de caracteres interpolada que representa o URI acaba parecendo semelhante à seguinte cadeia de caracteres:

NotePage?ItemId=path\on\device\XYZ.notes.txt

O parâmetro ItemId= é definido como o nome do arquivo no dispositivo em que a anotação é armazenada.

O Visual Studio pode estar indicando que a propriedade NotePage.ItemId não existe, o que é correto. A próxima etapa é modificar a Note exibição para carregar o modelo com base no parâmetro ItemId que você criará.

Parâmetros de cadeia de caracteres de consulta

A Note exibição precisa dar suporte ao parâmetro de cadeia de caracteres de consulta, ItemId. Crie-o agora:

  1. No painel Gerenciador de Soluções, abra o arquivo Views/NotePage.xaml.cs.

  2. Adicione o atributo QueryProperty à palavra-chave class, fornecendo o nome da propriedade de cadeia de caracteres de consulta e a propriedade de classe para a qual ela mapeia, ItemId e ItemId respectivamente:

    [QueryProperty(nameof(ItemId), nameof(ItemId))]
    public partial class NotePage : ContentPage
    
  3. Adicione uma nova propriedade string chamada ItemId. Essa propriedade chama o método LoadNote, passando o valor da propriedade, que, por sua vez, deve ser o nome do arquivo da nota:

    public string ItemId
    {
        set { LoadNote(value); }
    }
    
  4. Substitua os manipuladores SaveButton_Clicked e DeleteButton_Clicked pelo seguinte código:

    private async void SaveButton_Clicked(object sender, EventArgs e)
    {
        if (BindingContext is Models.Note note)
            File.WriteAllText(note.Filename, TextEditor.Text);
    
        await Shell.Current.GoToAsync("..");
    }
    
    private async void DeleteButton_Clicked(object sender, EventArgs e)
    {
        if (BindingContext is Models.Note note)
        {
            // Delete the file.
            if (File.Exists(note.Filename))
                File.Delete(note.Filename);
        }
    
        await Shell.Current.GoToAsync("..");
    }
    

    Os botões agora são async. Depois que eles são pressionados, a página navega de volta para a página anterior usando um URI de ...

  5. Exclua a variável _fileName da parte superior do código, pois ela não é mais usada pela classe.

Modificar a árvore visual do aplicativo

O AppShell ainda está carregando a página de anotação única, em vez disso, ele precisa carregar a exibição AllPages. Abra o arquivo AppShell.xaml e altere a primeira entrada ShellContent para apontar para o AllNotesPage em vez de NotePage:

<?xml version="1.0" encoding="UTF-8" ?>
<Shell
    x:Class="Notes.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:views="clr-namespace:Notes.Views"
    Shell.FlyoutBehavior="Disabled">

    <TabBar>
        <ShellContent
            Title="Notes"
            ContentTemplate="{DataTemplate views:AllNotesPage}"
            Icon="{OnPlatform 'icon_notes.png', iOS='icon_notes_ios.png', MacCatalyst='icon_notes_ios.png'}" />

        <ShellContent
            Title="About"
            ContentTemplate="{DataTemplate views:AboutPage}"
            Icon="{OnPlatform 'icon_about.png', iOS='icon_about_ios.png', MacCatalyst='icon_about_ios.png'}" />
    </TabBar>

</Shell>

Se você executar o aplicativo agora, perceberá que ele falhará se pressionar o botão Adicionar, reclamando que ele não pode navegar até NotesPage. Todas as páginas que podem ser navegadas de outra página precisam ser registradas no sistema de navegação. As páginas AllNotesPage e AboutPage são registradas automaticamente no sistema de navegação sendo declaradas no TabBar.

Registre o NotesPage com o sistema de navegação:

  1. No painel Gerenciador de Soluções, abra o arquivo AppShell.xaml.cs.

  2. Adicione uma linha ao construtor que registra a rota de navegação:

    namespace Notes;
    
    public partial class AppShell : Shell
    {
        public AppShell()
        {
            InitializeComponent();
    
            Routing.RegisterRoute(nameof(Views.NotePage), typeof(Views.NotePage));
        }
    }
    

O método Routing.RegisterRoute usa dois parâmetros:

  • O primeiro parâmetro é o nome da cadeia de caracteres do URI que você deseja registrar, nesse caso, o nome resolvido é "NotePage".
  • O segundo parâmetro é o tipo de página a ser carregada quando "NotePage" é navegada.

Agora você pode executar seu aplicativo. Tente adicionar novas anotações, navegar entre anotações e excluir anotações.

Explore o código. Explore o código deste tutorial.. Se você quiser baixar uma cópia do projeto concluído com a qual comparar seu código, baixe este projeto.

Você concluiu o tutorial Criar um aplicativo .NET MAUI!

Próximas etapas

No próximo tutorial, você aprenderá a implementar padrões MVVM (model-view-viewmodel) em seu projeto.

Os seguintes links fornecem mais informações relacionadas a alguns dos conceitos que você aprendeu neste tutorial: