mvvmAan de slag met mvvm


Opmerkingen

Deze sectie geeft een overzicht van wat mvvm is en waarom een ontwikkelaar het misschien wil gebruiken.

Het moet ook alle grote onderwerpen binnen mvvm vermelden en een link naar de gerelateerde onderwerpen bevatten. Aangezien de documentatie voor mvvm nieuw is, moet u mogelijk eerste versies van die gerelateerde onderwerpen maken.

C # MVVM Samenvatting en compleet voorbeeld

Samenvatting:

MVVM is een architecturaal patroon dat wordt vertegenwoordigd door drie verschillende componenten, het Model , View en ViewModel . Om deze drie lagen te begrijpen, is het noodzakelijk om elke laag kort te definiëren, gevolgd door een uitleg over hoe ze samenwerken.

Model is de laag die de bedrijfslogica aanstuurt. Hiermee wordt informatie uit elke gegevensbron opgehaald en opgeslagen voor consumptie door het ViewModel .

ViewModel is de laag die fungeert als een brug tussen de weergave en het model . Het kan de onbewerkte gegevens van het model al dan niet transformeren in een presenteerbare vorm voor de weergave . Een voorbeeldtransformatie zou zijn: een Booleaanse vlag van het model naar de reeks 'True' of 'False' voor de weergave.

Weergave is de laag die de interface van de software vertegenwoordigt (dwz de GUI). Zijn rol is om de informatie van het ViewModel weer te geven aan de gebruiker en om de veranderingen van de informatie terug te communiceren naar het ViewModel .

Deze drie componenten werken samen door op de volgende manier naar elkaar te verwijzen:

  • De weergave verwijst naar het ViewModel .
  • Het ViewModel verwijst naar het model .

Het is belangrijk op te merken dat de View en het ViewModel tweerichtingscommunicatie mogelijk maken, ook wel Data Bindings genoemd .

Een belangrijk ingrediënt voor tweerichtingscommunicatie (gegevensbinding) is de interface INotifyPropertyChanged .

Door dit mechanisme te gebruiken, kan de weergave de gegevens in de ViewModel wijzigen via gebruikersinvoer en kan de ViewModel de weergave bijwerken met gegevens die mogelijk zijn bijgewerkt via processen in het model of met bijgewerkte gegevens uit de gegevensopslagruimte.

MVVM-architectuur legt een zware nadruk op de scheiding van problemen voor elk van deze lagen. Het scheiden van de lagen komt ons ten goede als:

  • Modulariteit: de interne implementatie van elke laag kan worden gewijzigd of geruild zonder de andere te beïnvloeden.
  • Verbeterde testbaarheid: elke laag kan eenheidstest zijn met nepgegevens, wat niet mogelijk is als de code van het ViewModel in de code achter de weergave is geschreven.

De build:

Maak een nieuw WPF-toepassingsproject Maak een nieuw WPF-toepassingsproject

Maak drie nieuwe mappen in uw oplossing: Model , ViewModel en View , en verwijder de originele MainWindow.xaml , gewoon om een nieuwe start te maken.

Maak 3 nieuwe mappen in uw oplossing

Maak drie nieuwe items, die elk overeenkomen met een afzonderlijke laag:

  • Klik met de rechtermuisknop op de map Model en voeg een Klasse- item toe met de naam HelloWorldModel.cs .
  • Klik met de rechtermuisknop op de map ViewModel en voeg een Klasse- item toe met de naam HelloWorldViewModel.cs .
  • Klik met de rechtermuisknop op de map Weergave en voeg een Windows- item (WPF) toe met de naam HelloWorldView.xaml .

Voeg de drie items toe

Wijzig App.xaml om naar de nieuwe weergave te wijzen

<Application x:Class="MyMVVMProject.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:MyMVVMProject"
             StartupUri="/View/HelloWorldView.xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>
 

ViewModel:

Begin met het bouwen van het ViewModel eerst. De klasse moet de INotifyPropertyChanged interface implementeren, een PropertyChangedEventHandler gebeurtenis declareren en een methode maken om de gebeurtenis te verhogen (bron: MSDN: kennisgeving van eigenschapsverandering implementeren ). OnPropertyChanged() een veld en een bijbehorende eigenschap en zorg ervoor dat u de methode OnPropertyChanged() aanroept in de set accessor van de eigenschap. De constructor in het onderstaande voorbeeld wordt gebruikt om aan te tonen dat het model de gegevens aan het ViewModel levert.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using MyMVVMProject.Model;

