16

我正在使用 L. Bugnion 的 MVVM Light Framework。
将客户 ID 等参数传递给 ViewModel 的构造函数的推荐方法有哪些?

编辑:每个 ViewModel 我需要的参数不是跨模型共享的。它是每个视图模型实例所独有的。

4

5 回答 5

10
//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
    }
于 2011-04-04T14:27:44.670 回答
3

对我来说,使用 MVVM Light 的全部意义在于避免将任何东西注入到 View Model 的构造函数中。MVVM Light 提供了一个消息传递工具,允许您将参数发送到在视图模型中注册的侦听

例如,这是我的WordWalkingStick项目中使用 VSTO 和 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;
    }
}

您可以看到 MVVM Light正在使用Messenger.Default.RegisterMessenger.

于 2010-11-08T19:36:03.213 回答
2

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

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

于 2010-11-08T08:58:33.957 回答
1

这是我所做的:

ViewModel 需要显示带有作为参数传递的汽车 id 的车窗:

ViewModel -> 消息到代码隐藏以查看打开窗口。消息发送 id。

基本上在后面的代码中:

var vm = 新视图模型(id);变量视图 = 新视图();view.datacontext = vm; view.show();

我的视图模型有一个接受 id 的构造函数。

于 2010-11-11T15:37:14.187 回答
0

在针对视图模型编写测试的情况下,我有时会创建以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>
于 2010-11-08T14:02:35.227 回答