Aracılığıyla paylaş


Bağımlılık enjeksiyonu ekle

Bağımlılık ekleme (DI), ViewModel'lerinizin ve hizmetlerinizin yaşam döngüsünü yönetmenize yardımcı olur. Kodunuzu test edilebilir hale getirir ve bakımını kolaylaştırır. Bu adımda, uygulamanızda DI'yi yapılandıracak ve modellerinizi dosya işlemleri için bir dosya hizmeti kullanacak şekilde güncelleştireceksiniz.

.NET bağımlılık ekleme çerçevesi hakkında daha fazla arka plan için bkz. .NET bağımlılık ekleme ve .NET'te bağımlılık eklemeyi kullanma öğreticisi .

Microsoft.Extensions paketlerini yükleme

Projelerinize DI desteği ekleyin.

  1. Microsoft.Extensions.DependencyInjection hem de WinUINotes.Bus projelerine yükleyin:

    dotnet add WinUINotes package Microsoft.Extensions.DependencyInjection
    dotnet add WinUINotes.Bus package Microsoft.Extensions.DependencyInjection
    

Dosya hizmeti arabirimi ve uygulaması oluşturma

  1. WinUINotes.Bus projesinde Services adlı yeni bir klasör oluşturun.

  2. Arabirim dosyası IFileService.csekleyin:

    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Windows.Storage;
    
    namespace WinUINotes.Services
    {
        public interface IFileService
        {
            Task<IReadOnlyList<IStorageItem>> GetStorageItemsAsync();
            Task<IReadOnlyList<IStorageItem>> GetStorageItemsAsync(IStorageFolder storageFolder);
            Task<string> GetTextFromFileAsync(IStorageFile file);
            Task CreateOrUpdateFileAsync(string filename, string contents);
            Task DeleteFileAsync(string filename);
            bool FileExists(string filename);
            IStorageFolder GetLocalFolder();
        }
    }
    

    Dosya hizmeti arabirimi, dosya işlemleri için yöntemleri tanımlar. ViewModel ve Model'lerdeki dosya işleme ayrıntılarını soyutlar. Parametrelerin ve dönüş değerlerinin tümü temel .NET türleri veya arabirimleridir. Bu tasarım, birim testlerinde hizmetin kolayca taklit edilmesini veya değiştirilebilmesini sağlayarak gevşek bağlama ve test edilebilirliği teşvik eder.

  3. Uygulama dosyasını WindowsFileService.csekleyin:

    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Windows.Storage;
    
    namespace WinUINotes.Services
    {
        public class WindowsFileService : IFileService
        {
             public StorageFolder storageFolder;
    
             public WindowsFileService(IStorageFolder storageFolder)
             {
                 this.storageFolder = (StorageFolder)storageFolder;
    
                 if (this.storageFolder is null)
                 {
                     throw new ArgumentException("storageFolder must be of type StorageFolder", nameof(storageFolder));
                 }
             }
    
             public async Task CreateOrUpdateFileAsync(string filename, string contents)
             {
                 // Save the note to a file.
                 StorageFile storageFile = (StorageFile)await storageFolder.TryGetItemAsync(filename);
                 if (storageFile is null)
                 {
                     storageFile = await storageFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
                 }
                 await FileIO.WriteTextAsync(storageFile, contents);
             }
    
         public async Task DeleteFileAsync(string filename)
         {
             // Delete the note from the file system.
             StorageFile storageFile = (StorageFile)await storageFolder.TryGetItemAsync(filename);
             if (storageFile is not null)
             {
                 await storageFile.DeleteAsync();
             }
         }
    
         public bool FileExists(string filename)
         {
             StorageFile storageFile = (StorageFile)storageFolder.TryGetItemAsync(filename).AsTask().Result;
             return storageFile is not null;
         }
    
         public IStorageFolder GetLocalFolder()
         {
             return storageFolder;
         }
    
         public async Task<IReadOnlyList<IStorageItem>> GetStorageItemsAsync()
         {
             return await storageFolder.GetItemsAsync();
         }
    
         public async Task<IReadOnlyList<IStorageItem>> GetStorageItemsAsync(IStorageFolder folder)
         {
             return await folder.GetItemsAsync();
         }
    
         public async Task<string> GetTextFromFileAsync(IStorageFile file)
         {
             return await FileIO.ReadTextAsync(file);
         }
        }
    }
    

