WPF MVVM模式中,通过命令实现窗体拖动、跳转以及显隐控制

简介: 原文:WPF MVVM模式中,通过命令实现窗体拖动、跳转以及显隐控制在WPF中使用MVVM模式,可以让我们的程序实现界面与功能的分离,方便开发,易于维护。但是,很多初学者会在使用MVVM的过程中遇到一个显而易见且无法回避的问题,那就是不同的窗体之间如何跳转?很多人在介绍MVVM的使用时,都没有明显提到该如何解决这一问题,不知是因为觉得太简单了还是其他原因。
原文: WPF MVVM模式中,通过命令实现窗体拖动、跳转以及显隐控制

在WPF中使用MVVM模式,可以让我们的程序实现界面与功能的分离,方便开发,易于维护。但是,很多初学者会在使用MVVM的过程中遇到一个显而易见且无法回避的问题,那就是不同的窗体之间如何跳转?很多人在介绍MVVM的使用时,都没有明显提到该如何解决这一问题,不知是因为觉得太简单了还是其他原因。

博主根据自己的开发经验,写了一个简单的示例程序,介绍MVVM模式中,如何通过命令来控制窗体的跳转、拖动与显隐控制。

先看效果:

搜狗截图20150904171343

主窗体中只有一个按钮,点击该按钮后,可以打开新的窗。

搜狗截图20150904171406

新窗体可以为自定义样式窗体,鼠标拖动标题框,可以拖动整个窗体,点击关闭按钮,窗体隐藏。

下面是实现操作:

1.定义命令类ActionCommand.

使用MVVM模式的第一步,就是要实现自己的命令类。

public class ActionCommand<T> : ICommand where T : class
    {
        private Predicate<T> _canExecuteMethod;
        private Action<T> _executeMethod;

        public ActionCommand(Action<T> executeMethod)
        {
            _canExecuteMethod = null;
            _executeMethod = executeMethod;
        }

        public ActionCommand(Action<T> executeMethod, Predicate<T> canExecuteMethod)
        {
            _canExecuteMethod = canExecuteMethod;
            _executeMethod = executeMethod;
        }

        public bool CanExecute(object parameter)
        {
            return _canExecuteMethod == null ? true : _canExecuteMethod(parameter as T);
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            if (_executeMethod != null)
            {
                _executeMethod(parameter as T);
            }
            UpdateCanExecute();
        }

        public void UpdateCanExecute()
        {
            var handls = CanExecuteChanged;
            if (handls != null)
            {
                handls(this, new EventArgs());
            }
        }
    }

2.在App.xaml中定义窗体导航实现代码以及窗体操作命令

