开发者社区> 杰克.陈> 正文

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

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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
码农养成记2——Activity隐式跳转
转载请标明地址 QuincySx: http://www.jianshu.com/p/a6554196fd78 开始中可能遇到比较恶心的Activity跳转 比如在库中Activity中向另一个库中跳转 接下来说一种优雅的方式 在目的Activi...
777 0
[unity3d]鼠标点击地面人物自动走动(也包含按键wasd&amp;space控制)
在漫游游戏中常用的功能就是人物在场景中行走,必要的功能就是鼠标点击地面人物就朝着那个方向行走,键盘方向键前后左右也能控制人物的行走和跳跃,在官方自带的第三人称视角中做了一点修改,官方自带的ThirdPersonController中的摄像机自动指向人物的背面,这样不能看到人物的正面或者侧面,对ThirdPersonController脚本做了修改之后,可以旋转摄像机的视角,可以摄像机跟随,类似smoothfollow的功能。
742 0
C# 命令模式
一、命令模式:         将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。 ——《设计模式》 二、模式结构: Command:         定义命令的接口,声明执行的方法。 ConcreteCommand:         命令接口实现对象,是“虚”的实现;通常会
1036 0
WPF中通过代码定义模板
WPF中可以再XAML中定义模板,也可以通过C#代码定义模板,通过代码可能更清楚的看清其逻辑,而且代码的好处就是可以随时动态的去操作,而在XAML中定义的一般都是静态的。 //控件呈现的显示内容1(这里为Image) FrameworkElementFactory fe ...
619 0
5.cocos2dx中关于draw绘图,声音和音效,预加载,播放与停止Vs暂停和恢复,音量控制
 1 draw绘图 头文件 T19Draw.h #ifndef __T19Draw_H__ #define __T19Draw_H__ #include "cocos2d.h" #include "TBack.h"   USING_NS_CC;   class T
1503 0
+关注
杰克.陈
一个安静的程序猿~
10425
文章
2
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载