2010-11-08 3 views
14

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

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

ответ

2

Запросите все, что хотите, посредством инъекций, используя интерфейсы.

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

+0

Благодарим вас за ответ.Однако параметр, который мне нужен для каждого ViewModel, не является общим для всех моделей. это нечто уникальное для каждого экземпляра viewmodel, такого как идентификатор клиента для подробной детали ViewModel клиента. – Yeonho

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

Update

Создание представления в XAML может быть так:

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

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

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

как бы вы создавали экземпляр ViewModel во время выполнения и соединяли его с его представлением? – Yeonho

+0

В случае ModelViewLocator, используемого в MvvmLight, это не требует никаких изменений. Для очень простых проектов я иногда создаю viewmodel в xaml. Я добавлю его в сообщение ... – Sorskoot

2

для меня весь смысл использования 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 Свет сообщений (не инъекционные) значения в конструктор (Messenger.Default.Register) с его Messenger.

+0

Мне нужно отправить параметр в определенный экземпляр ViewModel, такой как идентификатор клиента для детали клиента ViewModel. Как вы можете использовать мессенджер для отправки сообщения в конкретный экземпляр ViewModel? – Yeonho

+0

Я не уверен, что ваш точный сценарий можно решить. Похоже, что обмен сообщениями может управлять внутренней функциональностью в модели просмотра, которая может управляться идентификатором клиента. Мне кажется, что обмен сообщениями не нужно знать о конкретном экземпляре, но код, который может вызвать сообщение, может сделать. – rasx

+0

Вы должны иметь возможность делать конкретные сообщения с использованием токенов, но лично я бы рекомендовал вместо этого вводить параметры. – jpierson

2

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

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

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

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

вар Vm = новый ViewModel (ID); var view = new view(); view.datacontext = vm; view.show();

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

+0

Я думаю, что если вы идете по маршруту «Свет», это лучший вариант. Я бы предположил, что в дополнение к этому вы регистрируете класс в ServiceLocator в режиме разработки только для того, чтобы предоставить данные о времени разработки. –

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 
    } 
Смежные вопросы