Uygulama, WindowsFileService Windows Çalışma Zamanı (WinRT) ve .NET depolama API'lerini kullanarak somut dosya işlemleri sağlar:

  • Oluşturucu ekleme: Hizmet, oluşturucusunda bir IStorageFolder kabul eder. Bu yaklaşım, hizmetin örneğini oluştururken depolama konumunu yapılandırmanıza olanak tanır. Bu yaklaşım, hizmeti esnek ve test edilebilir hale getirir.
  • CreateOrUpdateFileAsync(): Bu yöntem, bir dosyanın zaten var olup olmadığını denetlemek için kullanır TryGetItemAsync() . Varsa, yöntemi mevcut dosyayı güncelleştirir. Aksi takdirde, CreateFileAsync() kullanarak yeni bir dosya oluşturur. Bu yaklaşım hem oluşturma hem de güncelleştirme senaryolarını tek bir yöntemle işler.
  • DeleteFileAsync(): Bir dosyayı silmeden önce, bu yöntem kullanarak TryGetItemAsync()dosyanın mevcut olduğunu doğrular. Bu kontrol, var olmayan dosyaları silmeye çalışırken hataların oluşmasını engeller.
  • FileExists(): Bu eşzamanlı yöntem, eşzamansız TryGetItemAsync() öğesini çağırarak ve .Result ile engelleyerek dosya varlığını denetler. Bu yaklaşım genellikle önerilmese de, burada ViewModel'deki doğrulama yönteminin eşzamanlı olması gerektiği için CanDelete() desteklemek amacıyla kullanılır.
  • Depolama öğesi yöntemleri: GetStorageItemsAsync() ve GetTextFromFileAsync() yöntemleri, WinRT depolama API'lerini kullanarak dosyalara ve içeriklerine erişim sağlar. Bu yöntemler, Modellerin notları yüklemesine ve numaralandırmasına olanak tanır.

Arabirimini uygulayarak IFileService bu sınıfı test için sahte bir uygulamayla veya gerekirse farklı bir depolama sağlayıcısıyla kolayca değiştirebilirsiniz.

Belgelerde daha fazla bilgi edinin:

App.xaml.cs'de bağımlılık eklemeyi yapılandırma

Dosya hizmetini kullanmak için modelleri ve ViewModel'leri güncelleştirmeden önce, hizmetin çözümlenebilmesi ve oluşturuculara eklenebilmesi için bağımlılık eklemeyi yapılandırın.

DI kapsayıcısını App.xaml.cs ayarlamak için dosyayı güncelleştirin:

using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.UI.Xaml;
using WinUINotes.ViewModels;

namespace WinUINotes;

public partial class App : Application
{
    private readonly IServiceProvider _serviceProvider;

    public App()
    {
        Services = ConfigureServices();
        this.InitializeComponent();
    }

    private static IServiceProvider ConfigureServices()
    {
        var services = new ServiceCollection();

        // Services
        services.AddSingleton<Services.IFileService>(x =>
            ActivatorUtilities.CreateInstance<Services.WindowsFileService>(x,
                            Windows.Storage.ApplicationData.Current.LocalFolder)
        );

        // ViewModels
        services.AddTransient<AllNotesViewModel>();
        services.AddTransient<NoteViewModel>();

        return services.BuildServiceProvider();
    }

    protected override void OnLaunched(LaunchActivatedEventArgs args)
    {
        m_window = new MainWindow();
        m_window.Activate();
    }

    public IServiceProvider Services { get; }

    private Window? m_window;

    public new static App Current => (App)Application.Current;
}

