在ViewModels与事件之间进行通信

时间:2013-10-10 03:31:35

标签: c# wpf mvvm

我正在尝试将我的孩子ViewModel中的事件传递回父母。子视图模型的视图是一个单独的窗口,我相信我无法传递构造函数参数。此视图上的按钮需要在父ViewModel上触发方法。

Child ViewModel:

public ConnectViewModel(ConnectEvents connectEvents)
{
    ConnectEvents = connectEvents;
}

父ViewModel

public MainWindowViewModel()
{
    ConnectEvents connectEvents = new ConnectEvents();
    ConnectViewModel = new ConnectViewModel(connectEvents);
    connectEvents.ThrowEvent += ConnectToServer;
}

我如何在这两者之间进行沟通?是否有更好的系统,或者我如何允许父母订阅孩子?

4 个答案:

答案 0 :(得分:5)

你有很多选择。您可以使用custom event,您可以直接使用delegate,您可以使用普通订阅在您的父ViewModel中订阅PropertyChangedCollectionChanged事件,或{{3 }}

我更喜欢最后一个,因为没有必要取消订阅。

答案 1 :(得分:4)

您可以制作自己的EventAggregator

public static class DumbAggregator
{
  public static void BroadCast(string message)
  {
   if (OnMessageTransmitted != null)
       OnMessageTransmitted(message);
  }

 public static Action<string> OnMessageTransmitted;
}

用法:

  public class MySender
  {
    public void SendMessage()
    {
      DumbAggregator.BroadCast("Hello There!");
    }
  }

public class MySubscriber
{
  public MySubscriber()
  {
   DumbAggregator.OnMessageTransmitted += OnMessageReceived;
  }

 private void OnMessageReceived(string message)
 {
  MessageBox.Show("I Received a Message! - " + message);
 }
}

在此帮助下,您可以与视图模型进行通信

答案 2 :(得分:2)

使用活动传达'事件'

在ConnectViewModel中......

public ConnectViewModel(ConnectEvents connectEvents)
{
    public event EventHandler<EventArgs> SomethingHappenedEvent;

     ...

     private void DoSomething()
     {
          if (SomethingHappenedEvent != null)
          {
              SomethingHappenedEvent(this, newEventArgs());
          }
     }

     RelayComand _somethingCommand;
     public ICommand SomethingHappenedCommand
     {   
          get
          {
              if (_someethingCommand == null)
                   _somethingCommand = new RelayCommand(DoSomething)
           }
     }
}

并在您的MainWindowViewModel

public MainWindowViewModel()
{
    ConnectEvents connectEvents = new ConnectEvents();
    ConnectViewModel = new ConnectViewModel(connectEvents);
    ConnectViewModel.SomethingHappenedEvent += HandleSomethingHappened;
    connectEvents.ThrowEvent += ConnectToServer;
}
private void HandleSomethingHappened(object sender, EventArgs e)
{
    // Now your mainviewmodel knows that something happened
}

答案 3 :(得分:0)

这是一个使用已接受答案中提到的 WeakEventManager 的示例。

namespace Stuff {
    using System;
    using System.Windows;

    // An "event bus" public to all view models.
    public sealed class Events {
        public static Events Instance { get; } = new Events();

        public event EventHandler<EventArgs>? SomethingHappend;

        private Events() { }

        public static void RaiseSomethingHappend(object? sender = null)
            => Instance.SomethingHappend?.Invoke(sender ?? Instance, EventArgs.Empty);
    }

    // A view model that wants to listen to one or more events.
    public class Listener {
        public Listener() {
            WeakEventManager<Events, EventArgs>.AddHandler(
                source: Events.Instance,
                eventName: nameof(Events.SomethingHappend),
                Handle);
        }

        private void Handle(object? sender, EventArgs args) { }
    }

    // A view model that raises events.
    public class Source {
        public void Foo() {
            Events.RaiseSomethingHappend();
        }
    }
}