简体   繁体   English

WPF:在 MVVM 中管理窗口(打开、关闭等)?

[英]WPF: Managing windows (opening, closing, etc...) in MVVM?

I've read about it in a bunch of places.我在很多地方读到过它。 Most of the people are referring to these two links:大多数人都指的是这两个链接:

I don't understand either of them.我不明白他们中的任何一个。 I am a beginner when it comes to MVVM.说到 MVVM,我是初学者。 Some people are mentioning controllers when it comes to window manipulation in MVVM.当谈到 MVVM 中的窗口操作时,有些人会提到控制器。 What are those and how are they implemented?这些是什么以及它们是如何实施的? By book , MVVM is consisted of model, viewmodel and view - where do controllers come in?按照书本,MVVM 由模型、视图模型和视图组成——控制器从哪里来?

If someone could provide a sample of the following use case, that would be terrific (for all those people who are just getting started with this, as I am):如果有人可以提供以下用例的示例,那将是非常棒的(对于所有刚开始使用这个的人,就像我一样):

  1. Prerequisite: A window is opened.先决条件:打开一个窗口。
  2. User clicks a button.用户单击一个按钮。
  3. New window is opened and some data is passed to that window, ie some string.新窗口打开,一些数据被传递到那个窗口,即一些字符串。
  4. New window is closed (or a button is clicked) and some data is passed to the first window.关闭新窗口(或单击按钮)并将一些数据传递到第一个窗口。
  5. Passed data has changed something on the window.传递的数据改变了窗口上的某些内容。

The ViewModel to ViewModel communication is usually handled by an implementation of the Event Aggregator pattern. ViewModel 到 ViewModel 的通信通常由事件聚合器模式的实现来处理。

MVVM Light uses the Messenger class, Prism has another implementation but basically that is one way to send messages between View Models without coupling. MVVM Light 使用Messenger类,Prism 有另一种实现,但基本上这是一种在视图模型之间发送消息而无需耦合的方法。

There are some examples, and Articles describing the usage.有一些示例和描述用法的文章 I would suggest taking a look at it.我建议看一看。

Regarding the controllers stuff in WPF, I don't know.关于 WPF 中的控制器,我不知道。

Regarding the example:关于这个例子:

-I Have a Windows with its WindowsViewModel. -我有一个带有 WindowsViewModel 的 Windows。 This class should have a Command bound to the Button.这个类应该有一个绑定到按钮的命令。

-The user clicks the button. -用户点击按钮。 Executes the command.执行命令。

-The Command opens a new Window. -命令打开一个新窗口。

Here you should create the Dialog View Model and somehow you should create the Window.在这里您应该创建对话框视图模型,并且您应该以某种方式创建窗口。 Or create the Window with a ViewModel, but ViewModel shouldn't know much about the View otherwise is not testable.或者使用 ViewModel 创建 Window,但 ViewModel 不应该对 View 了解太多,否则无法测试。

We use something like this because we have some requirements, but it could be much much simplier, it happens it's the only example I have at hand:我们使用这样的东西是因为我们有一些要求,但它可能会简单得多,碰巧这是我手头唯一的例子:

bool? ShowDialogImpl<TViewModel>(Action<TViewModel> setup) where TViewModel : ViewModel
{
    return (bool?)DispatcherHelper.UIDispatcher.Invoke(
        (Func<bool?>)(() =>
        {
            var viewModel = viewModelFactory.Get<TViewModel>();
            viewModel.ViewService = this;
            setup(viewModel);
            var window = new Window
            {
                Owner = this,
                SizeToContent = SizeToContent.WidthAndHeight,
                WindowStartupLocation = WindowStartupLocation.CenterOwner,
                Content = ViewFactory.CreateView<TViewModel>(),
                DataContext = viewModel,
                WindowStyle = WindowStyle.ToolWindow,
                ShowInTaskbar = false
            };
            window.SetBinding(TitleProperty, new Binding("Title"));
            openDialogs.Push(window);
            window.Activated += (sender, args) => window.SizeToContent = SizeToContent.Manual;
            var result = window.ShowDialog();
            openDialogs.Pop();
            viewModelFactory.Release(viewModel);
            return result;
        }));
}

Basically: We create a window and with a view model.基本上:我们创建一个窗口和一个视图模型。 The view model is created from a factory using an container.视图模型是使用容器从工厂创建的。 The setup Action delegate is the entry point for our data. setup Action 委托是我们数据的入口点。

  • Communication:沟通:

The first Windows is a Grid, and the second Dialog to edit data of the grid.第一个窗口是网格,第二个对话框用于编辑网格的数据。 Inf the Windows we have:在 Windows 中,我们有:

messenger.Register<EntityUpdated<FooClass>>(this, message => UpdateItem(message.Entity));

And in the Dialog:在对话框中:

messenger.Send(new EntityUpdated<FooClass>(subject));

This way, we know when something was updated in the Edit Dialog in order to refresh the grid.这样,我们就知道何时在编辑对话框中更新了某些内容以刷新网格。

Hope this help you:)希望这对你有帮助:)

If you aren't planning on allowing the user to switch back and forth between the windows, while both are open (ie, the first opens the second, and the second must be closed to return to the first), you could simply set the viewmodel for both windows to the same viewmodel instance, and open the 2nd window as modal, and the strings you are passing back and forth, would simply be properties of the view model, with data bindings to something in the view.如果您不打算允许用户在两个窗口都打开时来回切换(即第一个打开第二个,第二个必须关闭才能返回到第一个),您可以简单地设置两个窗口的 viewmodel 到同一个 viewmodel 实例,并将第二个窗口打开为模态,并且您来回传递的字符串只是视图模型的属性,数据绑定到视图中的某些内容。

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

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