Bu yapılandırma, bağımlılık ekleme kapsayıcısını gerekli tüm hizmetlerle ayarlar:

  • ConfigureServices() method: Hizmet koleksiyonunu oluşturan ve yapılandıran statik bir yöntem. Bu yöntemin ayrılması yapılandırmayı daha sürdürülebilir ve test etmek daha kolay hale getirir.
  • Services property: IServiceProvider öğesini barındıran bir örnek özelliği. Oluşturucu, çağırarak ConfigureServices()bu özelliği ayarlar.
  • App.Current statik özellik: Modellerin veya diğer sınıfların hizmet sağlayıcısına erişmesi gerektiğinde yararlı olan geçerli App örneğe kolay erişim sağlar.
  • IFileService kaydı: ApplicationData.Current.LocalFolder parametresiyle bir WindowsFileService örneği oluşturmak için ActivatorUtilities.CreateInstance kullanılır. Bu yaklaşım, oluşturucu parametresinin kayıt esnasında eklenmesini sağlar. Dosya işlemleri durumsuz olduğundan ve uygulama genelinde tek bir örnek paylaşılabildiğinden, hizmeti singleton olarak kaydedin.
  • ViewModels kaydı: Her iki ViewModel'i de geçici olarak kaydedin; başka bir deyişle her istekte yeni bir örnek oluşturulur. Bu yaklaşım, her sayfanın temiz durumda kendi ViewModel örneğini almasını sağlar.

Modeller ve diğer sınıflar, gerektiğinde kayıtlı hizmetleri almak için App.Current.Services.GetService() aracılığıyla hizmet sağlayıcısına erişebilir.

Belgelerde daha fazla bilgi edinin:

Dosya hizmetini kullanmak için modelleri güncelleştirme

Artık dosya hizmeti bağımlılık ekleme yoluyla kullanılabilir olduğuna göre, model sınıflarını bunu kullanacak şekilde güncelleştirin. Modeller dosya hizmetini alır ve tüm dosya işlemleri için kullanır.

Not modelini güncelleştirme

Note dosya hizmetini kabul etmek için sınıfını güncelleştirin ve kaydetme, silme ve dosya varlığı işlemleri için kullanın:

using System;
using System.Threading.Tasks;
using WinUINotes.Services;

namespace WinUINotes.Models;

public class Note
{
    private IFileService fileService;
    public string Filename { get; set; } = string.Empty;
    public string Text { get; set; } = string.Empty;
    public DateTime Date { get; set; } = DateTime.Now;

    public Note(IFileService fileService)
    {
        Filename = "notes" + DateTime.Now.ToBinary().ToString() + ".txt";
        this.fileService = fileService;
    }

    public async Task SaveAsync()
    {
        await fileService.CreateOrUpdateFileAsync(Filename, Text);
    }

    public async Task DeleteAsync()
    {
        await fileService.DeleteFileAsync(Filename);
    }

    public bool NoteFileExists()
    {
        return fileService.FileExists(Filename);
    }
}

Model Note artık constructor enjeksiyonu yoluyla dosya hizmetini alır.

  • Oluşturucu: Bağımlılığı açık ve gerekli hale getirerek bir IFileService parametreyi kabul eder. Bu tasarım test edilebilirliği teşvik eder ve modelin ihtiyaç duyduğu dosya hizmetine her zaman erişmesini sağlar.
  • Dosya adı oluşturma: Oluşturucu, geçerli zaman damgasını kullanarak otomatik olarak benzersiz bir dosya adı oluşturur ve her notta ayrı bir dosya adı olmasını sağlar.
  • Dosya işlemleri: SaveAsync(), DeleteAsync(), ve NoteFileExists() yöntemlerinin tümü, enjekte edilen dosya hizmetine yönlendirilerek modelin dosya G/Ç ayrıntılarını uygulamayarak koordinasyona odaklanmasını sağlar.

Bu yaklaşım, modelin test edilebilirliği artıran ve bağımlılıkları net hale getiren hizmet bulucu desenini (doğrudan erişim App.Services ) kullanma gereksinimini ortadan kaldırır.

AllNotes modelini güncelleştirme

AllNotes dosya hizmetini kullanarak depolama alanından not yüklemek için sınıfını güncelleştirin:

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using Windows.Storage;
using WinUINotes.Services;

namespace WinUINotes.Models;

public class AllNotes
{
        private IFileService fileService;
        public ObservableCollection<Note> Notes { get; set; } = [];

        public AllNotes(IFileService fileService)
        {
            this.fileService = fileService;
        }

        public async Task LoadNotes()
        {
            Notes.Clear();
            await GetFilesInFolderAsync(fileService.GetLocalFolder());
        }

