2010-11-08 6 views
14

Ich benutze L. Bugnions MVVM Light Framework.
Was sind einige der empfohlenen Ansätze zum Übergeben von Parametern wie die ID des Kunden an ViewModels Konstruktor?MVVM: wie Parameter an ViewModels Konstruktor übergeben werden

Bearbeiten: Der Parameter, den ich für jedes ViewModel brauche, ist nicht etwas, das über Modelle hinweg geteilt wird. es ist etwas, das für jede Viewmodel-Instanz einzigartig ist.

Antwort

2

Fragen Sie alles, was Sie wollen, über die Injektion, über Schnittstellen.

Wenn Sie Einstellungen über Modelle gemeinsam, instanziiert ein Singleton die Werte enthält, und sie und ISomethingEditor Schnittstellen über ISomethingProvider aussetzen.

+0

Vielen Dank für Ihre Antwort.Der Parameter, den ich für jedes ViewModel benötige, ist jedoch nicht für alle Modelle freigegeben. Dies ist für jede Viewmodel-Instanz einzigartig, beispielsweise die Kunden-ID für Customer Detail ViewModel. – Yeonho

0

Im Falle des Schreibens von Tests gegen das Viewmodel erstelle ich manchmal eine Überladung des Viewmodel-Konstruktors, die einen ISomething als Parameter verwendet. Ich habe den Standardkonstruktor den zweiten Aufruf mit einer Standardimplementierung von ISomething. Im Falle des Tests rufe ich den Konstruktor mit einer Testimplementierung auf. Ich weiß, es ist nicht die beste Methode, weil es eine Abhängigkeit zwischen den beiden Klassen schafft ... aber manchmal werden Sie den einfachen Weg nehmen müssen ...

public class SomeViewModel 
{ 
    private ISomething internalSomething; 

    public void SomeViewModel():this(new Something()){} 

    public void SomeViewModel(ISomething something) 
    { 
    this.internalSomething = something; 
    }  
} 

aktualisieren

eine Ansicht in xAML Erstellen kann wie folgt sein:

<UserControl xmlns="...." 
      xmlns:Example="SomeNamespace"> 

    <UserControl.DataContext> 
    <Example:SomeViewModel /> 
    </UserControl.DataContext> 

    <Grid> 
    ... 
    </Grid> 
</UserControl> 
+0

Wie würden Sie das ViewModel in der Laufzeit instanziieren und es mit seiner Sicht koppeln? – Yeonho

+0

Bei einem ModelViewLocator, wie er in MvvmLight verwendet wird, sind keine Änderungen erforderlich. Bei sehr einfachen Projekten erstelle ich manchmal das Viewmodel in XAML. Ich werde es zum Beitrag hinzufügen ... – Sorskoot

2

Für mich ist der ganze Punkt MVVM Licht besteht darin, zu vermeiden, irgendetwas in den Konstruktor einer Ansicht Modell injiziert wird. MVVM Light bietet eine Messaging-Funktion, mit der Sie Ihre Parameter an einen Listener senden können, der unter innerhalb des View-Modells registriert ist.

Zum Beispiel, das ist meine Ansicht Modell von meinem WordWalkingStick Projekt mit VSTO und WPF: mit

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; 
    } 
} 

Sie können sehen, dass MVVM Light ist Messaging (nicht Injektion) Konstruktor Werte in (Messenger.Default.Register) sein Messenger.

+0

Ich muss den Parameter an eine bestimmte Instanz von ViewModel, z. B. Kundennummer für Kundendetail ViewModel senden. Wie können Sie Messenger verwenden, um eine Nachricht an eine bestimmte ViewModel-Instanz zu senden? – Yeonho

+0

Ich bin mir nicht sicher, ob Ihr genaues Szenario angesprochen werden kann. Es sieht so aus, als ob Messaging die interne Funktionalität im View-Modell steuern kann, die kundenidentifikationsgesteuert sein kann. Es scheint mir, dass Messaging nicht auf eine bestimmte Instanz achten muss, sondern auf den Code, den die Nachrichten aufrufen können. – rasx

+0

Sie sollten in der Lage sein, instanzspezifische Nachrichten mit Tokens zu erstellen, aber ich würde persönlich empfehlen, stattdessen die Parameter zu verwenden. – jpierson

2

Hier ist, was ich tue:

Ansichtsmodell braucht ein Autofenster mit Auto-ID als Parameter übergeben zeigen:

Ansichtsmodell -> Nachricht für Blick auf Code-Behind-Fenster zu öffnen. Nachricht sendet ID.

Wesentlichen Code hinter:

var vm = new Ansichtsmodell (id); var view = neue Ansicht(); view.datacontext = vm; view.show();

Mein Viewmodel hat einen Konstruktor, der eine ID aufnimmt.

+0

Ich denke, wenn Sie die "Light" Route gehen, ist dies die beste Option. Ich würde vorschlagen, dass Sie zusätzlich die Klasse im ServiceLocator im Entwurfsmodus registrieren, nur um Entwurfszeitdaten bereitzustellen. –

8
//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 
    }