MVVM:如何将参数传递给ViewModel的构造函数

时间:2010-11-08 07:49:41

标签: silverlight mvvm viewmodel mvvm-light service-locator

我正在使用L. Bugnion的MVVM Light Framework 将诸如Customer的ID等参数传递给ViewModel的构造函数的一些推荐方法是什么?

编辑: 每个ViewModel所需的参数不是跨模型共享的参数。它是每个viewmodel实例独有的东西。

5 个答案:

答案 0 :(得分: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
    }

答案 1 :(得分:2)

使用接口通过注入请求任何您想要的东西。

如果您有跨模型共享的设置,请实例化包含值的单例并通过 ISomethingProvider ISomethingEditor 接口公开它们。

答案 2 :(得分:2)

对我来说,使用MVVM Light的重点是避免将任何内容注入到View Model的构造函数中。 MVVM Light提供了一个Messaging工具,允许您将参数发送到View Model中注册 inside 的监听器。

例如,这是我使用VSTO和WPF的WordWalkingStick项目的视图模型:

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

您可以看到MVVM Light 消息传递(不注入)值到构造函数(Messenger.Default.Register)及其Messenger

答案 3 :(得分:2)

以下是我的工作:

ViewModel需要显示一个车辆窗口,车辆ID作为参数传递:

ViewModel - &gt;消息到codebehind以查看打开窗口。消息发送id。

基本上在代码背后:

var vm = new viewmodel(id); var view = new view(); view.datacontext = vm; view.show();

我的viewmodel有一个构造函数,它接受一个id。

答案 4 :(得分:0)

在针对viewmodel编写测试的情况下,我有时会创建一个viewmodel构造函数的重载,它将 ISomething 作为参数。我有默认构造函数调用第二个使用默认实现 ISomething 。在测试的情况下,我使用测试实现调用构造函数。我知道这不是最好的方法,因为它在两个类之间创建了一个依赖关系...但有时候你必须采取简单的方法......

public class SomeViewModel
{
  private ISomething internalSomething;

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

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

更新

在xaml中创建视图可以是这样的:

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

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

  <Grid>
     ...
  </Grid>
</UserControl>