Windows-gegevensbinding en MVVM

Model-View-ViewModel (MVVM) is een architectuurontwerppatroon voor de gebruikersinterface waarmee de gebruikersinterface en niet-UI-code worden losgekoppeld. Meer informatie over hoe MVVM losse koppeling mogelijk maakt met behulp van gegevensbinding in XAML om de gebruikersinterface en gegevens te synchroniseren, de onderhoudbaarheid te verbeteren en afhankelijkheden te verminderen.

Omdat er losse koppeling wordt geboden, vermindert het gebruik van gegevensbinding harde afhankelijkheden tussen verschillende soorten code. Deze aanpak maakt het eenvoudiger om afzonderlijke code-eenheden (methoden, klassen, besturingselementen enzovoort) te wijzigen zonder onbedoelde bijwerkingen in andere eenheden te veroorzaken. Deze ontkoppeling is een voorbeeld van de scheiding van zorgen, wat een belangrijk concept is in veel ontwerppatronen.

Tip

Wanneer gebruikt u MVVM: Gebruik MVVM voor apps met complexe gegevensstromen, meerdere schermen of door het team ontwikkelde codebases. Voor eenvoudige hulpprogramma's of prototypen met één pagina is code-behind acceptabel. U kunt MVVM stapsgewijs gebruiken naarmate de complexiteit toeneemt. Als uw app moduletestbare bedrijfslogica heeft, maakt MVVM die logica testbaar zonder een actieve gebruikersinterface.

Voordelen van MVVM

Het ontkoppelen van uw code heeft veel voordelen, waaronder:

  • Een iteratieve, verkennende coderingsstijl inschakelen. Verandering die geïsoleerd is, is minder riskant en gemakkelijker te experimenteren.
  • Het testen van eenheden vereenvoudigen. U kunt code-eenheden testen die afzonderlijk en buiten productieomgevingen van elkaar zijn geïsoleerd.
  • Ondersteuning voor teamsamenwerking. Afzonderlijke personen of teams kunnen losgekoppelde code ontwikkelen die voldoet aan goed ontworpen interfaces en deze later integreren.
  • De onderhoudbaarheid verbeteren. Het oplossen van fouten in losgekoppelde code veroorzaakt minder waarschijnlijk regressies in andere code.

In tegenstelling tot MVVM maakt een app met een conventionelere 'code-behind'-structuur meestal gebruik van gegevensbinding voor gegevens die alleen worden weergegeven. Het reageert op gebruikersinvoer door gebeurtenissen die rechtstreeks worden weergegeven door besturingselementen te verwerken. De event handlers worden geïmplementeerd in code-behind-bestanden (zoals MainWindow.xaml.cs) en zijn vaak nauw verbonden met de controls. Ze bevatten doorgaans code waarmee de gebruikersinterface rechtstreeks wordt bewerkt. Deze structuur maakt het moeilijk of onmogelijk om een besturingselement te vervangen zonder dat u de code voor het afhandelen van gebeurtenissen hoeft bij te werken. Met deze architectuur verzamelen code-behind-bestanden vaak code die niet rechtstreeks is gerelateerd aan de gebruikersinterface, zoals code voor databasetoegang, die uiteindelijk wordt gedupliceerd en gewijzigd voor gebruik met andere vensters.

App-lagen

Wanneer u het MVVM-patroon gebruikt, verdeelt u uw app in de volgende lagen:

  • De modellaag definieert de typen die uw bedrijfsgegevens vertegenwoordigen. Deze laag bevat alles wat nodig is om het kern-app-domein te modelleren en bevat vaak kern-app-logica. Deze laag is volledig onafhankelijk van de weergave- en weergavemodellagen en bevindt zich vaak gedeeltelijk in de cloud. Gezien een volledig geïmplementeerde modellaag kunt u meerdere verschillende client-apps maken als u kiest, zoals Windows App SDK en web-apps die met dezelfde onderliggende gegevens werken.
  • De weergavelaag definieert de gebruikersinterface met behulp van XAML-markeringen. De markering bevat expressies voor gegevensbinding (zoals x:Bind) die de verbinding tussen specifieke UI-onderdelen en verschillende leden van het weergavemodel en model definiëren. Soms kunt u code-behind-bestanden gebruiken als onderdeel van de weergavelaag om extra code te bevatten die nodig is om de gebruikersinterface aan te passen of te manipuleren of om gegevens te extraheren uit argumenten voor gebeurtenis-handler voordat u een weergavemodelmethode aanroept waarmee het werk wordt uitgevoerd.
  • De weergavemodellaag biedt gegevensbindingsdoelen voor de weergave. In veel gevallen maakt het weergavemodel het model rechtstreeks beschikbaar of biedt het eigenschappen die specifieke modelleden omwikkelen. Het weergavemodel kan ook leden definiëren voor het bijhouden van gegevens die relevant zijn voor de gebruikersinterface, maar niet voor het model, zoals de weergavevolgorde van een lijst met items. Het weergavemodel fungeert ook als een integratiepunt met andere services, zoals code voor gegevenstoegang. Voor eenvoudige projecten hebt u mogelijk geen afzonderlijke modellaag nodig, maar alleen een weergavemodel dat alle gegevens bevat die u nodig hebt.

