2010-11-08 33 views
14

Estoy utilizando MVVM Light Framework de L. Bugnion.
¿Cuáles son algunos de los enfoques recomendados para pasar parámetros como el ID del cliente al constructor de ViewModel?MVVM: cómo pasar el parámetro al constructor de ViewModel

Editar: El parámetro que necesito para cada ViewModel no es algo que se comparta entre los modelos. es algo único para cada instancia de viewmodel.

Respuesta

2

Solicite lo que desee, mediante inyección, utilizando interfaces.

Si tiene ajustes compartidos a través de modelos, una instancia de un producto único que contiene los valores y los exponen a través de ISomethingProvider y ISomethingEditor interfaces.

+0

gracias por su respuesta.Sin embargo, el parámetro que necesito para cada ViewModel no es algo que se comparta entre los modelos. es algo único para cada instancia de viewmodel, como la identificación del cliente para el detalle del cliente ViewModel. – Yeonho

0

En el caso de escribir pruebas contra el modelo de vista, a veces creo una sobrecarga del constructor del modelo de vista que toma un ISomething como parámetro. Tengo la llamada de constructor predeterminada la segunda con una implementación predeterminada de ISomething. En el caso de la prueba, llamo al constructor con una implementación de prueba. Yo sé que no es el mejor método, ya que crea una dependencia entre las dos clases ... pero a veces se tendrá que tomar el camino fácil ...

public class SomeViewModel 
{ 
    private ISomething internalSomething; 

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

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

actualización

Creación de una vista en XAML puede ser así:

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

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

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

¿cómo crearías una instancia del ViewModel en el tiempo de ejecución y lo emparejaría con su vista? – Yeonho

+0

En el caso de un ModelViewLocator como se usa en MvvmLight esto no requiere ningún cambio. Para proyectos muy simples, a veces creo el modelo de vista en xaml. Lo agregaré a la publicación ... – Sorskoot

2

para mí todo el punto de usar MVVM Light es nada para evitar la inyección en el constructor de una vista del modelo. MVVM Light proporciona una función de mensajería que le permite enviar sus parámetros a un oyente registrado dentro de del Modelo de visualización.

Por ejemplo, este es mi punto de vista de modelo de mi proyecto WordWalkingStick con VSTO y 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; 
    } 
} 

Se puede ver que MVVM Light es mensajería (no inyectada) valores en el constructor (Messenger.Default.Register) con es Messenger.

+0

Necesito enviar el parámetro a una cierta instancia de ViewModel, como ID de cliente para el detalle del cliente ViewModel. ¿Cómo se puede usar Messenger para enviar mensajes a una instancia específica de ViewModel? – Yeonho

+0

No estoy seguro de que se pueda abordar su situación exacta. Parece que la mensajería puede impulsar la funcionalidad interna en el Modelo de Vista que puede ser manejado por ID del cliente. Me parece que la mensajería no tiene que ser consciente de una instancia en particular, pero el código que las llamadas de mensajes pueden hacer. – rasx

+0

Debería poder hacer mensajes específicos de instancia utilizando tokens, pero personalmente recomendaría inyectar los parámetros en su lugar. – jpierson

2

Aquí es lo que hago:

modelo de vista necesita mostrar una ventana de coche con el coche Identificación del pasado como parámetro:

modelo de vista -> mensaje al código subyacente para el fin de abrir la ventana. El mensaje envía la identificación.

Esencialmente en código detrás:

var = vm nuevo modelo de vista (id); var view = new view(); view.datacontext = vm; view.show();

my viewmodel tiene un constructor que toma una identificación.

+0

Creo que si vas por la ruta "Luz", esta es la mejor opción. Sugeriría que, además de esto, registre la clase en ServiceLocator en modo de diseño solo para proporcionar datos de tiempo de diseño. –

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 
    } 
Cuestiones relacionadas