【问题标题】:Communicating between ViewModels with Events使用事件在 ViewModel 之间进行通信
【发布时间】:2013-10-10 03:31:34
【问题描述】:

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

子视图模型:

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

父视图模型

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

如何在这两者之间进行通信?有没有更好的系统,或者我怎样才能让父母订阅孩子?

【问题讨论】:

  • 如果你真的想实现 MVVM,你应该看看命令模式。
  • 是否可以将命令传递给另一个视图模型?它们有不同的数据上下文。
  • 这就是它的作用,看定义:en.wikipedia.org/wiki/Command_pattern

标签: c# wpf mvvm


【解决方案1】:

你有很多选择。您可以使用custom event,也可以直接使用delegate,您可以在父视图模型中订阅PropertyChangedCollectionChanged 事件,使用普通订阅或Weak Event Pattern

我更喜欢最后一个,因为不需要退订。

【讨论】:

    【解决方案2】:

    您可以制作自己的 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);
     }
    }
    

    借助它,您可以与视图模型进行通信

    【讨论】:

    • 仅针对使用此功能的其他人以及每个订阅者,您可能希望他们都做不同的事情。因此,您可以仅 DumbAggregator.OnMessageTransmitted += OnMessageReceived; 而不是创建一个类在每个类构造函数中,然后根据通过的消息创建特定的消息接收情况。这提供了很大的灵活性。
    【解决方案3】:

    使用事件传达“事件”

    在您的 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
    }
    

    【讨论】:

      【解决方案4】:

      这是一个使用已接受答案中提到的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();
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-02
        • 1970-01-01
        • 2019-07-11
        • 2013-02-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多