/// <summary>
    /// App.xaml 的交互逻辑
    /// </summary>
    public partial class App : Application
    {
        private static bool _bDebug = true;
        public static void MessageBox(string text, string caption)
        {
            if (_bDebug)
            {
                System.Windows.MessageBox.Show(text, caption);
            }

        }

        private static Dictionary<string, Window> _cacheWindow = new Dictionary<string, Window>();
        public static Window NavigationToWindow(string wndUri, bool createNew = false, bool cache = true, string cacheKey = null)
        {
            Window window = null;
            string key = string.IsNullOrWhiteSpace(cacheKey) ? wndUri : cacheKey;
            if (createNew)
            {
                window = App.Current.GetType().Assembly.CreateInstance(wndUri) as Window;
                if (cache && window != null)
                {
                    if (!_cacheWindow.ContainsKey(key))
                    {
                        _cacheWindow.Add(key, window);
                    }
                }
            }
            else
            {
                if (_cacheWindow.ContainsKey(key))
                {
                    window = _cacheWindow[key];
                }
                else
                {
                    window = App.Current.GetType().Assembly.CreateInstance(wndUri) as Window;
                    if (cache && window != null)
                    {
                        _cacheWindow.Add(key, window);
                    }
                }
            }
            return window;
        }


        /// <summary>
        /// 显示窗体命令
        /// </summary>
        public static ICommand ShowWindowCommand
        {
            get
            {
                return new ActionCommand<string>(p =>
                    {
                        if (string.IsNullOrWhiteSpace(p))
                        {
                            App.MessageBox("参数不能为空!", "[App][ShowWindowCommand]");
                            return;
                        }
                        string[] arrs = p.Split(',');

                        string wndUri = null, cacheKey = null;
                        bool createNewWnd = false, cacheWnd = true;
                        try
                        {
                            if (arrs.Length > 3)
                            {
                                wndUri = arrs[0];
                                createNewWnd = Convert.ToBoolean(arrs[1]);
                                cacheWnd = Convert.ToBoolean(arrs[2]);
                                cacheKey = arrs[3];
                            }
                            else if (arrs.Length > 2)
                            {
                                wndUri = arrs[0];
                                createNewWnd = Convert.ToBoolean(arrs[1]);
                                cacheWnd = Convert.ToBoolean(arrs[2]);
                            }
                            else if (arrs.Length > 1)
                            {
                                wndUri = arrs[0];
                                createNewWnd = Convert.ToBoolean(arrs[1]);
                            }
                            else
                            {
                                wndUri = arrs[0];
                            }
                            Window window = NavigationToWindow(wndUri, createNewWnd, cacheWnd, cacheKey);
                            if (window == null)
                            {
                                App.MessageBox("未找到导航窗体" + "[" + wndUri + "]", "[App][ShowWindowCommand]");
                                return;
                            }
                            window.Owner = App.Current.MainWindow;
                            if (!window.IsVisible)
                            {
                                window.Show();
                            }
                            else
                            {
                                window.Hide();
                            }
                        }
                        catch (Exception ex)
                        {
                            App.MessageBox(ex.Message, "[App][ShowWindowCommand]");
                        }

                    }
                    );
            }
        }

        /// <summary>
        /// 隐藏窗体命令
        /// </summary>
        public static ICommand HideWindowCommand
        {
            get
            {
                return new ActionCommand<string>(p =>
                {
                    if (string.IsNullOrWhiteSpace(p))
                    {
                        App.MessageBox("参数不能为空!", "[App][HideWindowCommand]");
                        return;
                    }

                    Window window = App.NavigationToWindow(p);
                    if (window != null)
                    {
                        window.Hide();
                    }
                }
                );
            }
        }

        /// <summary>
        /// 拖动窗体命令
        /// </summary>
        public static ICommand DragMoveWindowCommand
        {
            get
            {
                return new ActionCommand<string>(p =>
                {
                    if (string.IsNullOrWhiteSpace(p))
                    {
                        App.MessageBox("参数不能为空!", "[App][DrawMoveWindowCommand]");
                        return;
                    }

                    Window window = App.NavigationToWindow(p);
                    if (window != null)
                    {
                        if (Mouse.LeftButton == MouseButtonState.Pressed)
                        {
                            window.DragMove();
                        }
                        if (window.WindowState == WindowState.Maximized)
                        {
                            window.WindowState = WindowState.Normal;
                        }
                    }
                }
                );
            }
        }
    }

3.在主窗体中使用ShowCommand命令来实现窗体导航。

<Window x:Class="WpfMVVM.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfMVVM"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Width="100" Height="40" Content="打开新窗体" Command="{x:Static local:App.ShowWindowCommand}"
                CommandParameter="WpfMVVM.View.CustomWindow"/>
    </Grid>
</Window>

4.在自定义窗体CustomWindow.xaml中使用命令来实现窗体拖动和显隐控制。

为了使得Grid中的MouseMove事件能够响应命令绑定操作,导入blend中的类库:System.Windows.Interactivity.dll。并在页面中导入xml命名空间:xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"。这样就可以实现WPF中任意事件的命令响应。

