Vad är MVVM?

Slutförd

.NET MAUI-appar som inte använder Model-View-ViewModel (MVVM) har vanligtvis mer kod i sina kod bakom filer. Kod bakom filerna i .NET MAUI följer det här mönstret: {something}.xaml.cs. De flesta kod i filen bakom koden styr vanligtvis användargränssnittets beteende. Användargränssnittsbeteendet kan innehålla allt som händer med användargränssnittet, till exempel att ändra en färg eller text. Och det kan innehålla allt som händer på grund av användargränssnittet, inklusive knappklickshanterare.

Ett problem med den här metoden är att det är svårt att skriva enhetstester mot kod bakom filer. Kod bakom filer förutsätter ofta ett programtillstånd som skapas genom att parsa XAML eller till och med skapas av andra sidor. Dessa villkor är svåra att hantera i en enhetstestkörare som kanske inte ens körs på en mobil enhet, för att inte tala om med ett användargränssnitt. Enhetstester kan därför sällan testa användargränssnittsbeteenden i dessa filer.

Men det är här MVVM-mönstret är användbart. När det används korrekt löser MVVM-mönstret dessa problem genom att flytta de flesta UI-beteendelogik till enhetstestbara klasser som kallas viewmodels. MVVM-mönstret används oftast med ramverk som stöder databindning. Med .NET MAUI kan du databinda varje UI-element till ett viewmodel och eliminera eller nästan eliminera kod i en vy eller bakomliggande kod.

Vilka är delarna i ett MVVM-program?

viewmodel Även om är den unika delen av MVVM-mönstret definierar mönstret även en modelldel och en vydel. Definitionerna av dessa delar överensstämmer med några andra vanliga mönster, till exempel en MVC (Model-View-Controller).

Vad är en modell?

I ett MVVM-program används termmodellen för att ange dina affärsdata och åtgärder. Modellen engagerar sig inte i appens användarpresentation.

En användbar regel för att avgöra vilken kod som hör hemma i modellen är att den ska vara portabel på olika plattformar. Från en mobilapp till ett webbgränssnitt eller till och med ett kommandoradsprogram med samma modell i alla instanser. Det är inte relaterat till hur informationen visas för användaren.

När du tänker på HR-programmet från vårt scenario kan modellen innehålla en Employee klass och en Department klass som innehåller data och logik om dessa entiteter. Modellen kan också innehålla saker som en EmployeeRepository klass som innehåller beständighetslogik. Vissa andra mönster för programvarudesign skulle betrakta saker som lagringsplatser som separata från modellen. Men i samband med MVVM refererar vi ofta till affärslogik eller affärsdata som en del av modellen.

Här är två exempel på en modell i C#:

public class Employee
{
    public int Id { get; }
    public string Name { get; set; }
    public Employee Supervisor { get; set; }
    public DateTime HireDate { get; set; }
    public void ClockIn() { ... }
}

public class EmployeeRepository
{
    public IList<Employee> QueryEmployees() { ... }
    ...
}

Vad är en vy?

Visningskoden styr saker som direkt interagerar med användaren, till exempel kontroller som knappar och inmatningsfält, samt andra rent visuella element som teman, formatmallar och teckensnitt.

I .NET MAUI behöver du inte skriva någon C#-kod för att generera en vy själv. I stället definierar du ofta dina vyer efter XAML-filer. Det finns situationer som kräver en anpassad användarkontroll, där du skapar en egen vy via kod.

Vad är en viewmodel?

Det för oss tillbaka till viewmodel. viewmodel är mellanhanden mellan vår affärslogik (modell) och våra vyer (UI).

Ett diagram som illustrerar hur en vymodell är en mellanhand mellan en modell och en vy.

Tänk på vad en viewmodel kan göra för HR-programmet. Anta att det finns en vy som visar en anställds tillgängliga semestertid och du vill att semestersaldot ska visas som "2 veckor, 3 dagar, 4 timmar". Men affärslogik i modellen ger samma värde som 13,5 dagar, ett decimaltal som representerar det totala antalet dagar under en 8-timmars arbetsdag. Objektmodellen kan se ut som i följande lista:

  • Modell – klassen Employee , som innehåller en metod:

    public decimal GetVacationBalanceInDays()
    {
        //Some math that calculates current vacation balance
        ...
    }
    
  • ViewModel – en EmployeeViewModel klass som har en egenskap som den här:

    public class EmployeeViewModel
    {
        private Employee _model;
    
        public string FormattedVacationBalance
        {
            get
            {
                decimal vacationBalance = _model.GetVacationBalanceInDays();
                ... // Some logic to format and return the string as "X weeks, Y days, Z hours"
            }
        }
    }
    
  • Visa – en XAML-sida som innehåller en enda etikett och en stängningsknapp. Etiketten har en bindning till viewmodelegenskapen 's:

    <Label Text="{Binding FormattedVacationBalance}" />
    

    Sedan behöver BindingContext du bara för sidan inställd på en instans av EmployeeViewModel.

