mvvm Tutorial
Iniziare con mvvm
Ricerca…
Osservazioni
Questa sezione fornisce una panoramica di cosa è mvvm e perché uno sviluppatore potrebbe volerlo utilizzare.
Dovrebbe anche menzionare qualsiasi argomento di grandi dimensioni all'interno di mvvm e collegarsi agli argomenti correlati. Poiché la documentazione di mvvm è nuova, potrebbe essere necessario creare versioni iniziali di tali argomenti correlati.
C # MVVM Riepilogo ed esempio completo
Sommario:
MVVM è un pattern architettonico rappresentato da tre componenti distinti: Model , View e ViewModel . Per comprendere questi tre livelli, è necessario definire brevemente ciascuno di essi, seguito da una spiegazione di come essi lavorano insieme.
Il modello è il livello che guida la logica aziendale. Recupera e archivia le informazioni da qualsiasi fonte di dati per il consumo da ViewModel .
ViewModel è il livello che funge da ponte tra la vista e il modello . Può o non può trasformare i dati grezzi dal modello in una forma presentabile per la vista . Una trasformazione di esempio potrebbe essere: un flag booleano dal modello alla stringa di "True" o "False" per la vista.
View è il layer che rappresenta l'interfaccia del software (ovvero la GUI). Il suo ruolo è quello di visualizzare le informazioni dal ViewModel per l'utente, e di comunicare i cambiamenti delle informazioni al ViewModel.
Questi tre componenti lavorano insieme facendo riferimento l'un l'altro nel modo seguente:
- La vista fa riferimento a ViewModel .
- ViewModel fa riferimento al modello .
È importante notare che View e ViewModel sono in grado di comunicazioni bidirezionali conosciute come Data Bindings .
Un ingrediente importante per la comunicazione bidirezionale (associazione dati) è l'interfaccia INotifyPropertyChanged .
Utilizzando questo meccanismo, la vista può modificare i dati nel ViewModel tramite l'input dell'utente e ViewModel può aggiornare la vista con dati che potrebbero essere stati aggiornati tramite processi nel modello o con dati aggiornati dal repository.
L'architettura MVVM pone una forte enfasi sulla separazione delle preoccupazioni per ciascuno di questi livelli. Separare gli strati ci avvantaggia come:
- Modularità: l'implementazione interna di ogni livello può essere cambiata o scambiata senza influire sugli altri.
- Maggiore testabilità: ogni livello può essere testato unitamente a dati falsi, cosa non possibile se il codice di ViewModel è scritto nel codice dietro la vista .
La costruzione:
Creare un nuovo progetto di applicazione WPF
Crea tre nuove cartelle nella soluzione: modello , ViewModel e View ed elimina il MainWindow.xaml
originale, solo per ottenere un nuovo inizio.
Crea tre nuovi elementi, ciascuno corrispondente a un livello separato:
- Fare clic con il pulsante destro del mouse sulla cartella Modello e aggiungere un elemento di classe denominato
HelloWorldModel.cs
. - Fare clic con il tasto destro sulla cartella ViewModel e aggiungere un elemento di classe chiamato
HelloWorldViewModel.cs
. - Fare clic con il tasto destro sulla cartella View e aggiungere un oggetto Window (WPF) chiamato
HelloWorldView.xaml
.
Alter App.xaml
per puntare alla nuova vista
<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:
Inizia con la costruzione del ViewModel per primo. La classe deve implementare l'interfaccia INotifyPropertyChanged
, dichiarare un evento PropertyChangedEventHandler
e creare un metodo per generare l'evento (fonte: MSDN: Come implementare la notifica di modifica della proprietà ). Quindi, dichiarare un campo e una proprietà corrispondente, assicurandosi di chiamare il metodo OnPropertyChanged()
nel set
accessor della proprietà. Il costruttore nell'esempio seguente viene utilizzato per dimostrare che il Modello fornisce i dati a ViewModel .
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;
}
}
}
Modello:
Quindi, crea il modello . Come indicato in precedenza, il Modello fornisce i dati per ViewModel estraendoli da un repository (oltre a reinserirli nel repository per il salvataggio). Questo è dimostrato di seguito con il metodo GetData()
, che restituirà una semplice List<string>
. La logica aziendale viene applicata anche in questo livello e può essere vista nel metodo ConcatenateData()
. Questo metodo costruisce la frase "Hello, world!" List<string>
che è stato precedentemente restituito dal nostro "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;
}
}
}
Vista:
Infine, la vista può essere costruita. Non c'è nulla che deve essere aggiunto al codice dietro per questo esempio, anche se questo può variare a seconda delle esigenze dell'applicazione. Tuttavia, ci sono alcune linee aggiunte a XAML. La Window
bisogno di un riferimento allo spazio dei nomi ViewModel
. Questo è mappato allo spazio dei nomi XAML xmlns:vm="clr-namespace:MyMVVMProject.ViewModel"
. Successivamente, la finestra ha bisogno di un DataContext
. Questo è impostato su <vm:HelloWorldViewModel/>
. Ora l'etichetta (o il controllo di tua scelta) può essere aggiunta alla finestra. Il punto chiave in questa fase è assicurarsi di impostare il binding sulla proprietà del ViewModel che si desidera visualizzare come contenuto dell'etichetta. In questo caso, è {Binding HelloString}
.
È importante associare alla proprietà e non al campo, poiché nel secondo caso la vista non riceverà la notifica che il valore è cambiato, poiché il metodo OnPropertyChanged()
solleverà il PropertyChangedEvent
sulla proprietà e non sul campo.
<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>