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.
Agora que você tem a estrutura do projeto em vigor, você pode começar a implementar o padrão MVVM usando o MVVM Toolkit. Esta etapa envolve a criação de ViewModels que aproveitam os recursos do Kit de Ferramentas do MVVM, como ObservableObject para notificação de alteração de propriedade e RelayCommand para implementação de comando.
Instalar o pacote NuGet do Kit de Ferramentas MVVM
Você precisa instalar o Kit de Ferramentas MVVM nos projetos WinUINotes e WinUINotes.Bus .
Usando o Visual Studio
- Clique com o botão direito do mouse no projeto WinUINotes.Bus no Gerenciador de Soluções.
- Selecione Gerenciar Pacotes NuGet.
- Pesquise CommunityToolkit.Mvvm e instale a versão estável mais recente.
- Repita estas etapas para o projeto WinUINotes .
Usando a CLI do .NET
Como alternativa, você pode usar a CLI do .NET para instalar o pacote:
dotnet add WinUINotes.Bus package CommunityToolkit.Mvvm
dotnet add WinUINotes package CommunityToolkit.Mvvm
Decisões de design para a camada de modelo
Ao implementar o MVVM, é importante decidir como estruturar suas classes de modelo em relação ao ViewModels. Neste tutorial, as classes de modelo (Note e AllNotes) são responsáveis pela representação de dados, pela lógica de negócios e pela atualização do armazenamento de dados. O ViewModels lida com propriedades observáveis, notificação de alteração e comandos para interação com a interface do usuário.
Em uma implementação mais simples, você pode usar POCOs (objetos CLR simples) antigos para as classes de modelo sem qualquer lógica de negócios ou métodos de acesso a dados. Nesse caso, o ViewModels manipula todas as operações de dados por meio da camada de serviço. No entanto, para este tutorial, as classes de modelo incluem métodos para carregar, salvar e excluir anotações para fornecer uma separação mais clara de preocupações e manter os ViewModels focados na lógica da apresentação.
Mover o modelo de nota
Mova a Note classe para o projeto WinUINotes.Bus . Ela continua sendo uma classe de modelo simples com alguma lógica para representação de dados e gerenciamento de estado, mas sem recursos do Kit de Ferramentas MVVM. Os ViewModels manipulam as propriedades observáveis e alteram a notificação, não o próprio modelo.
No projeto WinUINotes.Bus , crie uma nova pasta chamada Modelos.
Mova o
Note.csarquivo do projeto WinUINotes para a pasta WinUINotes.Bus/Models .Atualize o namespace para corresponder ao novo local:
namespace WinUINotes.Models { public class Note { // Existing code remains unchanged ... } }
A Note classe é um modelo de dados simples. Ele não precisa de notificação de alteração porque os ViewModels gerenciam propriedades observáveis e notificam a interface do usuário das alterações.
Mover o modelo do AllNotes
Mova a AllNotes classe para o projeto WinUINotes.Bus .
Mova o
AllNotes.csarquivo do projeto WinUINotes para a pasta WinUINotes.Bus/Models .Atualize o namespace para corresponder ao novo local:
namespace WinUINotes.Models { public class AllNotes { // Existing code remains unchanged ... } }
Como a Note classe, AllNotes é uma classe de modelo simples. O ViewModel manipula o comportamento observável e gerencia a coleção de anotações.
Criar o AllNotesViewModel
No projeto WinUINotes.Bus , crie uma nova pasta chamada ViewModels.
Adicione um novo arquivo de classe nomeado
AllNotesViewModel.cscom o seguinte conteúdo:using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using System.Collections.ObjectModel; using System.Threading.Tasks; using WinUINotes.Models; namespace WinUINotes.ViewModels { public partial class AllNotesViewModel : ObservableObject { private readonly AllNotes allNotes; [ObservableProperty] private ObservableCollection<Note> notes; public AllNotesViewModel() { allNotes = new AllNotes(); notes = new ObservableCollection<Note>(); } [RelayCommand] public async Task LoadAsync() { await allNotes.LoadNotes(); Notes.Clear(); foreach (var note in allNotes.Notes) { Notes.Add(note); } } } }
O AllNotesViewModel gerencia a coleção de anotações exibidas na interface do usuário:
-
[ObservableProperty]: onotescampo gera automaticamente uma propriedade públicaNotescom notificação de alteração. Quando aNotescoleção é alterada, a interface do usuário é atualizada automaticamente. -
allNotesmodelo: esse campo privado contém uma instância doAllNotesmodelo, que manipula as operações de dados reais. -
[RelayCommand]: esse atributo gera umaLoadCommandpropriedade doLoadAsync()método, permitindo que a interface do usuário dispare a operação de carregamento por meio da associação de dados. -
LoadAsync()método: esse método carrega anotações do modelo, limpa a coleção observável atual e a preenche com as anotações carregadas. Esse padrão garante que a coleção associada à interface do usuário permaneça sincronizada com os dados subjacentes.
A separação entre o allNotes modelo (operações de dados) e a Notes coleção observável (associação de interface do usuário) é um padrão MVVM chave que mantém as preocupações separadas e a exibição em sincronia com os dados do ViewModel.
Saiba mais nos documentos:
Criar o NoteViewModel
Na pasta ViewModels , adicione um novo arquivo de classe chamado
NoteViewModel.cs:using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using System; using System.Threading.Tasks; using WinUINotes.Models; namespace WinUINotes.ViewModels { public partial class NoteViewModel : ObservableObject { private Note note; [ObservableProperty] [NotifyCanExecuteChangedFor(nameof(SaveCommand))] [NotifyCanExecuteChangedFor(nameof(DeleteCommand))] private string filename = string.Empty; [ObservableProperty] [NotifyCanExecuteChangedFor(nameof(SaveCommand))] private string text = string.Empty; [ObservableProperty] private DateTime date = DateTime.Now; public NoteViewModel() { this.note = new Note(); this.Filename = note.Filename; } public void InitializeForExistingNote(Note note) { this.note = note; this.Filename = note.Filename; this.Text = note.Text; this.Date = note.Date; } [RelayCommand(CanExecute = nameof(CanSave))] private async Task Save() { note.Filename = this.Filename; note.Text = this.Text; note.Date = this.Date; await note.SaveAsync(); // Check if the DeleteCommand can now execute // (it can if the file now exists) DeleteCommand.NotifyCanExecuteChanged(); } private bool CanSave() { return note is not null && !string.IsNullOrWhiteSpace(this.Text) && !string.IsNullOrWhiteSpace(this.Filename); } [RelayCommand(CanExecute = nameof(CanDelete))] private async Task Delete() { await note.DeleteAsync(); note = new Note(); } private bool CanDelete() { // Note: This is to illustrate how commands can be // enabled or disabled. // In a real application, you shouldn't perform // file operations in your CanExecute logic. return note is not null && !string.IsNullOrWhiteSpace(this.Filename) && this.note.NoteFileExists(); } } }
NoteViewModel demonstra vários recursos principais do MVVM Toolkit:
-
[ObservableProperty]: Os camposfilename,text, edategeram automaticamente propriedades públicas (Filename,Text,Date) com suporte à notificação de alteração. -
[NotifyCanExecuteChangedFor]: Esse atributo garante que, quandoFilenameouTextse alteram, os comandos associados reavaliam se eles podem ser executados. Por exemplo, quando você digita texto, o botão Salvar habilita ou desabilita automaticamente com base na lógica de validação. -
[RelayCommand(CanExecute = nameof(CanSave))]: esse atributo gera umaSaveCommandpropriedade associada ao métodoCanSave()de validação. O comando só é habilitado quando tantoTextquantoFilenamepossuem valores. -
InitializeForExistingNote(): esse método carrega os dados de uma anotação existente nas propriedades ViewModel, que atualizam a interface do usuário por meio da associação de dados. - Lógica de salvamento: O
Save()método atualiza o modelo subjacenteNotecom os valores de propriedade atuais e chamaSaveAsync()no modelo. Depois de salvar, ele notificaDeleteCommandque ele deve ser reavaliado (já que um arquivo agora existe e pode ser excluído). -
Excluir lógica: o método
Delete()chamaDeleteAsync()no modelo de anotação e cria uma nova nota vazia.
Posteriormente neste tutorial, você integrará o serviço de arquivo para lidar com as operações de arquivo reais e usar a classe do Kit de Ferramentas MVVM WeakReferenceMessenger para notificar outras partes do aplicativo quando uma anotação for excluída enquanto permanecer acoplada de forma flexível.
Saiba mais nos documentos:
Atualizar os modos de exibição para usar o ViewModels
Agora você precisa atualizar suas páginas XAML para associar ao novo ViewModels.
Atualizar o modo de exibição AllNotesPage
Em
AllNotesPage.xaml, atualize aItemsSourcevinculação doItemsViewpara usar a propriedadeNotesdo ViewModel.<ItemsView ItemsSource="{x:Bind viewModel.Notes}" ...Atualize o
AllNotesPage.xaml.csarquivo para ter esta aparência:using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Navigation; using WinUINotes.ViewModels; namespace WinUINotes.Views { public sealed partial class AllNotesPage : Page { private AllNotesViewModel? viewModel; public AllNotesPage() { this.InitializeComponent(); viewModel = new AllNotesViewModel(); } private void NewNoteButton_Click(object sender, RoutedEventArgs e) { Frame.Navigate(typeof(NotePage)); } private void ItemsView_ItemInvoked(ItemsView sender, ItemsViewItemInvokedEventArgs args) { Frame.Navigate(typeof(NotePage), args.InvokedItem); } protected override async void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); if (viewModel is not null) { await viewModel.LoadAsync(); } } } }
Neste arquivo code-behind, o construtor instancia diretamente o AllNotesViewModel. O método OnNavigatedTo() chama o método LoadAsync() no ViewModel quando a página é acessada. Esse método carrega as anotações do armazenamento e atualiza a coleção observável. Esse método garante que os dados sejam sempre atualizados quando o usuário acessar a página Todas as Anotações.
Posteriormente neste tutorial, você refatora esse código para usar a injeção de dependência, o que permite que o ViewModel seja injetado no construtor de página em vez de ser criado diretamente. Essa abordagem melhora a capacidade de teste e facilita o gerenciamento de ciclos de vida ViewModel.
Atualizar a visualização NotePage
Em
NotePage.xaml, atualize as associações deTextBoxparaTexteHeader, para usar as propriedades do ViewModel. Atualize os botõesStackPanelpara se vincular aos comandos em vez de usar os eventosClick:... <TextBox x:Name="NoteEditor" Text="{x:Bind noteVm.Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" AcceptsReturn="True" TextWrapping="Wrap" PlaceholderText="Enter your note" Header="{x:Bind noteVm.Date.ToString()}" ScrollViewer.VerticalScrollBarVisibility="Auto" MaxWidth="400" Grid.Column="1"/> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Spacing="4" Grid.Row="1" Grid.Column="1"> <Button Content="Save" Command="{x:Bind noteVm.SaveCommand}"/> <Button Content="Delete" Command="{x:Bind noteVm.DeleteCommand}"/> </StackPanel> ...Você também define
UpdateSourceTriggerna associaçãoTextBox.Textpara garantir que as alterações sejam enviadas ao ViewModel enquanto o usuário digita. Essa configuração permite que oSavebotão habilite ou desabilite em tempo real com base na entrada.Em
NotePage.xaml.cs, atualize o código para usar :NoteViewModelusing Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Navigation; using WinUINotes.Models; using WinUINotes.ViewModels; namespace WinUINotes.Views { public sealed partial class NotePage : Page { private NoteViewModel? noteVm; public NotePage() { this.InitializeComponent(); } protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); noteVm = new NoteViewModel(); if (e.Parameter is Note note && noteVm is not null) { noteVm.InitializeForExistingNote(note); } } } }Os eventos para
SaveeDeletesão removidos, pois os botões agora vinculam-se diretamente aos comandos no ViewModel. ONoteViewModelé instanciado no métodoOnNavigatedTo(). Se umNoteparâmetro for passado, ele inicializará o ViewModel com os dados de anotação existentes.
Saiba mais nos documentos:
Windows developer