Partilhar via


Criar um aplicativo .NET MAUI

Este tutorial foi projetado para demonstrar como criar um aplicativo .NET Multi-platform App UI (.NET MAUI) que usa apenas código entre plataformas. 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ções, onde o usuário poderá criar, salvar e carregar várias anotações.

Neste tutorial, aprenderás como:

  • Crie um aplicativo .NET MAUI Shell.
  • Execute seu aplicativo na plataforma escolhida.
  • Defina a interface do usuário com eXtensible Application Markup Language (XAML) e interaja com elementos XAML por meio de código.
  • Crie vistas e associe-as aos dados.
  • Use a navegação para mover de e para as 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. A candidatura final é apresentada aqui:

Captura de ecrã final da aplicação de notas, listando as notas. Captura de ecrã final da aplicação de notas, adicionando uma nota.

Criar um projeto

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

  • Nome do Projeto

    Isso deve ser definido como Notes. Se o projeto for nomeado algo diferente, o código que você copiar e colar deste tutorial pode resultar em erros de compilação.

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

    Desmarque esta configuração.

Defina o nome do projeto .NET MAUI como Notes no Visual Studio.

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

Selecione o dispositivo alvo

Os aplicativos .NET MAUI são projetados para serem executados em vários sistemas operacionais e dispositivos. Você precisará selecionar qual alvo deseja usar para testar e depurar o 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 a configuração do de destino de depuração para Android:

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

  1. Selecione o botão suspenso Debug Target.
  2. Selecione o Emuladores Android item.
  3. Selecione o dispositivo do emulador.

Personalizar o shell do aplicativo

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

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

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

  • MauiProgram.cs

    Este é um arquivo de código que inicializa seu aplicativo. O código neste 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 definida pelo arquivo App.xaml .

  • e App.xaml.cs App.xaml

    Apenas para manter as coisas simples, ambos os arquivos são referidos como um único arquivo. Geralmente, há dois arquivos com qualquer arquivo XAML, o próprio arquivo de .xaml e um arquivo de código correspondente que é um item filho dele no Gerenciador de Soluções . O arquivo de .xaml contém marcação XAML e o arquivo de código contém 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 instancia o aplicativo Shell. Neste projeto, aponta para a classe AppShell.

  • e AppShell.xaml.cs AppShell.xaml

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

  • e MainPage.xaml.cs MainPage.xaml

    Esta é a página de inicialização exibida pelo aplicativo. O arquivo de 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 o 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 este aplicativo, como o autor, a versão e talvez um link para obter mais informações.

  1. No painel do Explorador de Soluções do Visual Studio, clique com o botão direito do rato sobre o projeto Notas>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 de .NET MAUI ContentPage (XAML). Nomeie o arquivo AboutPage.xamle selecione Adicionar .

    Adicionando uma nova ContentPage ao projeto. O ContentPage é chamado AboutPage.xaml.

  3. O arquivo de 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 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.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 detalhar as principais partes dos controles XAML colocados na página:

  • <ContentPage> é o objeto raiz para a 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 filhos verticalmente, um após o outro.

  • <HorizontalStackLayout> funciona da mesma forma que um <VerticalStackLayout>, exceto que seus filhos estão dispostos horizontalmente.

  • <Image> exibe uma imagem, neste caso está usando a imagem dotnet_bot.png que vem com cada projeto .NET MAUI.

    Importante

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

  • <Label> controla a exibição do texto.

  • <Button> controles podem ser pressionados pelo usuário, o que aumenta o evento Clicked. Você pode executar 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 para o evento do Clicked botão.

  1. No painel Gerenciador de Soluções do Visual Studio, expanda o arquivo de 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ódigos.

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

  2. Adicione o seguinte código do manipulador de eventos LearnMore_Clicked, que abre o navegador do sistema para uma URL específica:

    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 de 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 melhora 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.

Faça o download das seguintes imagens:

Depois de baixar as imagens, você pode movê-las com o Explorador de Arquivos para a pasta Resources\Images do projeto. Qualquer arquivo nesta pasta é automaticamente incluído 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 pule 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.

    Sugestão

    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 optar por arrastar e largar os ficheiros, ignore o resto 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 filtro de tipo de arquivo para Arquivos de imagem.

  5. Mantenha pressionada a tecla Ctrl e clique em cada uma das imagens baixadas e pressione Adicionar

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

Modificar o shell do aplicativo

Conforme observado no início deste artigo, a classe AppShell define a 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 de AppShell.xaml no painel Gerenciador de Soluções para abrir o editor XAML. Substitua a marcação XAML pelo seguinte código:

    <?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 detalhar as partes principais do XAML:

  • <Shell> é o objeto raiz da marcação XAML.
  • <TabBar> é o conteúdo do Shell.
  • Dois <ShellContent> objetos 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 nenhum elemento da interface do usuário, mas sim a organização da hierarquia visual do aplicativo. O Shell pega 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, todas as plataformas usam o ícone icon_about.png por padrão, mas iOS e 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 de reprodução na parte superior do Visual Studio:

botão Debug Target do Visual Studio com o texto Windows Machine.

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

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

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

botão parar depuração do Visual Studio.

Criar uma página para uma nota

Agora que o aplicativo contém os 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 uma nota e, em seguida, escreverá o código para carregar e salvar a nota.

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

  1. No painel do Explorador de Soluções do Visual Studio, clique com o botão direito do rato sobre o projeto Notas>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 de .NET MAUI ContentPage (XAML). Nomeie o arquivo NotePage.xamle 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 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"
                 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 Arquivo>Save NotePage.xaml.

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

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

  • <Editor> é um controle de editor de texto de várias linhas e é o primeiro controle dentro do 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 da criança 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 diz à coluna para preencher o máximo de espaço possível. O trecho anterior definia duas colunas, ambas usando o máximo de espaço possível, o que distribui uniformemente as colunas no espaço atribuído: ColumnDefinitions="*,*". Os tamanhos das colunas são separados por um caractere ,.

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

  • Dois controles <Button> estão dentro do <Grid> e recebem uma coluna. Se um controle filho não definir uma atribuição de coluna, ele será automaticamente atribuído à primeira coluna. Nesta marcação, o primeiro botão é o botão "Guardar" 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 Clicked evento manipulado. Você adicionará o código para esses manipuladores na próxima seção.

Carregue e guarde uma nota

Abra o NotePage.xaml.cs arquivo code-behind. Você pode abrir o code-behind do 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 View Code.
  • Use o Gerenciador de Soluções para expandir a entrada NotePage.xaml , revelando o arquivo NotePage.xaml.cs. Clique duas vezes no arquivo para abri-lo.

Quando você adiciona um novo arquivo XAML, o code-behind contém uma única linha no construtor, uma chamada para o 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ê vai adicionar código ao NotePage.xaml.cs arquivo code-behind para lidar com o carregamento e salvamento de notas.

  1. Quando uma nota é 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 é 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 manipular os eventos 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, para o 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 Arquivo>Salvar NotePage.xaml.cs.

O código final para o arquivo code-behind deve ter a seguinte aparência:

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;
    }
}

Teste a nota

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

<?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 abra-o novamente. A nota que introduziu deve ser carregada a partir do armazenamento do dispositivo.

Página de entrada da nota no aplicativo .NET MAUI.

Vincular dados à interface do usuário e navegar pelas páginas

Esta parte do tutorial apresenta os conceitos de modos de exibição, 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. A NotePage é uma "vista" que apresenta "dados de nota" e a AboutPage é uma "vista" que apresenta "dados de informações da aplicação". Ambas as exibições têm um modelo desses dados codificado ou incorporado nelas, e você precisará separar o modelo de dados da exibição.

Qual é a vantagem de separar o modelo da vista? 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 vinculação de dados, algo que será apresentado mais adiante neste tutorial. Por enquanto, porém, vamos reestruturar o projeto.

Separe a vista 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 as exibições e os modelos sejam definidos separadamente uns dos outros.

  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 nela e selecione Excluir.

    Sugestão

    A exclusão do item de 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. Dê um nome à pasta Models.

  3. Clique com o botão direito do mouse no projeto Notes e selecione Adicionar>Nova Pasta. Dê um nome à 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 vir este aviso.

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

  5. Encontre o item de 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 Notes com a pasta Views e as visualizações de página expandidas.

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

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

  4. Clique duas vezes no item de 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 para o XAML. Esta 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 para o item AboutPage.xaml, mas defina o valor como .

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. Deve ser semelhante ao seguinte trecho:

<?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 .NET no mesmo assembly é:

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

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

Remova o namespace XML local e adicione um novo. Esse novo namespace XML será mapeado para o namespace .NET do Notes.Views, então 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-as para views. Seu XAML agora deve se parecer com o seguinte trecho:

<?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 de compilador, e tudo ainda deve funcionar como antes.

Definir o modelo

Atualmente, o modelo são os dados que estão incorporados na nota e sobre as visualizações. Criaremos novas classes para representar esses dados. Primeiro, o modelo para representar os dados de uma página de nota:

  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 trecho:

    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 trecho:

    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.

Atualizar página Sobre

A página sobre será a página mais rápida de atualizar 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 trecho:

    <?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>
    