namespace MyMVVMProject.ViewModel
{
    // Implements INotifyPropertyChanged interface to support bindings
    public class HelloWorldViewModel : INotifyPropertyChanged
    {
        private string helloString;

        public event PropertyChangedEventHandler PropertyChanged;

        public string HelloString
        {
            get
            {
                return helloString;
            }
            set
            {
                helloString = value;
                OnPropertyChanged();
            }
        }

        /// <summary>
        /// Raises OnPropertychangedEvent when property changes
        /// </summary>
        /// <param name="name">String representing the property name</param>
        protected void OnPropertyChanged([CallerMemberName] string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }

        public HelloWorldViewModel()
        {
            HelloWorldModel helloWorldModel = new HelloWorldModel();
            helloString = helloWorldModel.ImportantInfo;
        }
    }
}
 

Model:

Bouw vervolgens het model . Zoals eerder vermeld, biedt het model gegevens voor het ViewModel door het uit een repository te halen (en het terug te duwen naar de repository om op te slaan). Dit wordt hieronder aangetoond met de GetData() , die een eenvoudige List<string> retourneert. Bedrijfslogica wordt ook in deze laag toegepast en is te zien in de methode ConcatenateData() . Met deze methode wordt de zin "Hallo wereld!" uit de List<string> die eerder werd geretourneerd uit onze "repository".

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyMVVMProject.Model
{
    public class HelloWorldModel
    {
        private List<string> repositoryData;
        public string ImportantInfo
        {
            get
            {
                return ConcatenateData(repositoryData);
            }
        }

        public HelloWorldModel()
        {
            repositoryData = GetData();
        }

        /// <summary>
        /// Simulates data retrieval from a repository
        /// </summary>
        /// <returns>List of strings</returns>
        private List<string> GetData()
        {
            repositoryData = new List<string>()
            {
                "Hello",
                "world"
            };
            return repositoryData;
        }

        /// <summary>
        /// Concatenate the information from the list into a fully formed sentence.
        /// </summary>
        /// <returns>A string</returns>
        private string ConcatenateData(List<string> dataList)
        {
            string importantInfo = dataList.ElementAt(0) + ", " + dataList.ElementAt(1) + "!";
            return importantInfo;
        }
    }
}
 

Visie:

Eindelijk kan de View worden gebouwd. Er is niets dat moet worden toegevoegd aan de code achter voor dit voorbeeld, hoewel dit kan variëren afhankelijk van de behoeften van de toepassing. Er zijn echter een paar regels toegevoegd aan de XAML. Het Window heeft een verwijzing naar de ViewModel naamruimte nodig. Dit wordt toegewezen aan de XAML-naamruimte xmlns:vm="clr-namespace:MyMVVMProject.ViewModel" . Vervolgens heeft het venster een DataContext . Dit is ingesteld op <vm:HelloWorldViewModel/> . Nu kan het label (of de controle van uw keuze) aan het venster worden toegevoegd. Het belangrijkste punt in dit stadium is ervoor te zorgen dat u de binding instelt op de eigenschap van het ViewModel dat u als labelinhoud wilt weergeven. In dit geval is het {Binding HelloString} .

Het is belangrijk om te binden aan de eigenschap, en niet aan het veld, omdat in het laatste geval de weergave geen melding ontvangt dat de waarde is gewijzigd, omdat de methode OnPropertyChanged() alleen de PropertyChangedEvent op de eigenschap verhoogt en niet op de veld.

<Window x:Class="MyMVVMProject.View.HelloWorldView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MyMVVMProject.View"
        xmlns:vm="clr-namespace:MyMVVMProject.ViewModel"
        mc:Ignorable="d"
        Title="HelloWorldView" Height="300" Width="300">
    <Window.DataContext>
        <vm:HelloWorldViewModel/>
    </Window.DataContext>
    <Grid>
        <Label x:Name="label" FontSize="30" Content="{Binding HelloString}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    </Grid>
</Window>