MVVM: как передать параметр в конструктор ViewModel - PullRequest
14 голосов
/ 08 ноября 2010

Я использую MVVM Light Framework Л. Бюньона.Каковы некоторые из рекомендуемых подходов для передачи параметров, таких как идентификатор клиента, конструктору ViewModel?

Редактировать: параметр, который мне нужен для каждой модели ViewModel, не является чем-то общим для всех моделей.это что-то уникальное для каждого экземпляра модели представления.

Ответы [ 5 ]

8 голосов
/ 04 апреля 2011
//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
    }
2 голосов
/ 11 ноября 2010

Вот что я делаю:

ViewModel должен показать окно автомобиля с идентификатором автомобиля, переданным в качестве параметра:

ViewModel -> сообщение для кода для просмотра, чтобы открыть окно. Сообщение отправляет идентификатор.

По существу в коде позади:

var vm = новая модель представления (id); var view = new view (); view.datacontext = vm; view.show ();

у моей viewmodel есть конструктор, который принимает идентификатор.

2 голосов
/ 08 ноября 2010

Для меня весь смысл использования MVVM Light состоит в том, чтобы избегать внедрения чего-либо в конструктор модели представления.MVVM Light предоставляет функцию обмена сообщениями, которая позволяет отправлять ваши параметры слушателю, зарегистрированному внутри модели представления.

Например, это моя модель представления из моего WordWalkingStick *Проект 1006 * с использованием 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.Register) с его Messenger.

2 голосов
/ 08 ноября 2010

Запросите все, что вы хотите, с помощью внедрения через интерфейсы.

Если у вас есть общие настройки для моделей, создайте экземпляр синглтона, содержащего значения, и выставьте их с помощью ISomethingProvider и ISomethingEditor интерфейсы.

0 голосов
/ 08 ноября 2010

В случае написания тестов для модели представления я иногда создаю перегрузку конструктора модели представления, которая принимает 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>
...