2014-10-06 5 views
0

Я создаю приложение WPF с помощью инструментария MVVMLight. У меня есть «родительская» форма (ParentView) и вы хотите загрузить «дочернюю» форму (ChildView), передав «родительский» объект (родительский), который будет загружать все «дочерние» объекты.Использование ICommand и ServiceLocator для передачи родительского объекта для загрузки дочерних объектов способом MVVM

Я включил фрагменты кода из 3 основных классов, которые я считаю важными в чьем-либо анализе: ViewModelLocator, ChildViewModel, ParentViewModel. Первоначально я думал о реализации свойства ICommand в ParentViewModel, создавая экземпляр ParentView (см. Ниже), но это не кажется правильным, поскольку я пытаюсь сделать это с помощью MVVM. Может ли кто-нибудь помочь со следующей структурой и как передать родителя ребенку?

// ----- ChildViewModel ----- 
public class ChildViewModel 
{ 

    // this ctor doesn't make sense in the MVVM world, right?... 
    public ChildViewModel(Parent selectedParent) 
    { 
    this.Parent = selectedParent; 
    // ... 
    } 

    // how do I plug into this one?... 
    public ChildViewModel(IParentService parentService) 
    { 
    this.ParentService = parentService 
    // ... 
    } 

    // ... removed other code for brevity 
} 

// ----- ParentViewModel ----- 
{ 
    public ICommand ShowChildCommand 
    { 
    get { return new RelayCommand(() => new ChildView(SelectedParent).Show()); } 
    } 

    // ... removed other code for brevity 
} 

// ----- ViewModelLocator ----- 
public class ViewModelLocator 
{ 
    public ChildModel ChildViewModel 
    { 
    get { return ServiceLocator.Current.GetInstance<ChildViewModel>(); } 
    } 

    public ParentModel ParentViewModel 
    { 
    get { return ServiceLocator.Current.GetInstance<ParentViewModel>(); } 
    } 

    public ViewModelLocator() 
    { 
     SimpleIoc.Default.Register<IChildService, ChildService>(); 
     SimpleIoc.Default.Register<IParentService, ParentService>(); 
     // ... removed other code for brevity 
     SimpleIoc.Default.Register<ChildViewModel>(); 
     SimpleIoc.Default.Register<ParentViewModel>(); 
    } 

    // ... removed other code for brevity 
} 

// ------ ПЕРЕСМОТР 2 редактирует ------------

я включил последние предложения от пользователя @kidshaw, но я сбит с толком комментарий, в котором я должен был создать экземпляр ChildView в ParentView. Я не уверен, как это сделать. Я снова прочитал статью MSDN о Messenger, но не вижу, как это может помочь мне в этом вопросе. Я включил следующий последний код. Пожалуйста, обратитесь к комментариям.

public class ParentViewModel 
{ 

public ICommand ShowChildCommand 
    { 
     get { return new RelayCommand(OnLoadChildCommand); } 
    } 

private void OnLoadChildCommand() 
    { 
    Messenger.Default.Send(new ParentToChildMessage { Parent = this.CurrentParent }); 
    // ****** this is where I instantiated the child view 
    // I am sure this is wrong... 
    var view = new ChildView().Show(); 
    } 

public class ParentToChildMessage : MessageBase 
    { 
     public Parent Parent { get; set; } 
    } 
... 
} 

И ChildViewModel выглядит следующим образом:

public class ChildViewModel 
{ 
    public ChildViewModel(IChildService service) 
     { 
      this.ServiceProxy = service; 
      this.MessengerInstance.Register<ParentViewModel.ParentToChildMessage>(this, this.OnParentToChildMessage); 
      this.ChildCollection = new ObservableCollection<Child>(); 
      GetChildInfo(this.CurrentParent); 
     } 
} 
+0

Создайте экземпляр childview в своем родительском представлении. Просмотр является xaml. Я предлагаю вам добавить экземпляр вашего дочернего элемента управления к родительскому объекту, так что он будет создан одновременно. – kidshaw

ответ

3

В вашем образце, это говорит о том, что ViewModel разговаривает с видом. Этого следует избегать, если вы уже сделали переход к шаблону MVVM.

Я хотел бы использовать структуру сообщений в свете MVVM для этого. Вы можете разделить родительские и дочерние представления таким образом и передавать данные, не связывая их вместе. Вы можете контролировать видимость вашего дочернего представления в модели просмотра дочерних элементов и переключать его в обработчике сообщений.

В этой статье msdn будут представлены концепции. http://msdn.microsoft.com/en-us/magazine/dn745866.aspx.

На основе ваших правок ...

Первый основной шаг заключается в создании класса сообщений для выполнения данных от родителей к ребенку.

public class ParentToChildMessage : MessageBase 
{ 
    /// Include any properties you want to send 
} 

Если у вас нет данных для передачи, вы можете использовать объект GenericMessage <> от MVVM Light передать логическое значение, чтобы сэкономить немного кода. Однако сообщения регистрируются по типу, поэтому, используя общие средства, ваш метод регистрации должен будет провести дополнительную проверку - я покажу его через мгновение.

В модели родительского представления у вас есть команда ShowChildCommand - мы можем использовать это как отправную точку для отправки сообщения.

public class ParentViewModel : ViewModelBase 
{ 
    public ParentViewModel() 
    { 

    } 

    public ICommand ShowChildCommand 
    { 
     get 
     { 
      return new RelayCommand(()=>this.MessengerInstance.Send<ParentToChildMessage>(new ParentToChildMessage())); 
     } 
    } 
} 

Это все для модели родительского вида. Затем мы регистрируем приемник сообщений в модели дочернего представления.

public class ChildViewModel : ViewModelBase 
{ 
    public ChildViewModel() 
    { 
     this.MessengerInstance.Register<ParentToChildMessage>(this, this.OnParentToChildMessage); 
    } 

    private void OnParentToChildMessage(ParentToChildMessage obj) 
    { 
     // Inspect obj to decide what to do - let's just set as visible 
     this.IsVisible = true; 
    } 

    public bool IsVisible 
    { 
     get 
     { 
      return _IsVisible; 
     } 
     set 
     { 
      if (value != _IsVisible) 
      { 
       _IsVisible = value; 
       RaisePropertyChanged(); 
      } 
     } 
    } 
    private bool _IsVisible; 
} 

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

Модель детского вида обновляет простое свойство bool IsVisible - для этого для вашего родительского представления потребуется экземпляр Child view внутри него. Это обеспечит создание вашего дочернего представления и экземпляр модели вашего дочернего представления.

Надеюсь, это поможет.

+0

#kidshaw: Я взгляну на концепт мессенджера, так как в настоящее время я не использую эту часть инструментария MVVMLight. Какую часть моего кода вы бы хотели видеть? – user118190

+0

Я пошел и отредактировал свое оригинальное сообщение с некоторыми добавленными фрагментами кода, которые, надеюсь, помогут. – user118190

+0

@ user118190, я чувствовал, что ответ, который я дал, был небольшим кратким, поэтому с большим количеством кода я мог бы привести вам пример. Если вы с удовольствием исследуете концепцию самостоятельно, пожалуйста, не стесняйтесь. Тот факт, что вы используете ViewModelLocator, говорит о том, что вы вполне способны :) из дополнительного кода, который вы указали, я немного обновлю свой ответ на примере чуть позже. – kidshaw