确定取消对话框MVVM模式wpf。我该怎么办呢

时间:2010-11-16 21:28:07

标签: wpf mvvm

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

我注意到很多人使用“IDialogService”

任何人都可以指向一个链接,或者有一个方便片段,介绍如何使用MVVM模式实现Dialog?

非常感谢

4 个答案:

答案 0 :(得分:13)

这是一个带有“确定”和“取消”按钮的准系统对话框。我已经包含了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。

希望这会有所帮助......

答案 1 :(得分:8)

我认为使用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.

我更喜欢这种方法,因为它简单易用。其他人的想法是什么?

答案 2 :(得分:0)

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

答案 3 :(得分:-1)

从ViewModel的代码中调用System.Windows.MessageBox.Show()有什么问题

e.g。

public bool GetConfirmation(string Message, string Caption)
{ return MessageBox.Show(Message, 
                         Caption, 
                         System.Windows.MessageBoxButton.OKCancel, 
                         System.Windows.MessageBoxImage.Question, 
                         System.Windows.MessageBoxResult.Cancel) == System.Windows.MessageBoxResult.OK; }