Vejamos as linhas alteradas, que são destacadas no trecho anterior:

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

    Esta linha mapeia o namespace .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 vinculação para aumentar o desempenho do tempo de execução 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 do elemento de propriedade em vez de um atributo XML.

    Importante

    Até agora, as propriedades eram definidas usando um atributo XML. Isso funciona muito 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 sintaxe de ligação: {Binding PATH}.

    {Binding} sintaxe é processada em tempo de execução, permitindo que o valor retornado da associação seja dinâmico. A parte PATH do {Binding PATH} é o caminho da propriedade ao qual se vincular. A propriedade vem do controle atual BindingContext. Com o controle <Label>, BindingContext é desconfigurado. O contexto é herdado do pai quando é desdefinido pelo controle, que neste 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 ligação de um dos rótulos vincula a propriedade Label.Text à propriedade About.Title.

A alteração final na página sobre é atualizar o clique no 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 com o 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ê olhar para a linha realçada, o código verificará se o BindingContext é um tipo Models.About e, se for, atribui-o à variável about. 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 como antes. Tente alterar os valores do modelo about e veja como a interface do usuário e o URL abertos pelo navegador também mudam.

Página Atualizar Nota

A seção anterior vinculava a exibição de página about ao modelo about e agora você fará o mesmo, vinculando a exibição note ao modelo note. No entanto, nesse caso, o modelo não será criado em 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 trecho:

    <?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>
    

Vejamos as linhas alteradas, que são destacadas no trecho anterior:

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

    Esta linha mapeia o namespace .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 vinculação para aumentar o desempenho do tempo de execução 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 vinculando 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, em seguida, 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 nota no construtor, crie um novo método LoadNote. Este método fará o seguinte:

  • Aceite um parâmetro de nome de arquivo.
  • Crie um novo modelo de nota 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 a BindingContext da página para 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 para a nota deve ser um nome gerado aleatoriamente a 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 vista e um modelo que listem todas as notas

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

Várias notas e navegação

Atualmente, a exibição de de notas exibe uma única nota. Para exibir várias anotações, crie um novo modo de exibição e 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 de .NET MAUI ContentPage (XAML). Nomeie o arquivo AllNotesPage.xamle, em seguida, 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.

Codifique o modelo AllNotes

O novo modelo representará os dados necessários para exibir várias notas. Esses dados serão uma propriedade que representa uma coleção de notas. A coleção será um ObservableCollection que é uma coleção especializada. Quando um controle que lista vários itens, como um ListView, é vinculado a um ObservableCollection, os dois trabalham juntos para manter automaticamente a lista de itens sincronizada 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 Gerenciador de Soluções , abra o arquivo Models\AllNotes.cs.

  2. Substitua o código pelo seguinte trecho:

    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 notas do dispositivo. Esse método usa extensões LINQ para carregar, transformar e classificar os dados na coleção Notes.

Criar a página AllNotes

Em seguida, a exibição precisa ser projetada para suportar o 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 introduz alguns conceitos novos:

  • 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, pode estar em uma posição diferente. Quando um desses botões é pressionado, o evento Clicked é levantado, 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 imagem.

  • O controle CollectionView exibe uma coleção de itens e, nesse caso, está vinculado à propriedade Notes do modelo. A maneira como cada item é apresentado pela 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. A BindingContext desse XAML torna-se o próprio item de coleção, neste caso, cada nota individual. O modelo para a nota usa dois rótulos, que são vinculados à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 da exibição precisa ser escrito para carregar as notas 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 trecho:

    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 diz ao modelo para carregar as notas. Como o no de exibição do AllNotes está vinculado à propriedade do modelo AllNotes, que é um , sempre que as notas são carregadas, o é atualizado automaticamente.

O manipulador de Add_Clicked introduz outro novo conceito, a navegação. Como o aplicativo está usando o .NET MAUI Shell, você pode navegar até as 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. Este manipulador navega para o NotePage.

A última parte do código no trecho 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 URI para navegação. Nesse caso, é construída uma cadeia de caracteres 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 se parecendo com a seguinte cadeia de caracteres:

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

O parâmetro ItemId= é definido como o nome do arquivo no dispositivo onde a nota está armazenada.

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

Parâmetros de string de consulta

O modo de exibição Note precisa suportar o 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. Esta 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 estão async. Depois de 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 nota única, em vez disso, ele precisa carregar o visualização AllPages. Abra o arquivo de AppShell.xaml e altere a primeira entrada para apontar para o em vez de :

<?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, notará que ele falha se você pressionar o botão Adicionar , reclamando que ele não pode navegar até . Todas as páginas que podem ser navegadas a partir de outra página, precisam ser registradas no sistema de navegação. As páginas AllNotesPage e AboutPage são automaticamente registadas no sistema de navegação, sendo declaradas no TabBar.

Registe 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, neste 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 notas, navegar entre notas e eliminar notas.

Explore o código. Explore o código deste tutorial.. Se você quiser baixar uma cópia do projeto concluído para comparar seu código, faça o download este projeto.

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

Próximos passos

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

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