使用MVVM模式的WPF项目和传统的使用事件驱动模式的WPF在处理逻辑有所不同,即使最简单的打开窗口也有很大差异。
public static class WindowManager
{
private static Hashtable _RegisterWindow = new Hashtable();
//注册窗口
public static void Regiter<T>(string key)
{
_RegisterWindow.Add(key, typeof(T));
}
//注册窗口
public static void Regiter(string key, Type t)
{
if (!_RegisterWindow.ContainsKey(key))
_RegisterWindow.Add(key, t);
}
//移除窗口
public static void Remove(string key)
{
if (_RegisterWindow.ContainsKey(key))
_RegisterWindow.Remove(key);
}
//打开窗口
public static void ShowDialog(string key, object VM)
{
if (!_RegisterWindow.ContainsKey(key))
{
throw (new Exception("没有注册此键!"));
}
var win = (Window)Activator.CreateInstance((Type)_RegisterWindow[key]);
win.DataContext = VM;
win.ShowDialog();
}
//打开窗口
public static void ShowDialog(string key, object model,Window window)
{
if (!_RegisterWindow.ContainsKey(key))
{
throw (new Exception("没有注册此键!"));
}
var win = (Window)Activator.CreateInstance((Type)_RegisterWindow[key]);
win.DataContext = model;
win.Owner = window;
win.ShowDialog();
}
}
public static class WindowExtension
{
public static void Register(this Window win, string key)
{
WindowManager.Regiter(key, win.GetType());
}
public static void Register(this Window win, string key, Type t)
{
WindowManager.Regiter(key, t);
}
public static void Register<T>(this Window win, string key)
{
WindowManager.Regiter<T>(key);
}
}
在ViewModel层的基类ViewModelBase中,除了定义打开Window窗口的方法外,还有MessageBox消息弹出框、文件选择对话框和文件夹选择对话框。
public class ViewModelBase : INotifyPropertyChanged
{
#region Window-窗口管理
//打开窗口
public void ShowDialog(string key, object vm)
{
WindowManager.ShowDialog(key, vm);
}
//打开窗口并设置所属窗口
public void ShowDialog(string key,object args,Window owner)
{
WindowManager.ShowDialog(key, args, owner);
}
//消息提示框
public void ShowMessage(string mes, string title = "", MessageBoxButton buttons = MessageBoxButton.OK)
{
MessageBox.Show(mes, title, buttons);
}
//带返回结果的消息提示框
public bool ShowMessageWithResult(string content,string title="",MessageBoxButton button=MessageBoxButton.OKCancel)
{
if (MessageBox.Show(content, title,button)==MessageBoxResult.OK)
{
return true;
}
else
{
return false;
}
}
//文件选择对话框
public string ShowFileDialog(string title,string filter="docx|*.docx",string folder= "C:\\Users\\Administrator\\Desktop")
{
string filePath = "";
SaveFileDialog dialog = new SaveFileDialog();
dialog.Title = title;
dialog.Filter = filter;
dialog.InitialDirectory = folder;
if (dialog.ShowDialog()==true)
{
filePath = dialog.FileName;
}
return filePath;
}
//文件夹选择对话框
public string ShowFolderDialog(string title)
{
string folderPath = "";
System.Windows.Forms.FolderBrowserDialog dialog = new System.Windows.Forms.FolderBrowserDialog();
dialog.RootFolder = Environment.SpecialFolder.MyDocuments;
dialog.ShowNewFolderButton = true;
dialog.Description = title;
if (dialog.ShowDialog()==System.Windows.Forms.DialogResult.OK)
{
folderPath = dialog.SelectedPath;
};
return folderPath;
}
#endregion
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected internal virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
注意:示例采用是,NET Core 3.1开发环境,文件选择对话框SaveFileDialog 需要引用Microsoft.Win32,文件夹选择对话框FolderBrowserDialog需要手动引用C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\3.1.1目录下的System.Windows.Forms.dll
在主窗口类MainWindow.xaml.cs中通过名称注册新的窗口。
public partial class MainWindow : MetroWindow, ISingletonDependency
{
private MainWindowViewModel _viewModel;
public static MetroWindow Instance
{
get; private set;
}
public MainWindow()
{
_viewModel = new MainWindowViewModel();
this.DataContext = _viewModel;
InitializeComponent();
this.Register<DemoView>("DemoView");//注册窗口
Instance = this;
}
}
在ViewModel层的类中,由于已经继承了基类ViewModelBase,窗口管理相关的类都可以直接使用。
public class MainWindowViewModel : ViewModelBase
{
public MainWindowViewModel()
{
OpenDemoCommand = new DelegateCommands<string>(OpenDemoWindow);
}
#region Commands
public DelegateCommands<string> OpenDemoCommand { get; set; }
#endregion
#region Methods
#region 打开窗口示例
private void OpenDemoWindow(string obj)
{
DemoViewModel viewModel = new DemoViewModel ();
ShowDialog("DemoView", viewModel, MainWindow.Instance);
}
#endregion
#endregion
}