从ViewModel打开/关闭视图

fra*_*sg3 5 c# wpf view mvvm viewmodel

我有一个AddClientViewModel,由2个视图(AddClientView和SuggestedAddressesView)引用.AddClientView是一个具有地址字段的表单.表单有一个验证按钮,使用地理编码验证输入的地址.如果返回多个地址,则打开SuggestedAddressesView.

以下是我目前的做法:

AddClientViewModel:

    private void ValidateExecute(object obj)
    {
        SuggestedAddresses = new ObservableCollection<DBHelper.GeocodeService.GeocodeResult>(GeoCodeTest.SuggestedAddress(FormattedAddress));

        ....

        if (SuggestedAddresses.Count > 0)
        {
            var window = new SuggestedAddressesView(this);
            window.DataContext = this;
            window.Show();
        }
    }
Run Code Online (Sandbox Code Playgroud)

这是SuggestedAddressesView构造函数,其中AddClientViewModel从ViewModelBase继承

    public SuggestedAddressesView(ViewModelBase viewModel)
    {
        InitializeComponent();
        viewModel.ClosingRequest += (sender, e) => this.Close();
    }
Run Code Online (Sandbox Code Playgroud)

我遇到的另一个问题是当我从AddClientViewModel调用OnClosingRequest()时... AddClientView和SuggestedAddressesView都关闭.我知道这是因为两个视图都引用了相同的ViewModel.这不是我想要的行为.我希望能够独立关闭任一窗口.

从ViewModel正确的MVVM结构打开一个View,我将如何独立关闭窗口?

Viv*_*Viv 5

一旦从VM引用UI元素(在本例中为View),您就会反对建议的MVVM准则.只有这样我们才能知道Window在VM中创建对象是错误的.

所以现在纠正这个:

  • 首先尝试在应用程序中保留1个View < - > 1 VM.它更干净,允许您使用相同的逻辑轻松切换View实现.将多个View添加到同一个VM即使不是"突破性的"也只是让它变得笨拙.
  • 所以,现在你得到了AddClientView,并SuggestedAddressesView用自己的VM.大!

从VM实现视图打开/关闭:

  • 由于我们无法直接从我们的VM访问View(为了符合标准),我们可以使用诸如使用Messenger(MVVM Light),EventAggregator(PRISM)等方法从VM向View发送"消息"需要打开/关闭视图并在视图中执行实际操作.
  • 这样,VM只是启动消息,并且可以针对相同的操作进行单元测试,并且不引用任何UI元素.

使用"Messenger"方法处理View 打开:

  • 根据你的逻辑,它是AddClientViewModel必须要求SuggestedAddressesView打开的.
  • 因此,当您检测到时SuggestedAddresses.Count > 0,您会向AddClientView要求它打开的消息发送消息SuggestedAddressesView.
  • AddClientView.xaml.cs收到此消息时,你会做你正在做的VM什么.创建一个对象SuggestedAddressesView并调用.Show() 它.
  • 您将添加在上述步骤的过程中的一个额外的步骤是指定DataContextSuggestedAddressesView作为SuggestedAddressesViewModel.

而已.现在你拥有的是,当显示AddClientViewModel想要的时候SuggestedAddressesView,它会向它自己的View发送一条消息,然后View依次创建并显示SuggestedAddressesView.这样VM就不会引用任何View,我们仍然坚持MVVM标准.

使用"Messenger"方法处理View close:

  • 关闭a View非常简单.再次当您需要从VM关闭View时,您会向其自己的View发送一条消息,要求将其关闭.
  • 收到此消息后,View几乎会通过.Hide()/ .Close()或者您希望摆脱它而自行关闭.

在这个中,每个VM处理它自己的View的关闭,并且您没有任何相互连接的依赖关系.

您可以将此作为一个起点,指导您处理此方法的"消息".它有一个附加的下载,你可以得到,看看它是如何Messenger工作的.这是MVVM Light,如果您不使用它或使用其他/您自己的MVVM实现,请将其用作指南以帮助您获得所需内容.