Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Esta parte do tutorial apresenta os conceitos de exibições de dados e modelos.
Nas etapas anteriores do tutorial, você adicionou uma nova página ao projeto que permite que o usuário salve, edite ou exclua uma única anotação. No entanto, como o aplicativo precisa lidar com mais de uma nota, você precisa adicionar outra página que exibe todas as anotações (chame-a AllNotesPage). Esta página permitirá que o usuário escolha uma nota para abrir na página do editor para que ele possa exibi-la, editá-la ou excluí-la. Ele também deve permitir que o usuário crie uma nova anotação.
Para fazer isso, AllNotesPage precisa ter uma coleção de anotações e uma maneira de exibir a coleção. É aí que o aplicativo encontra problemas porque os dados de anotação estão fortemente associados ao NotePage arquivo. Em AllNotesPage, você só deseja exibir todas as anotações em uma lista ou outro modo de exibição de coleção, com informações sobre cada anotação, como a data em que ela foi criada e uma visualização do texto. Com o texto da anotação sendo fortemente associado ao TextBox controle, não há como fazer isso.
Antes de adicionar uma página para mostrar todas as anotações, vamos fazer algumas alterações para separar os dados de anotação da apresentação de anotação.
Exibições e modelos
Normalmente, um aplicativo WinUI tem pelo menos uma camada de exibição e uma camada de dados.
A camada de exibição define a interface do usuário usando a marcação XAML. A marcação inclui expressões de associação de dados (como x:Bind) que definem a conexão entre componentes específicos da interface do usuário e membros de dados. Os arquivos code-behind às vezes são usados como parte da camada de exibição para conter código adicional necessário para personalizar ou manipular a interface do usuário ou para extrair dados de argumentos do manipulador de eventos antes de chamar um método que executa o trabalho nos dados.
A camada de dados, ou modelo, define os tipos que representam os dados do aplicativo e a lógica relacionada. Essa camada é independente da camada de exibição e você pode criar várias exibições diferentes que interagem com os dados.
Atualmente, representa NotePage uma exibição de dados (o texto da anotação). No entanto, depois que os dados são lidos no aplicativo a partir do arquivo do sistema, ele existe apenas na Text propriedade do TextBox in NotePage. Ele não é representado no aplicativo de uma maneira que permite que você apresente os dados de maneiras diferentes ou em locais diferentes; ou seja, o aplicativo não tem uma camada de dados. Você reestruturará o projeto agora para criar a camada de dados.
Separar a exibição e o modelo
Dica
Você pode baixar ou exibir o código deste tutorial no repositório do GitHub. Para ver o código como ele está nesta etapa, consulte esta confirmação: página de observação – modelo de exibição.
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.
No Gerenciador de Soluções, clique com o botão direito do WinUINotes mouse no projeto e selecione Adicionar>Nova Pasta. Nomeie a pasta Models.
Clique com o botão direito do mouse no WinUINotes projeto novamente e selecione Adicionar>Nova Pasta. Nomeie a pasta Views.
Localize o NotePage.xaml item e arraste-o para a Views pasta. O NotePage.xaml.cs arquivo deve se mover com ele.
Observação
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. Você alterará o namespace nas próximas etapas.
Atualizar o namespace de exibição
Agora que a exibição foi movida para a Views pasta, você precisará atualizar os namespaces para corresponder. O namespace para os arquivos XAML e code-behind das páginas é definido como WinUINotes. Isso precisa ser atualizado para WinUINotes.Views.
No painel Gerenciador de Soluções , expanda NotePage.xaml para revelar o arquivo code-behind.
Clique duas vezes no NotePage.xaml.cs item para abrir o editor de código se ele ainda não estiver aberto. Altere o namespace para
WinUINotes.Views:namespace WinUINotes.ViewsClique duas vezes no NotePage.xaml item para abrir o editor XAML se ele ainda não estiver aberto. 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 valorx:ClassparaWinUINotes.Views.NotePage:x:Class="WinUINotes.Views.NotePage"
Corrigir a referência de namespace em MainWindow
Na etapa anterior, você criou a página de anotação e atualizou MainWindow.xaml para navegar até ela. Lembre-se de que ele foi mapeado com o mapeamento de local: namespace. É uma prática comum mapear o nome local para o namespace raiz do projeto e o modelo de projeto do Visual Studio já faz isso para você (xmlns:local="using:WinUINotes"). Agora que a página foi movida para um novo namespace, o mapeamento de tipo no XAML agora é inválido.
Felizmente, você pode adicionar seus próprios mapeamentos de namespace conforme necessário. Você precisa fazer isso para acessar itens em pastas diferentes criadas em seu projeto. Esse novo namespace XAML será mapeado para o namespace de WinUINotes.Views, portanto, nomeie-o views. A declaração deve ser semelhante ao seguinte atributo: xmlns:views="using:WinUINotes.Views".
No painel Gerenciador de Soluções , clique duas vezes na entrada MainWindow.xaml para abri-la no editor XAML.
Adicione este novo mapeamento de namespace na linha abaixo do mapeamento para
local:xmlns:views="using:WinUINotes.Views"O
localnamespace XAML foi usado para definir a propriedade, portanto, altere-aFrame.SourcePageTypeparaviewslá. Seu XAML agora deve ter esta aparência:<Window x:Class="WinUINotes.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:WinUINotes" xmlns:views="using:WinUINotes.Views" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Title="WinUI Notes"> <!-- ... Unchanged XAML not shown. --> <Frame x:Name="rootFrame" Grid.Row="1" SourcePageType="views:NotePage"/> <!-- ... Unchanged XAML not shown. --> </Window>Compile e execute o aplicativo. O aplicativo deve ser executado sem erros do compilador e tudo ainda deve funcionar como antes.
Definir o modelo
Atualmente, o modelo (os dados) está inserido no modo de exibição de observação. Você criará uma nova classe para representar os dados de uma página de anotação:
No painel Gerenciador de Soluções, clique com o botão direito do mouse na pasta Models e selecione Adicionar>Classe....
Nomeie a classe Note.cs e pressione Adicionar. O Note.cs arquivo será aberto no editor de código.
Substitua o código no Note.cs arquivo por esse código, o que torna a classe
publice adiciona propriedades e métodos para lidar com uma observação:using System; using System.Threading.Tasks; using Windows.Storage; namespace WinUINotes.Models { public class Note { private StorageFolder storageFolder = ApplicationData.Current.LocalFolder; public string Filename { get; set; } = string.Empty; public string Text { get; set; } = string.Empty; public DateTime Date { get; set; } = DateTime.Now; public Note() { Filename = "notes" + DateTime.Now.ToBinary().ToString() + ".txt"; } public async Task SaveAsync() { // Save the note to a file. StorageFile noteFile = (StorageFile)await storageFolder.TryGetItemAsync(Filename); if (noteFile is null) { noteFile = await storageFolder.CreateFileAsync(Filename, CreationCollisionOption.ReplaceExisting); } await FileIO.WriteTextAsync(noteFile, Text); } public async Task DeleteAsync() { // Delete the note from the file system. StorageFile noteFile = (StorageFile)await storageFolder.TryGetItemAsync(Filename); if (noteFile is not null) { await noteFile.DeleteAsync(); } } } }Salve o arquivo.
Você observará que esse código é muito semelhante ao código, NotePage.xaml.cscom algumas alterações e adições.
Filename e Text foram alterados para public propriedades e uma nova Date propriedade foi adicionada.
O código para salvar e excluir os arquivos foi colocado em public métodos. Ele é praticamente idêntico ao código usado nos manipuladores de eventos de botão Click , NotePagemas o código extra para atualizar o modo de exibição após a exclusão do arquivo foi removido. Não é necessário aqui porque você usará a associação de dados para manter o modelo e exibir sincronizado.
Essas assinaturas de método assíncrono retornam Tarefa em vez de void. A Task classe representa uma única operação assíncrona que não retorna um valor. A menos que a assinatura do método exijavoid, como é o caso dos manipuladores de eventos, Click os async métodos devem retornar um Task.
Você também não manterá mais uma referência ao StorageFile que contém a nota. Você só tenta obter o arquivo quando precisa dele para salvar ou excluir.
Em NotePage, você usou um espaço reservado para o nome do arquivo: note.txt. Agora que o aplicativo dá suporte a mais de uma nota, os nomes de arquivo para anotações salvas precisam ser diferentes e exclusivos. Para fazer isso, defina a Filename propriedade no construtor. Você pode usar o método DateTime.ToBinary para criar uma parte do nome do arquivo com base na hora atual e tornar os nomes de arquivo exclusivos. O nome do arquivo gerado tem esta aparência: notes-8584626598945870392.txt.
Atualizar a página de notas
Agora você pode atualizar a NotePage exibição para usar o Note modelo de dados e excluir o código que foi movido para o Note modelo.
Abra o arquivo Views\NotePage.xaml.cs se ele ainda não estiver aberto no editor.
Após a última
usinginstrução na parte superior da página, adicione uma novausinginstrução para dar acesso ao código às classes na pasta e noModelsnamespace.using WinUINotes.Models;Exclua estas linhas da classe:
private StorageFolder storageFolder = ApplicationData.Current.LocalFolder; private StorageFile? noteFile = null; private string fileName = "note.txt";Em vez disso, adicione um
Noteobjeto nomeadonoteModelem seu lugar. Isso representa os dados de anotação queNotePagefornecem uma exibição.private Note? noteModel;Você também não precisa mais do
NotePage_Loadedmanipulador de eventos. Você não lerá o texto diretamente do arquivo de texto no TextBox. Em vez disso, o texto da anotação será lido emNoteobjetos. Você adicionará o código para isso quando adicionar aAllNotesPageetapa posterior. Exclua essas linhas.Loaded += NotePage_Loaded; ... private async void NotePage_Loaded(object sender, RoutedEventArgs e) { noteFile = (StorageFile)await storageFolder.TryGetItemAsync(fileName); if (noteFile is not null) { NoteEditor.Text = await FileIO.ReadTextAsync(noteFile); } }Substitua o código no
SaveButton_Clickmétodo por isso:if (noteModel is not null) { await noteModel.SaveAsync(); }Substitua o código no
DeleteButton_Clickmétodo por isso:if (noteModel is not null) { await noteModel.DeleteAsync(); }
Agora você pode atualizar o arquivo XAML para usar o Note modelo. Anteriormente, você leu o texto diretamente do arquivo de texto na TextBox.Text propriedade no arquivo code-behind. Agora, você usa a associação de dados para a Text propriedade.
Abra o arquivo Views\NotePage.xaml se ele ainda não estiver aberto no editor.
Adicione um
Textatributo aoTextBoxcontrole. Associe-oTextà propriedade denoteModel:Text="{x:Bind noteModel.Text, Mode=TwoWay}".Atualize a
Headerassociação àDatepropriedade denoteModel:Header="{x:Bind noteModel.Date.ToString()}".<TextBox x:Name="NoteEditor" <!-- ↓ Add this line. ↓ --> Text="{x:Bind noteModel.Text, Mode=TwoWay}" AcceptsReturn="True" TextWrapping="Wrap" PlaceholderText="Enter your note" <!-- ↓ Update this line. ↓ --> Header="{x:Bind noteModel.Date.ToString()}" ScrollViewer.VerticalScrollBarVisibility="Auto" Width="400" Grid.Column="1"/>
A associação de dados é uma maneira de a interface do usuário do aplicativo exibir dados e, opcionalmente, manter-se sincronizada com esses dados. A Mode=TwoWay configuração na associação significa que as propriedades e TextBox.Text as noteModel.Text propriedades são sincronizadas automaticamente. Quando o texto é atualizado no TextBox, as alterações são refletidas na Text propriedade do noteModel, e se noteModel.Text for alterado, as atualizações serão refletidas no TextBox.
A Header propriedade usa o padrão Mode porque OneTime a noteModel.Date propriedade não é alterada depois que o arquivo é criado. Esse código também demonstra um recurso poderoso da chamada x:Bind de função, que permite que você use uma função como ToString uma etapa no caminho de associação.
Importante
É importante escolher o BindingMode correto; caso contrário, a associação de dados pode não funcionar conforme o esperado. (Um erro comum é {x:Bind} esquecer de alterar o padrão BindingMode quando OneWay ou TwoWay for necessário.)
| Nome | Description |
|---|---|
OneTime |
Atualiza a propriedade de destino somente quando a associação é criada. Padrão para {x:Bind}. |
OneWay |
Atualiza a propriedade de destino quando a associação é criada. As alterações no objeto de origem também podem se propagar para o destino. Padrão para {Binding}. |
TwoWay |
Atualiza o destino ou o objeto de origem quando uma das alterações é alterada. Quando a associação é criada, a propriedade de destino é atualizada da origem. |
A associação de dados dá suporte à separação de seus dados e interface do usuário e isso resulta em um modelo conceitual mais simples, bem como melhor legibilidade, testabilidade e manutenção do seu aplicativo.
No WinUI, há dois tipos de associação que você pode escolher:
- A
{x:Bind}extensão de marcação é processada em tempo de compilação. Alguns de seus benefícios são melhor desempenho e validação em tempo de compilação de suas expressões de associação. É recomendado para associação em aplicativos WinUI. - A
{Binding}extensão de marcação é processada em tempo de execução e usa a inspeção de objeto de runtime de uso geral.
Saiba mais nos documentos:
Vinculação de dados e MVVM
Model-View-ViewModel (MVVM) é um padrão de design de arquitetura da interface do usuário para desacoplar a interface do usuário e o código que não é da interface do usuário que é popular entre os desenvolvedores do .NET. Você provavelmente verá e ouvirá isso mencionado à medida que aprender mais sobre como criar aplicativos WinUI. Separar os modos de exibição e os modelos, como você fez aqui, é o primeiro passo para uma implementação completa do MVVM do aplicativo, mas é o mais longe possível neste tutorial.
Observação
Usamos o termo "modelo" para fazer referência ao modelo de dados neste tutorial, mas é importante observar que esse modelo está mais alinhado com o ViewModel em uma implementação MVVM completa, ao mesmo tempo em que incorpora aspectos do Modelo.
Para saber mais sobre o MVVM, confira estes recursos:
Windows developer