<Window x:Class="WpfMVVM.View.CustomWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:local="clr-namespace:WpfMVVM"
        Title="CustomWindow" Height="300" Width="300"
        WindowStyle="None" AllowsTransparency="True"
        ShowInTaskbar="False"
        >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Grid Grid.Row="0" Background="{StaticResource BoardHead}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="30"/>
            </Grid.ColumnDefinitions>

            <TextBlock Grid.Column="0" Text="标题" Style="{StaticResource BoardTitle}"/>
            <Button Grid.Column="1" Style="{StaticResource CloseBtn}"
                    Command="{x:Static local:App.HideWindowCommand}"
                    CommandParameter="WpfMVVM.View.CustomWindow"/>
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseMove">
                    <i:InvokeCommandAction Command="{x:Static local:App.DragMoveWindowCommand}"
                                               CommandParameter="WpfMVVM.View.CustomWindow"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Grid>
        
        <Grid Grid.Row="1" Background="{StaticResource BoardBody}">
            <Image Source="/Resource/sun.png" Stretch="Uniform"/>
        </Grid>
        
    </Grid>
</Window>

通过以上步骤操作,我们便可以实现窗体之间的导航以及自定义窗体的拖动控制以及显隐控制。

完整代码下载:http://download.csdn.net/detail/tianwenxue/9078205

本文原创,转载请注明出处。

目录
相关文章
|
4月前
|
前端开发 C# 容器
浅谈WPF之控件拖拽与拖动
使用过office的visio软件画图的小伙伴都知道,画图软件分为两部分,左侧图形库,存放各种图标,右侧是一个画布,将左侧图形库的图标控件拖拽到右侧画布,就会生成一个新的控件,并且可以自由拖动。那如何在WPF程序中,实现类似的功能呢?今天就以一个简单的小例子,简述如何在WPF中实现控件的拖拽和拖动,仅供学习分享使用,如有不足之处,还请指正。
108 2
|
7月前
|
设计模式 开发框架 前端开发
深入理解WPF中MVVM的设计思想
近些年来,随着WPF在生产,制造,工业控制等领域应用越来越广发,很多企业对WPF开发的需求也逐渐增多,使得很多人看到潜在机会,不断从Web,WinForm开发转向了WPF开发,但是WPF开发也有很多新的概念及设计思想,如:数据驱动,数据绑定,依赖属性,命令,控件模板,数据模板,MVVM等,与传统WinForm,ASP.NET WebForm开发,有很大的差异,今天就以一个简单的小例子,简述WPF开发中MVVM设计思想及应用。
61 0
|
8月前
|
前端开发
WPF-Binding问题-MVVM中IsChecked属性CommandParameter转换值类型空异常
WPF-Binding问题-MVVM中IsChecked属性CommandParameter转换值类型空异常
86 0
|
9月前
|
前端开发 算法 JavaScript
走进WPF之MVVM完整案例
走进WPF之MVVM完整案例
148 0
|
9月前
|
C#
WPF控件和窗体一起放大一起缩小
WPF控件和窗体一起放大一起缩小
182 0
|
9月前
|
C# 容器
WPF框架下,窗体的嵌套显示
WPF框架下,窗体的嵌套显示
173 0
|
前端开发 C# 图形学
【.NET6+WPF】WPF使用prism框架+Unity IOC容器实现MVVM双向绑定和依赖注入
前言:在C/S架构上,WPF无疑已经是“桌面一霸”了。在.NET生态环境中,很多小伙伴还在使用Winform开发C/S架构的桌面应用。但是WPF也有很多年的历史了,并且基于MVVM的开发模式,受到了很多开发者的喜爱。
559 0
【.NET6+WPF】WPF使用prism框架+Unity IOC容器实现MVVM双向绑定和依赖注入
|
前端开发 C# 数据库
WPF MVVM系统入门-下
本文详细讲解WPF,MVVM开发,实现UI与逻辑的解耦。
|
前端开发 数据可视化 C#
WPF MVVM系统入门-上
本文详细讲解WPF,MVVM开发,实现UI与逻辑的解耦。
|
前端开发 C#
WPF MVVM 如何在 ViewModel 中关闭界面窗口
WPF MVVM 如何在 ViewModel 中关闭界面窗口