【问题标题】:Ok cancel Dialog MVVM Pattern wpf.How can I do it好的取消对话框 MVVM 模式 wpf。我该怎么做
【发布时间】:2011-05-11 02:15:34
【问题描述】:

我正在开发一个 MVVM wpf 应用程序,我需要显示各种带有确定取消的对话框。我在网上看到的很少,但看起来过于复杂或可能是我在挣扎。

我注意到很多使用“IDialogService”

任何人都可以给我一个链接或者有一个关于如何使用 MVVM 模式实现对话框的方便的 sn-p 吗?

非常感谢

【问题讨论】:

  • 在我尝试回答之前,一些上下文可能会有所帮助:你为什么使用 MVVM?你是团队合作还是单独工作?您是否对表示层进行单元测试?如果是,您是否熟悉模拟框架?
  • 您遇到了什么问题? (显示对话框?关闭对话框?将对话框连接到您的 ViewModel?其他?)另外,您使用的是 MVVM 框架,如果是,是哪一个?
  • 对不起。我认为这是一个非常笼统的问题。因此没有代码。我使用 Moq 作为 Mocking 框架。理想情况下,我想对它进行单元测试。在实际工作项目中,我有一个使用 PL-SL-BL-DAL 的断开连接的架构。我不想混淆人们或提出问题。我只是想要并希望获得有关如何使用 MVVM 模式显示对话框的帮助。我不能使用任何框架。我们使用内部框架。一旦我抓住上下文并可以将其转移到我的实际项目中。

标签: wpf mvvm


【解决方案1】:

这是一个带有“确定”和“取消”按钮的准系统对话框。我已经包含了 XAML、View 和 ViewModel:

XAML:

<Window
    x:Class="TestProject.Views.OKCancelDialog"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
    Title="Window Title"
    Height="300"
    Width="600"
    WindowStartupLocation="CenterOwner"
    WindowStyle="ToolWindow"
    ResizeMode="CanResize"
    UseLayoutRounding="True"
    TextOptions.TextFormattingMode="Display">

    <Grid>
        <Button
            Name="OKButton"
            Content="OK"
            Height="23"
            HorizontalAlignment="Right" 
            Margin="0,0,93,12"
            VerticalAlignment="Bottom" 
            Width="75" 
            Click="OKButton_Click"
            IsDefault="True"
            Command="{Binding OKButtonCommand}" />

        <Button
            Name="CancelButton"
            Content="Cancel" 
            Height="23" 
            HorizontalAlignment="Right" 
            Margin="0,0,12,12"
            VerticalAlignment="Bottom"
            Width="75" 
            IsCancel="True" />
    </Grid>
</Window>

代码隐藏:

using System.Windows;
using TestProject.ViewModel;

namespace TestProject.Views
{
    public partial class OKCancelDialog : Window
    {
        private readonly OKCancelViewModel viewModel;

        //I use DI to inject the ViewModel into the View
        //This will allow you to use the view for different ViewModels if you need to.
        //Create an Interface for your ViewModel to implement to make ViewModel unit testing
        //easier. Testing frameworks such as rhino mock require Interfaces to test methods
        //in a class under test and it allows you to use an IoC Container to create the
        //ViewModel for you.                 
        public OpenReturnDialog(IOKCancelViewModel viewModel)
        {
            InitializeComponent();
            this.viewModel = viewModel; //Do this if you need access to the VM from inside your View. Or you could just use this.Datacontext to access the VM.
            this.DataContext = viewModel;
        }

        private void OKButton_Click(object sender, RoutedEventArgs e)
        {
            DialogResult = true;
        }

    }
}

视图模型

using Microsoft.Practices.Composite.Presentation.Commands;


namespace TestProject.ViewModel
{
    public class OKCancelViewModel
    {
        public OKCancelViewModel()
        {
            OKButtonCommand = new DelegateCommand<object>(HandleOKButtonCommand, CanExecuteOKButtonCommand);
        }

        public DelegateCommand<object> OKButtonCommand { get; private set; }

        public void HandleOKButtonCommand(object obj)
        {
             //Here is where your code for OK button clicks go.

        }

        public bool CanExecuteOKButtonCommand(object obj)
        {
            //Put code to determine when the OK button will be enabled/disabled.
        } 

        //You may want to add a command for the Cancel button also if you have a need to 
        //enable/disable the cancel button
        //The command will look just like the OK button command above.
    }
}

现在,如果您的 UI 中有其他控件将绑定到 ViewModel 中的属性,您很可能希望让您的 ViewModel 实现 INotifyPropertyChanged。

希望这会有所帮助...

【讨论】:

  • 感谢您对代码的回复。我刚刚创建了一个 noddy 项目并将您的代码放入其中。我有 2 个窗口。你的 OKCancelDialog 和 MainWindow。 MainWindow 有一个按钮“启动对话框。你如何用你的代码做到这一点?
  • 嗯,人们的意见不同。我还没有找到最佳实践,所以我会告诉你我是如何做到的。您的主窗口还应该有一个带有“LaunchDialogCommand”的虚拟机——就像我上面代码中的命令一样。在“HandleLaunchDialogCommand”内部,您有创建 OKCancelViewModel 和 OKCancelView 的代码。像这样: var dlg = new OKCancelView(new OKCancelViewModel());现在,这里有很多不同的意见。你可以调用 OKCancelView.ShowDialog();但是由于你在虚拟机中,大多数人觉得在虚拟机中调用 ShowDialog() 是错误的。
  • 在这种情况下,大多数人都会引发一个其他类订阅并调用 ShowDialog() 的事件。我有点懒,所以我通常只在 ViewModel 中调用 ShowDialog()。看看这个链接:stackoverflow.com/q/1730290/195356
  • 好的。到目前为止很好,但是如何从视图模型中消除视图?如果用户点击 OK,假设我们保持 MVVM 模式,视图如何知道是时候退出了。
【解决方案2】:

我认为使用 IDialogService 或实际创建自己的对话框的其他所有人都过度设计了问题。我真的很喜欢使用 Funcs 的简单方法。这是一个例子。首先将其添加到您的 ViewModel:

public abstract class ViewModelBase : INotifyPropertyChanged
{
    /** Other ViewModel Code *//

    public Func<string, string, bool> OkCancelDialog { get; set; }
}

然后,当您实例化 ViewModel 的派生类时,您只需附加以下代码:(我通常在 Program.cs 之类的启动中执行此操作)

var myVM = new SomeSuperViewModel();
myVM.OkCancelDialog = (msg, caption) => MessageBox.Show(msg, caption, MessageBoxButton.OkCancel) == MessageBoxResult.OK;

在您的实际 ViewModel 代码中,您所要做的就是调用:

if (OkCancelDialog("Some crazy message.", "Caption"))
    //do something if true
else
    //else do something if false

在您的单元测试中,您可以这样做:

var myVMToTest = new SomeSuperViewModel();
myVMToTest.OkCancelDialog = (msg, caption) => true; //could be false too if you need to test that functionality.

我更喜欢这种方法,因为它简单且易于测试。别人怎么看?

【讨论】:

    【解决方案3】:

    您可以查看 WPF Application Framework (WAF)ViewModel (EmailClient) 示例应用程序。它展示了如何使用 MVVM 编写自定义对话框,并展示了如何在不违反 MVVM 模式的情况下使用 MessageBox。

    【讨论】:

      猜你喜欢
      • 2011-09-09
      • 2021-05-31
      • 2020-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-16
      • 2014-07-17
      • 1970-01-01
      相关资源
      最近更新 更多