欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

WPF随笔(十三)--MVVM模式下的窗口管理

程序员文章站 2022-03-07 13:29:00
...

使用MVVM模式的WPF项目和传统的使用事件驱动模式的WPF在处理逻辑有所不同,即使最简单的打开窗口也有很大差异。


1.创建窗口管理类

    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();
        }

    }

2.添加窗口类扩展

    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);
        }
    }

3.创建ViewModel层基类

在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

4.窗口注册

在主窗口类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;
        }
    }

5.窗口使用

在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


    }
相关标签: WPF