        private async Task GetFilesInFolderAsync(IStorageFolder folder)
        {
            // Each StorageItem can be either a folder or a file.
            IReadOnlyList<IStorageItem> storageItems =
                                        await fileService.GetStorageItemsAsync(folder);
            foreach (IStorageItem item in storageItems)
            {
                if (item.IsOfType(StorageItemTypes.Folder))
                {
                    // Recursively get items from subfolders.
                    await GetFilesInFolderAsync((IStorageFolder)item);
                }
                else if (item.IsOfType(StorageItemTypes.File))
                {
                    IStorageFile file = (IStorageFile)item;
                    Note note = new(fileService)
                    {
                        Filename = file.Name,
                        Text = await fileService.GetTextFromFileAsync(file),
                        Date = file.DateCreated.DateTime
                    };
                    Notes.Add(note);
                }
            }
        }
}

Modeli, Note model gibi AllNotes oluşturucu ekleme yoluyla dosya hizmetini alır. Bu sınıf, WinUINotes.Bus projesinde olduğundan, WinUINotes projesinden App.Current.Services'e erişemez (proje başvurusu kısıtlamaları nedeniyle).

yöntemi, LoadNotes() yerel depolama klasöründeki ve alt klasörlerindeki tüm dosyaları yinelemeli olarak numaralandırmak için özel GetFilesInFolderAsync() yöntemi çağırır. Her depolama öğesi için:

  1. Bu bir klasörse, yöntemi özyinelemeli olarak kendisini çağırarak klasörün içeriğini işler
  2. Bu bir dosyaysa, dosya hizmetinin eklendiği yeni Note bir örnek oluşturur
  3. Notun Filename, dosyanın adı olarak ayarlanır
  4. Not dosyanın içeriği okunarak Text ve GetTextFromFileAsync() kullanılarak doldurulur.
  5. Notun Date, dosyanın oluşturulma tarihine ayarlanır
  6. Not gözlemlenebilir koleksiyona Notes eklenir

Bu yaklaşım, depolama alanından yüklenen tüm notların gelecekte kaydetme ve silme işlemleri için ihtiyaç duydukları dosya hizmetine erişmesini sağlar.

ViewModels'i dosya hizmetini kullanacak şekilde güncelleştirme

Modeller artık dosya hizmetini kullanıyorken ViewModel'leri güncelleştirmeniz gerekir. Ancak, modeller dosya işlemlerini doğrudan işlediğinden, ViewModel'ler öncelikle modelleri düzenlemeye ve gözlemlenebilir özellikleri yönetmeye odaklanır.

AllNotesViewModel'i güncelleştirme

AllNotesViewModel güncelleştirilmiş AllNotes modelle çalışacak şekilde güncelleştirin:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using WinUINotes.Models;
using WinUINotes.Services;

namespace WinUINotes.ViewModels
{
    public partial class AllNotesViewModel : ObservableObject
    {
        private readonly AllNotes allNotes;

        [ObservableProperty]
        private ObservableCollection<Note> notes;

        public AllNotesViewModel(IFileService fileService)
        {
            allNotes = new AllNotes(fileService);
            notes = new ObservableCollection<Note>();
        }

        [RelayCommand]
        public async Task LoadAsync()
        {
            await allNotes.LoadNotes();
            Notes.Clear();
            foreach (var note in allNotes.Notes)
            {
                Notes.Add(note);
            }
        }
    }
}

2. Adım'dan bu yana ne değişti?

Anahtar değişikliği, parametrenin IFileService oluşturucuya eklenmesidir. 2. Adımda, parametresiz bir oluşturucu (allNotes = new AllNotes()) ile ViewModel AllNotes örneklendi. Artık model, dosya hizmetinin işlemlerini gerçekleştirmesini gerektirdiğine göre, ViewModel, oluşturucu enjeksiyonu aracılığıyla IFileService öğesini alır ve modele geçirir.

Bu değişiklik doğru bağımlılık akışını korur. Dosya hizmeti en üst düzeye (ViewModel) eklenir ve modele doğru akar. ViewModel, dosyaların nasıl yüklendiğine ilişkin uygulama ayrıntılarını bilmenize gerek kalmadan yükleme işlemini koordine etmeye ve gözlemlenebilir Notes koleksiyonu modelin verileriyle eşitlenmiş tutmaya odaklanmaya devam eder.

