繁体   English   中英

我们可以从 ViewModel 向 View 发起事件吗?

[英]Can we raise an event from ViewModel to View?

例如,我的ViewModel做了一些事情。 在那之后,我想通知我的View以便做一些只能在View中完成的事情。

就像是;

public class MyViewModel : ViewModelBase{
  ...
  private void DoSomething(){
     //raise the event here and notify the View
  }
}

然后在视图中;

public MyView(){
  InitializeComponent();
  ...
}

private void ViewModelSaidDoSomething(){
 //The View Model raises an event, do something here about it...
}

在不破坏 MVVM 概念的情况下这可能吗?

是的,这是可能的。 通常,您可以做的是从您的ViewModel定义事件,然后让您的View订阅该事件。

例如,在您的 ViewModel 中。

public class MyViewModel : ViewModelBase{
  ...
  //Define your event.
  public delegate void YourEventAction(string your_argument); 
  public event YourEventAction? YourEvent;
  
  private void DoSomething(){
     YourEvent?.Invoke(your_argument); //raise the event here, any subscriber will received this.
  }
}

然后您可以在您的视图中订阅该事件。

public MyView(){
  InitializeComponent();
  ...
  DataContextChanged += ViewModelSaidDoSomething; //subscribe to DataContextChanged.
}

private void ViewModelSaidDoSomething(){ 
    var viewModel = (MyViewModel)DataContext; //Get your ViewModel from your DataContext.
    viewModel.YourEvent += (your_argument) =>{  //Subscribe to the event from your ViewModel.
        //The View Model raises an event, do something here about it...
    };
}

希望有帮助。

我对任何视图模型 <-> 视图通信的主要候选人都是绑定的。 这是一个弱事件模式,后期绑定,视图不需要知道视图模型是什么类型。 他们在实现绑定方面遇到了很多麻烦,而且 IMO 运行良好。 无论如何,绑定意味着视图和视图模型在保持合理实用性的同时尽可能松散耦合。

这是一个例子。 目的是允许视图模型关闭 window。

视图功能封装在控件中。 只有代码。

public class CloseMe : Control
{
    public bool? Yes
    {
        get
        {
            return (bool?)GetValue(YesProperty);
        }
        set
        {
            SetValue(YesProperty, value);
        }
    }
    public static readonly DependencyProperty YesProperty =
        DependencyProperty.Register("Yes",
                    typeof(bool?),
                    typeof(CloseMe),
                    new PropertyMetadata(null, new PropertyChangedCallback(YesChanged)));
    private static void YesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if ((bool?)e.NewValue != true)
        {
            return;
        }
        CloseMe me = (CloseMe)d;
        Window parent = Window.GetWindow(me) as Window;
        parent.Close();
    }
}

window 或用户控件中的任何位置进入您要关闭的 window :

   <local:CloseMe Yes="{Binding CloseYes, Mode=TwoWay}"/>

这绑定到视图模型中的布尔属性 CloseYes。 设置为真,window 关闭。

我们可以想象将一些数据封装在更复杂的视图模型 object 中,而不仅仅是 boolean。 但这不会那么优雅。 视图不应该处理数据,所以如果您要发送复杂数据,我会质疑您在做什么。

不过把这些疑虑放在一边。

如果您想通过松耦合将复杂类型从 A 转移到 B,那么 pub sub 模式是一个不错的选择。
mvvm 工具包是我的首选框架,其中有一个您可以使用的实现。 信使: https://docs.microsoft.com/en-us/windows/communitytoolkit/mvvm/messenger

发送的消息是您定义的 object,您可以使用 WeakReferenceMessenger。 它做了它所暗示的并依赖于弱引用。 从而降低 memory 泄漏的风险。 其他框架具有类似的机制,因此您可以查看您喜欢的框架中的内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM