2

在我的 WPF MVVM 应用程序中,使用 Caliburn.Micro,我有一个 ViewModel,CreateServiceViewModel单击按钮会在单独的窗口中打开一个 GridView,供用户从中选择一个行。

我为此创建了另一个 ViewModel,MemberSearchViewModel它有两个属性:

    private Member selectedMember;

    public Member SelectedMember
    {
        get { return selectedMember; }
        set { selectedMember = value; }
    }

    private IList<Member> members;

    public IList<Member> Members
    {
        get { return members; }
        set { members = value; }
    }

如何将 SelectedMember 值返回给调用 ViewModel?该 ViewModel 具有Service.SelectedMember.

4

5 回答 5

3

EventAggregator 是您可以使用的......我确信这是众多解决方案之一。

public class MessageNotifier{
  public object Content{get;set;}
  public string Message {get;set;}
}


//MEF bits here
public class HelloWorldViewModel: Screen, IHandle<MessageNotifier>{
   private readonly IEventAggregator _eventAggregator

  //MEF constructor bits
  public YourViewModel(IEventAggregator eventAggregator){
    _eventAggregator = eventAggregator;
  }

   public override OnActivate(){
       _eventAggregator.Subscribe(this);
   }
   public override OnDeactivate(){
     _eventAggregator.UnSubscribe(this);
   }

   //I Handle all messages with this signature and if the message applies to me do something
   //
   public void Handle(MesssageNotifier _notifier){
        if(_notifier.Message == "NewSelectedItem"){
            //do something with the content of the selectedItem
            var x = _notifier.Content
        }
   } 
}

//MEF attrs
public class HelloWorld2ViewModel: Screen{
   private readonly IEventAggregator _eventAggregator
    //MEF attrs
    public HelloWorld2ViewModel(IEventAggregator eventAggregator){
       _eventAggregator = eventAggregator;
    }

    public someobject SelectedItem{
      get{ return _someobject ;}
      set{ _someobject = value;
          NotifyOfPropertyChange(()=>SelectedItem);
          _eventAggregator.Publish(new MessageNotifier(){ Content = SelectedItem, Message="NewSelectedItem"});
    }
}
于 2013-05-17T00:35:45.897 回答
1

一种选择是利用NotifyPropertyChanged. 由于您使用的是 ViewModel,它们很可能实现INotifyPropertyChanged了 ,您可以像框架一样使用它。

当您的 CreateServiceViewModel 创建 MemberSearchViewModel 时,它只会订阅 PropertyChanged 事件:

//This goes wherever you create your child view model
var memberSearchViewModel = new MemberSearchViewModel(); //Or using a service locator, if applicable
memberSearchViewModel.PropertyChanged += OnMemberSearchPropertyChanged;

private void OnMemberSearchPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if(e.PropertyName == "SelectedMember")
    {
        //Code to respond to a change in the Member
    }
}

然后在您的 MemberSearchViewModel 中,当用户从网格中选择一个成员时,您只需引发 NotifyPropertyChanged 事件。

编辑:正如@DNH 在评论中正确指出的那样,如果没有正确清理,使用这样的事件处理程序可能会导致内存泄漏。因此,当您完成 MemberSearchViewModel 后,请确保取消订阅该PropertyChanged事件。因此,例如,如果您只需要它直到用户选择一个成员,您可以将它放在 Property Changed Handler 本身中(我已将其切换为使用类级变量来保存 ViewModel):

private void OnMemberSearchPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if(e.PropertyName == "SelectedMember")
    {
        //Code to respond to a change in the Member

        //Unsubscribe so the view model can be garbage collected
        _memberSearchViewModel.PropertyChanged -= OnMemberSearchPropertyChanged;
        _memberSearchViewModel = null;
    }
}
于 2013-05-16T14:38:50.290 回答
0

一种选择是将属性存储MemberSearchViewModel为字段CreateServiceViewModel并定义CreateServiceViewModel.SelectedMember如下:

public Member SelectedMember
{
    get
    {
        return _memberSearchViewModel.SelectedMember;
    }
    set
    {
        _memberSearchViewModel.SelectedMember = value;
    }
}
于 2013-05-16T14:38:36.703 回答
0

作为我评论的后续,这里有一个使用Prism- 我从未使用过的示例Caliburn

创建一个事件- 事件的有效负载将是您的 SelectedMember:

public class YourEvent:CompositePresentationEvent<YourEventPayload>{}

发布活动:

EventAggregator.GetEvent<YourEvent>().Publish(YourEventPayload);

订阅活动:

EventAggregator.GetEvent<YourEvent>().Subscribe((i) => ...);
于 2013-05-16T15:13:07.547 回答
0

怎么样?

public interface INotifyMe<T>
{
    T ResultToNotify { get; set; }
}

public class CreateServiceViewModel : ViewModelBase, INotifyMe<Member>
{
    // implement the interface as you like...
}

public class MemberSearchViewModel : ViewModelBase
{
    public MemberSearchViewModel(INotifyMe<Member> toBeNotified)
    {
        // initialize field and so on...
    }
}

现在您可以让监听CreateServiceViewModel它自己的属性,而不必考虑删除事件监听器。

当然,要采用更经典的方式,您也可以使用这样的界面。

public interface INotifyMe<T>
{
    void Notify(T result);
}
于 2013-05-16T14:58:57.990 回答