NoteViewModel'i Güncelleştirme

NoteViewModel dosya hizmetini eklemek için öğesini güncelleştirin ve MVVM Toolkit'in mesajlaşma sistemini kullanın:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using System;
using System.Threading.Tasks;
using WinUINotes.Models;
using WinUINotes.Services;

namespace WinUINotes.ViewModels
{
    public partial class NoteViewModel : ObservableObject
    {
        private Note note;
        private IFileService fileService;

        [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(IFileService fileService)
        {
            this.fileService = fileService;
            this.note = new Note(fileService);
            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(fileService);
            // Send a message from some other module
            WeakReferenceMessenger.Default.Send(new NoteDeletedMessage(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();
        }
    }
}

2. Adım'dan bu yana ne değişti?

Çeşitli önemli değişiklikler bağımlılık eklemeyi ve viewmodeller arası iletişimi destekler:

  1. Dosya hizmeti ekleme: Oluşturucu artık parametre olarak kabul eder IFileService ve bunu bir alanda depolar. Bu hizmet, yeni örnekler oluşturulurken Note modeline geçirilir ve tüm notların dosya işlemlerini gerçekleştirebilmesini temin eder.

  2. WeakReferenceMessenger: Delete() yöntemi artık bir notu sildikten sonra WeakReferenceMessenger.Default.Send() kullanarak NoteDeletedMessage yayımlar. Bu yaklaşım, ViewModel'ler arasında gevşek bağlantı sağlar. Uygulamanın diğer bölümleri (örneğin NotePage) bu iletiyi dinleyebilir ve bunlara doğrudan başvuru gerekmeden NoteViewModel uygun şekilde yanıt verebilir (örneğin, yenilenen notlar listesine geri giderek).

WeakReferenceMessenger, MVVM Araç Seti'nin zayıf başvurular kullanarak bellek sızıntılarını önleyen önemli bir özelliğidir. Bileşenler, çöp toplamayı engellemeyecek güçlü referanslar oluşturmadan iletilere abone olabilir.

Belgelerde daha fazla bilgi edinin:

NoteDeletedMessage sınıfını oluşturma

WeakReferenceMessenger bileşenler arasında göndermek için bir ileti sınıfına ihtiyaç duyar. Not silme olayını göstermek için yeni bir sınıf oluşturun:

  1. WinUINotes.Bus projesinde yeni bir sınıf dosyası NoteDeletedMessage.csekleyin:

    using CommunityToolkit.Mvvm.Messaging.Messages;
    using WinUINotes.Models;
    
    namespace WinUINotes
    {
        public class NoteDeletedMessage : ValueChangedMessage<Note>
        {
            public NoteDeletedMessage(Note note) : base(note)
            {
            }
        }
    }
    

Bu ileti sınıfı, değer değişikliği bildirimlerini taşımak için MVVM Araç Seti tarafından sağlanan özel bir ileti türü olan öğesinden ValueChangedMessage<Note>devralır. Oluşturucu, bir Note kabul eder ve bunu temel sınıfa geçirerek Value özelliği aracılığıyla ileti alıcılarının kullanımına sunar. Bu iletiyi gönderdiğinde NoteViewModel , abone NoteDeletedMessage olan tüm bileşenler bu iletiyi alır ve silinen nota Value özelliği aracılığıyla erişebilir.

MVVM Araç Seti'nde mesajlaşma nasıl çalışır?

  1. Gönderen: NoteViewModel.Delete() yöntemi iletiyi kullanarak WeakReferenceMessenger.Default.Send(new NoteDeletedMessage(note))gönderir.
  2. Alıcı: NotePage gibi sayfalar, mesajları almak için IRecipient<NoteDeletedMessage> uygular ve haberciye kaydolur. İleti alındığında, sayfa tüm notlar listesine geri gidebilir.
  3. Gevşek bağlantı: Gönderenin kimin (varsa) dinlediğini bilmesi gerekmez. Alıcının doğrudan gönderene başvurması gerekmez. Bu kurulum, bileşenlerinizi bağımsız ve test edilebilir tutar.

Zayıf başvuru yaklaşımı, bir bileşenin atık toplanması durumunda ileti aboneliğinin bellek sızıntılarına neden olmadan otomatik olarak temizlendiğini gösterir.

Bağımlılık ekleme özelliğini kullanmak için sayfaları güncelleştirme

Sayfa oluşturucularınızı VIEWModel'leri DI aracılığıyla alacak şekilde güncelleştirin.

Güncelle AllNotesPage.xaml.cs

using Microsoft.Extensions.DependencyInjection;
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 = App.Current.Services.GetService<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();
            }
        }
    }
}

