【问题标题】:Can I access main Window ViewModel from others child windows ViewModel我可以从其他子窗口 ViewModel 访问主窗口 ViewModel
【发布时间】:2019-11-25 13:21:50
【问题描述】:

首先,如果这很简单,我必须道歉。我对 WPF 和 MVVM 非常陌生,我想确保我没有违反任何 WPF 或 MVVM 概念。另外,对于下面的冗长解释(试图给出所有细节):

我目前正在引用具有所有业务逻辑或服务层(服务类、实体类、数据操作等)的 Assembly dll。

这用于其他传统的 Windows 窗体应用程序。我现在正在创建一个新的桌面 WPF 应用程序(早期阶段),我必须使用相同的程序集。

我创建了一个带有菜单、状态栏等的主窗口及其 ViewModel(我们称之为 _mainViewModel)。

我用自己的 ViewModel 对象创建了另一个简单的窗口(让我们称为 _abcViewModel)。 Windows 对象/控件在子视图中绑定良好。这很好用,到目前为止我很满意。

_abcViewModel 使用程序集的逻辑,可以使用传统的委托和事件处理程序检索一些消息。

现在,我的意图是将来自这些事件的消息绑定到绑定到 _mainWindowViewModel.StatusBarItemMessage 的主窗口状态栏对象。我怎样才能做到这一点?

我从另一个 stackoverflow 帖子 (:How to access WPF MainWindow Controls from my own .cs file) 中发现,您可以使用以下方式访问主窗口对象: ((MainWindow)System.Windows.Application.Current.MainWindow)._mainWindowViewModel.StatusBarMessage = args.Message;

我在 _abcViewModel 中订阅了那些 DLL 事件处理程序:

    private void SubscribeBusinessLogicEvents()
    {
        _SPPIDDrawingWPFService.PidToolBoxInfoEvent += new SPPIDDrawingWPFService.PidToolBoxInfoEventHandler(PidToolBoxInfoEvent);
        _SPPIDDrawingWPFService.PidToolBoxErrorEvent += new SPPIDDrawingWPFService.PidToolBoxErrorEventHandler(PidToolBoxErrorEvent);
    }


    private void UnsubscribeBusinessLogicEvents()
    {
        _SPPIDDrawingWPFService.PidToolBoxInfoEvent -= PidToolBoxInfoEvent;
        _SPPIDDrawingWPFService.PidToolBoxErrorEvent -= PidToolBoxErrorEvent;

    }


    internal void PidToolBoxErrorEvent(object sender, PidToolBoxEventArg args)
    {
        App.WriteLocalErrorLogFile(args);
    }


    internal void PidToolBoxInfoEvent(object sender, PidToolBoxEventArg args)
    {
        //Is this correct? Can I change Main Windows view model from here?
        ((MainWindow)System.Windows.Application.Current.MainWindow)._mainWindowViewModel.StatusBarItemMessage = args.Message;
        if (args.OptionalPopUpFlag)
        {
            //
        }
        App.WriteWoodEngSysToolBoxErrorLog(args);
    }

这是正确的方法吗?从其他 ViewModel 访问 ViewModel 是否违反了 Model-view-viewmodel 或 MVVM 的概念?

如何从子窗口执行的操作中更新主窗口状态栏控件。我不希望所有窗口都有一个庞大的 ViewModel 对象。

任何帮助/建议将不胜感激。 谢谢

【问题讨论】:

    标签: wpf mvvm


    【解决方案1】:

    查看事件聚合。您的 MainWindowViewmodel 应该订阅 AbcViewModel 广播的“事件”。这将使您的 AbcViewModel 与 MainWindowViewModel 分离。

    Prism 是一个实现此模式的库。该库可能无法满足您的需求,但您可以轻松实现自己的系统。

    您的用法可能类似于:

    AbcViewModel.cs

     internal void PidToolBoxInfoEvent(object sender, PidToolBoxEventArg args)
     {
            _eventAggregator.GetEvent<PidToolBoxUpdateEvent>().Publish(args);
    
            App.WriteWoodEngSysToolBoxErrorLog(args);
      }
    

    MainWindowViewModel.cs

    public class MainWindowViewModel
    {
        public MainWindowViewModel(IEventAggregator ea)
        {
            // You may need to subscribe on the UI thread. 
            // If so, use: Subscribe(..., ThreadOption.UIThread) 
            ea.GetEvent<PidToolBoxUpdateEvent>().Subscribe(UpdateStatusBar);
        }
    
        void UpdateStatusBar(PidToolBoxEventArg pidEventArgs)
        {
            //implement logic
        }
    }
    

    【讨论】:

    • 哇,真快。非常感谢迈克尔您的快速回复。我将看看 Prism 事件聚合,看看它是如何工作的。我今天已经完成了,但我明天会看看然后再找你。谢谢
    • 嗨,迈克尔。 IEventAggregator 为我工作。我必须在执行 GetEvent(xxx).Publish(Args) 的 AbcViewModel 中使用 BackgroundWorker。现在它令人耳目一新。我所做的是: 1.-将 App.xaml.cs 中的主要 IEventAggregator 对象创建为静态。 2.-将 EventAggregator 对象传递给两个 viewModels 构造函数 3.-订阅程序集事件处理程序并在 backgroundWorker 中执行进程...问题。我可以直接从模型中与静态 ea 交互,而不是通过构造函数传递它吗?或者这会违反 MVVM 理念?
    • 抱歉,我之前的评论问题令人困惑。我想问我是否可以从 ViewModel 访问静态 EventAggregator 对象(在 App.xaml.cs 中创建)而不是通过 ViewModel 的构造函数传递它?或者那是针对 MVVM 的。谢谢迈克尔。真的很感激
    • 您可以通过静态构造函数提供单例实例——但是,最好利用依赖注入进行测试。不要忘记接受这个答案作为回答:)
    • 谢谢迈克尔。我接受了回答。但是,由于我是新手,所以我没有足够的声誉来投票赞成有用的答案....没关系...非常感谢您的帮助
    猜你喜欢
    • 2017-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-08
    • 1970-01-01
    • 2014-08-07
    • 1970-01-01
    相关资源
    最近更新 更多