MVVM: Comment passer le paramètre au constructeur de ViewModel
j'utilise le cadre lumineux MVVM de L. Bugnion.
Quelles sont certaines des approches recommandées pour transmettre des paramètres tels que L'ID du client au constructeur de ViewModel?
Modifier: Le paramètre dont j'ai besoin pour chaque modèle de vue n'est pas quelque chose qui est partagé entre les modèles. c'est quelque chose d'unique à chaque instance de viewmodel.
5 réponses
//Create a container class to pass via messenger service
public class CarSelectedArgs
{
#region Declarations
public Car Car { get; set; }
#endregion
#region Constructor
public CarSelectedArgs(Car car)
{
Car = car;
}
#endregion
}
//example of view model sending message.
public class SendingViewModel : ViewModelBase
{
private Car _car;
public Car SelectedCar
{
get { return _car; }
set
{
_car = value;
if (value != null)
{
//messenger will notify all classes that have registered for a message of this type
Messenger.Default.Send(new CarSelectedArgs(value));
}
}
}
}
//Example of ViewModel registering to recieve a message
public class SampleViewModel : ViewModelBase
{
#region Constructor
public SampleViewModel()
{
Messenger.Default.Register<CarSelectedArgs>(this, OnCarSelected);
}
#endregion
#region LocalMethods
void OnCarSelected(CarSelectedArgs e)
{
var NewCar = e.Car;
}
#endregion
}
demandez tout ce que vous voulez, par injection, en utilisant des interfaces.
si vous avez des paramètres partagés entre les modèles, instanciez un singleton contenant les valeurs et exposez-les via ISomethingProvider et ISomethingEditor interfaces.
pour moi, le but de L'utilisation de la lumière MVVM est d'éviter d'injecter quoi que ce soit dans le constructeur d'un modèle de vue. MVVM Light fournit un service de messagerie qui vous permet d'envoyer vos paramètres à un auditeur enregistré à l'intérieur du modèle View.
Par exemple, c'est mon point de Vue, le Modèle de mon WordWalkingStick projet à l'aide de VSTO et WPF:
using System;
using System.Xml.Linq;
using GalaSoft.MvvmLight.Messaging;
namespace Songhay.Wpf.WordWalkingStick.ViewModels
{
using Songhay.Office2010.Word;
using Songhay.OpenXml;
using Songhay.OpenXml.Models;
using Songhay.Wpf.Mvvm;
using Songhay.Wpf.Mvvm.ViewModels;
/// <summary>
/// View Model for the default Client
/// </summary>
public class ClientViewModel : ViewModelBase
{
/// <summary>
/// Initializes a new instance of the <see cref="ClientViewModel"/> class.
/// </summary>
public ClientViewModel()
{
if(base.IsInDesignMode)
{
#region
this._flatOpcSourceString = ApplicationUtility
.LoadResource(
new Uri("/Songhay.Wpf.WordWalkingStick;component/PackedFiles/FlatOpcToHtml.xml",
UriKind.Relative));
this._xhtmlSourceString = ApplicationUtility
.LoadResource(
new Uri("/Songhay.Wpf.WordWalkingStick;component/PackedFiles/FlatOpcToHtml.html",
UriKind.Relative));
#endregion
}
else
{
this._flatOpcSourceString = "Loading…";
this._xhtmlSourceString = "Loading…";
//Receive MvvmLight message:
Messenger.Default.Register(this,
new Action<GenericMessage<TransformationMessage>>(
message =>
{
var tempDocFolder =
Environment.ExpandEnvironmentVariables("%UserProfile%/Desktop/");
var inputPath = tempDocFolder + "temp.docx";
var outputPath = tempDocFolder + "temp.html";
var flatOpcDoc =
XDocument.Parse(message.Content.TransformationResult);
OpenXmlUtility.TransformFlatToOpc(flatOpcDoc, inputPath);
this.FlatOpcSourceString = flatOpcDoc.Root.ToString();
var settings = new SonghayHtmlConverterSettings()
{
PageTitle = "My Page Title " + DateTime.Now.ToString("U"),
UseEntityMap = false
};
OpenXmlUtility.WriteHtmlFile(inputPath, outputPath, settings);
var xhtmlDoc = XDocument.Load(outputPath);
this.XhtmlSourceString = xhtmlDoc.Root.ToString();
}));
}
}
/// <summary>
/// Gets or sets the flat opc source string.
/// </summary>
/// <value>The flat opc source string.</value>
public string FlatOpcSourceString
{
get
{
return _flatOpcSourceString;
}
set
{
_flatOpcSourceString = value;
base.RaisePropertyChanged("FlatOpcSourceString");
}
}
/// <summary>
/// Gets or sets the XHTML source string.
/// </summary>
/// <value>The XHTML source string.</value>
public string XhtmlSourceString
{
get
{
return _xhtmlSourceString;
}
set
{
_xhtmlSourceString = value;
base.RaisePropertyChanged("XhtmlSourceString");
}
}
string _flatOpcSourceString;
string _xhtmlSourceString;
}
}
vous pouvez voir que la lumière MVVM est messagerie (ne pas injecter) valeurs dans le constructeur (Messenger.Default.Register
avec son Messenger
.
Voici ce que je fais:
ViewModel doit faire preuve d'une fenêtre de la voiture avec la voiture de l'id passé en paramètre:
ViewModel -> message à codebehind pour voir ouvrir la fenêtre. Le Message envoie une pièce d'identité.
essentiellement en code derrière:
var vm = new viewmodel (id); var affichage = nouveau point de vue(); vue.datacontext = vm; vue.show ();
mon viewmodel a un constructeur qui prend un id.
dans le cas d'écrire des tests contre le viewmodel je crée parfois une surcharge du constructeur de viewmodel qui prend un ISomething comme paramètre. J'ai le constructeur par défaut appelez le second avec une implémentation par défaut de ISomething. Dans le cas du test j'appelle le constructeur avec une implémentation de test. Je sais que ce n'est pas la meilleure méthode, parce que ça crée une dépendance entre les deux classes... mais parfois, vous aurez à prendre le facile chemin...
public class SomeViewModel
{
private ISomething internalSomething;
public void SomeViewModel():this(new Something()){}
public void SomeViewModel(ISomething something)
{
this.internalSomething = something;
}
}
mise à Jour
créer une vue dans xaml peut être comme ceci:
<UserControl xmlns="...."
xmlns:Example="SomeNamespace">
<UserControl.DataContext>
<Example:SomeViewModel />
</UserControl.DataContext>
<Grid>
...
</Grid>
</UserControl>