【问题标题】:WPF & MVVM - Close Window from within Child controlWPF & MVVM - 从子控件中关闭窗口
【发布时间】:2015-04-09 11:19:08
【问题描述】:

我需要根据在窗口中显示的控件中触发的单击命令从 ViewModel 关闭模式窗口。

所以,我有 MainViewModel、JimViewModel、JimWindow 和 JimControl。 MainViewModel 创建一个 JimWindow 并将其 DataContext 设置为 JimViewModel。 JimWindow 包含 JimControl,其中包含一个按钮。单击此按钮时,我想触发一个以某种方式关闭 JimWindow 的命令。

我已经看到了一些关于从实际窗口关闭窗口的问题(通过将窗口实例传递给 ViewModel 上的命令),但它并没有转化为我想要的做。

我没有使用框架,所以我没有方便的信使来帮助我。任何人都可以帮忙吗?是否以某种方式从控件中引用父窗口的名称?

【问题讨论】:

  • 由于窗口关闭与视图严格相关,我想说覆盖事件以调用命令(如果需要)并关闭窗口比在命令中提供该功能的视图模型更好。
  • 这个关闭的调用会在哪里呢?关闭窗口的按钮位于窗口内部的控件中。窗口是否应该将对自身的引用传递给控件?
  • 该函数将在窗口上下文中被覆盖。也就是说,覆盖类将是窗口,因此可以调用Close()。这会将代码添加到代码应该稀缺的地方,但我认为它不属于 VM 中的代码。我没有足够的经验来了解所有其他可用选项。

标签: c# wpf mvvm controls


【解决方案1】:

虽然ViewModel 创建View 的想法听起来有点倒退,但您可以使用消息传递,例如TinyMessengerMVVMLight自带的Messenger。

然后您可以在您的视图/视图模型中注册一条消息并从任何地方发送它。使用 MVVMLight 的一个非常简单的示例可能是:

// custom message
public class CloseMessage : MessageBase
{
    public CloseMessage(object sender)
        :base(sender)
    {}
}

// main view registers for a message
public partial class MainWindow : Window
{
    public MainWindow()
    {
        Messenger.Default.Register<CloseMessage>(this, message =>
        {
            // do teh stuff
        });
    }
    ...
}

// command bound to close button sends the message
private void YourCloseMainViewCommand()
{
    Messenger.Default.Send(new CloseMessage(this));
}

【讨论】:

  • 我不确定我是否遵循。我真的不太了解 Messenger 课程。 JimWindow 会在我的 MainWindow(或者更确切地说,在我的情况下为 MainControl)类中创建为实例吗?
  • 没关系。您可以在任何需要的地方注册/发送消息。
  • 实际上,如果您想看一看,我在github.com/mikkoviitala/cross-viewmodel-communication 设置了一个旧的 repo 来演示 MVVM 消息传递。
  • 我会浏览一下,干杯。不过,就外部类而言,我可以使用的东西有限。
  • 有许多库,来自 Microsoft 和第 3 方,它们使 MVVM 实现更快、更干净、更有趣。不使用任何东西都是愚蠢的,浪费金钱/精力:)
【解决方案2】:

MainViewModel 不应该创建窗口,至少不应该直接创建。虚拟机应该只创建虚拟机。窗口是视图世界的一部分。

如果您需要将JimVM 托管在窗口中,那么最好将某种WindowService 抽象到接口后面。 MainVM 然后只创建 JimVM 并将其提供给窗口服务以托管在窗口中

一旦您将 Windows 位解耦为一个单独的服务,您就可以在其中完成所有繁琐的窗口操作。我会让JimVM 公开CloseCommandClosed 事件。您可以将JimControl 按钮绑定到CloseCommand,Windows 服务可以订阅Close 事件,并在窗口触发时将其拆除。

这使视图和 VM 内容完全分开。唯一知道如何将两者粘合在一起的是窗口管理器。

【讨论】:

    猜你喜欢
    • 2020-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多