2. Adım'dan bu yana ne değişti?

Uygulama artık AllNotesViewModel, doğrudan new AllNotesViewModel() ile oluşturmak yerine App.Current.Services.GetService<AllNotesViewModel>() kullanarak bağımlılık enjeksiyonu kapsayıcısından alıyor. Bu yaklaşımın çeşitli avantajları vardır:

  1. Otomatik bağımlılık çözümlemesi: DI kapsayıcısı, oluşturucusunda IFileService gereken bağımlılığı AllNotesViewModel otomatik olarak sağlar.
  2. Yaşam döngüsü yönetimi: DI kapsayıcısı, ViewModel'in yaşam döngüsünü nasıl kaydedildiği (bu örnekte geçici olarak yeni bir örnek sağlayan) göre yönetir.
  3. Test edilebilirlik: Bu düzen, testlerdeki uygulamaları veya sahte bağımlılıkları değiştirmeyi kolaylaştırır.
  4. Bakım: ViewModel'in bağımlılıkları gelecekte değişirse, ViewModel'in oluşturulduğu her yerde değil, yalnızca DI yapılandırmasını güncelleştirmeniz gerekir.

Kodun geri kalanı aynı kalır. OnNavigatedTo() yöntemi, kullanıcı bu sayfaya gittiği zaman, not listesini yenilemek için yine de LoadAsync() çağırır.

Güncelleme NotePage.xaml.cs

using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.DependencyInjection;
using 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();
        }

        public void RegisterForDeleteMessages()
        {
            WeakReferenceMessenger.Default.Register<NoteDeletedMessage>(this, (r, m) =>
            {
                if (Frame.CanGoBack)
                {
                    Frame.GoBack();
                }
            });
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            noteVm = App.Current.Services.GetService<NoteViewModel>();
            RegisterForDeleteMessages();

            if (e.Parameter is Note note && noteVm is not null)
            {
                noteVm.InitializeForExistingNote(note);
            }
        }
    }
}

2. Adım'dan bu yana ne değişti?

Çeşitli önemli değişiklikler bağımlılık ekleme ve mesajlaşma özelliklerini tümleştirir:

  1. DI kapsayıcısından ViewModel: NoteViewModel artık doğrudan örneklenmek yerine OnNavigatedTo() yönteminde App.Current.Services.GetService<NoteViewModel>() kullanılarak bağımlılık ekleme kapsayıcısından alınıyor. Bu yaklaşım, ViewModel'in gerekli IFileService bağımlılığını otomatik olarak almasını sağlar.
  2. İleti kaydı: Yeni RegisterForDeleteMessages() yöntem, WeakReferenceMessenger kullanarak NoteDeletedMessage öğesine abone olur. Bir not silindiğinde (NoteViewModel.Delete() yöntemiyle), bu sayfa mesajı alır ve Frame.GoBack() kullanarak tüm notlar listesine geri döner.
  3. Mesajlaşma düzeni: Bu desen, MVVM Toolkit'in mesajlaşma sistemi tarafından etkinleştirilen gevşek bağlamayı gösterir. öğesinin NoteViewModel gezinti veya sayfa yapısı hakkında bilgi sahibi olması gerekmez; yalnızca bir not silindiğinde bir ileti gönderir ve sayfa gezinti yanıtını bağımsız olarak işler.
  4. Yaşam döngüsü zamanlaması: ViewModel örneği oluşturulur ve içinde ileti kaydı gerçekleşir OnNavigatedTo()ve sayfa etkin olduğunda her şeyin düzgün bir şekilde başlatılmasını sağlar.

Bu desen, kaygıları etkili bir şekilde ayırır: ViewModel iş mantığına ve veri işlemlerine odaklanırken, sayfa gezinti gibi kullanıcı arabirimine özgü endişeleri işler.