I det här exemplet innehåller modellen affärslogik. Den här logiken är inte bunden till en visuell visning eller enhet. Du kan använda samma logik för en handhållen enhet eller stationär dator. Vyn vet ingenting om affärslogik. Vykontrollerna, som etiketten, vet hur du hämtar text på skärmen, men bryr sig inte om det är ett semestersaldo eller en slumpmässig sträng. De viewmodel vet lite om båda världarna, så det kan fungera som en mellanhand.

Det som är intressant är hur det viewmodel åstadkommer att vara en mellanhand: Det exponerar egenskaper som en vy kan binda till. Offentliga egenskaper är det enda sättet att viewmodel ge data. A viewmodel kallas så eftersom "modellen" i MVVM representerar strukturen, data och logiken i affärsprocesserna, medan viewmodel representerar den struktur, data och logik som vyn kräver.

Hur fungerar vyn med viewmodel?

När du tittar på relationen viewmodel som har med modellen är det en klass-till-klass-standardrelation. viewmodel Har en instans av modellen och exponerar aspekter av modellen för vyn via egenskaper. Men hur hämtar och anger en vy egenskaper för viewmodel? Hur uppdaterar vyn de visuella kontrollerna med nya värden när ändringarna viewmodel ändras? Svaret är databindning.

Egenskaperna viewmodelför 's läse vid den tidpunkt då objektet är bundet till vyn. Men bindningen har inget sätt att veta om viewmodelegenskaperna ändras efter att bindningen har tillämpats på vyn. viewmodel Om du ändrar sprids inte det nya värdet automatiskt via bindningen till vyn. Om du vill uppdatera från viewmodel vyn viewmodel till måste du implementera System.ComponentModel.INotifyPropertyChanged gränssnittet.

Gränssnittet INotifyPropertyChanged deklarerar en enskild händelse med namnet PropertyChanged. Det tar en enda parameter, namnet på egenskapen som ändrade dess värde. Bindningssystemet som används i .NET MAUI förstår det här gränssnittet och lyssnar på den händelsen. När en egenskap ändras på viewmodel och genererar händelsen meddelar bindningen ändringens mål.

Tänk på hur den här relationen fungerar i HR-programmet med en anställd viewmodel. Har viewmodel egenskaper som representerar en medarbetare, till exempel namnet på medarbetaren. Implementerar viewmodel INotifyPropertyChanged gränssnittet och när Name egenskapen ändras genererar händelsen PropertyChanged , så här:

using System.ComponentModel;

public class EmployeeViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;
    private Employee _model;

    public string Name
    {
        get {...}
        set
        {
            _model.Name = value;
            OnPropertyChanged(nameof(Name))
        }
    }

    protected void OnPropertyChanged(string propertyName) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

Vyn som beskriver den anställdes information innehåller en etikettkontroll som är bunden till viewmodelegenskapen 's Name :

<Label Text="{Binding Name}" />

När egenskapen Name ändras i viewmodelPropertyChanged genereras händelsen med namnet på den egenskapen. Bindningen lyssnar på händelsen och meddelar sedan etiketten att Name egenskapen har ändrats. Sedan uppdateras etikettens Text egenskap med det senaste värdet.

Kontrollera dina kunskaper

1.

En utvecklare arbetar med ett .NET MAUI-program och vill implementera MVVM-mönstret. De skapar en modell för affärsdata och åtgärder samt en vy för användarinteraktion. Vad ska de skapa härnäst för att fungera som mellanhand mellan modellen och vyn?

2.

Ett team utvecklar ett mobilprogram med hjälp av .NET MAUI och vill se till att deras affärslogik är portabel på olika plattformar. Var ska de placera den här affärslogik i MVVM-mönstret?