Basic en geavanceerde MVVM

Net als bij elk ontwerppatroon is er meer dan één manier om MVVM te implementeren en worden veel verschillende technieken beschouwd als onderdeel van MVVM. Daarom zijn er verschillende MVVM-frameworks van derden die de verschillende XAML-platformen ondersteunen, waaronder Windows App SDK. Deze frameworks omvatten echter over het algemeen meerdere services voor het implementeren van ontkoppelde architectuur, waardoor de exacte definitie van MVVM enigszins dubbelzinnig is.

Hoewel geavanceerde MVVM-frameworks zeer nuttig kunnen zijn, met name voor projecten op ondernemingsniveau, zijn er meestal kosten verbonden aan het aannemen van een bepaald patroon of een bepaalde techniek, en de voordelen zijn niet altijd duidelijk, afhankelijk van de schaal en grootte van uw project. Gelukkig kunt u alleen die technieken gebruiken die een duidelijk en tastbaar voordeel bieden en anderen negeren totdat u ze nodig hebt.

U kunt met name veel voordeel krijgen door de volledige kracht van gegevensbinding te begrijpen en toe te passen en uw app-logica te scheiden in de lagen die eerder zijn beschreven. Dit kan worden bereikt met behulp van alleen de mogelijkheden van de Windows App SDK en zonder externe frameworks te gebruiken. Met name de markupextensie {x:Bind} maakt gegevensbinding eenvoudiger en beter presterend dan in eerdere XAML-platforms, waardoor veel van de standaardcode die eerder is vereist, niet meer nodig is.

Zie de CommunityToolkit MVVM-bibliotheek , die basisklassen biedt, zoals ObservableObject en RelayCommand, samen met brongeneratoren (via [ObservableProperty] en [RelayCommand] kenmerken) die standaardcode elimineren voor aanvullende richtlijnen voor het gebruik van MVVM. De WinUI Gallery demonstreert ook gegevensbinding en MVVM-patronen met WinUI 3.

Voorbeeld communitytoolkit.Mvvm

In het volgende voorbeeld ziet u een volledig ViewModel met behulp van CommunityToolkit.Mvvm 8.x-brongeneratoren. Het [ObservableProperty] kenmerk genereert de eigenschap en wijzigingsmelding en [RelayCommand] genereert de ICommand implementatie:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

public partial class CustomerViewModel : ObservableObject
{
    private readonly ICustomerService _customerService;

    public CustomerViewModel(ICustomerService customerService)
    {
        _customerService = customerService;
    }

    [ObservableProperty]
    [NotifyCanExecuteChangedFor(nameof(SaveCommand))]
    private string _name = string.Empty;

    [ObservableProperty]
    private bool _isBusy;

    [RelayCommand(CanExecute = nameof(CanSave))]
    private async Task SaveAsync()
    {
        IsBusy = true;
        await _customerService.SaveAsync(Name);
        IsBusy = false;
    }

    private bool CanSave() => !string.IsNullOrWhiteSpace(Name);
}

Koppel dit ViewModel aan een pagina met behulp van {x:Bind}:

<Page x:Class="MyApp.Views.CustomerPage"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel>
        <TextBox Text="{x:Bind ViewModel.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        <Button Content="Save" Command="{x:Bind ViewModel.SaveCommand}" />
        <ProgressRing IsActive="{x:Bind ViewModel.IsBusy, Mode=OneWay}" />
    </StackPanel>
</Page>

De code-behind van de pagina stelt de eigenschap ViewModel beschikbaar waarnaar {x:Bind} verwijst:

// CustomerPage.xaml.cs
public sealed partial class CustomerPage : Page
{
    public CustomerViewModel ViewModel { get; }

    public CustomerPage()
    {
        // Resolve via DI; see Architecture patterns for WinUI 3 desktop apps
        // for how to configure App.GetService<T>() with Microsoft.Extensions.DependencyInjection.
        ViewModel = App.GetService<CustomerViewModel>();
        InitializeComponent();
    }
}

Zie Architectuurpatronen voor WinUI 3-desktop-apps voor hulp bij het combineren van MVVM met afhankelijkheidsinjectie, configuratie en ondernemingspatronen.

Zie ook

Onderwerpen

Uitgebreide gegevensbinding
Markeringsextensie {x:Bind}
Prestatietips voor MVVM voor WinUI-apps
Architectuurpatronen voor WinUI 3-bureaublad-apps

WinUI 3 en MVVM-bronnen

Documentatie voor CommunityToolkit MVVM
WinUI Gallery - voorbeelden van gegevensbinding
Template Studio voor WinUI