我正在开发一个MVVM wpf应用程序,我需要显示各种对话框,取消确定。我在网上看到的很少,但看起来过于复杂,或者可能是我的挣扎。
我注意到很多人使用“IDialogService”
任何人都可以指向一个链接,或者有一个方便片段,介绍如何使用MVVM模式实现Dialog?
非常感谢
答案 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; }