应用场景

我现在做一个系统登录功能,要求在PasswordBox上输完密码后回车,能够响应Enter事件,并执行ViewModel中对应的方法。如果登录成功则隐藏当前窗口显示主窗体,登录失败则焦点返回到用户名TextBox中,并全选文字,方便用户再重新输入。

这个在我们制造业自动化流程控制中,做防呆功能是很明显的,因为没有人为去参与。

如果像Winform一样的开发模式,就相对很简单了,现在是要在ViewModel,对一个初学者来说就相对地困难多了,那怎么办呢?

设计思想

自定义一个Command,支持多参数对象数组,把控件,事件传到ViewModel中。

实现步骤

  1. 自定义命令InteractiveCommand类,继承TriggerAction<DependencyObject>
// -----------------------------------------------------------------------
// <copyright file="InteractiveCommand.cs" company="">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------namespace TLAgent.SecurityManager.WPF
{using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows;using System.Windows.Input;using System.Windows.Interactivity;using System.Reflection;/// <summary>/// TODO: Update summary./// </summary>public class InteractiveCommand : TriggerAction<DependencyObject>{protected override void Invoke(object parameter){if (base.AssociatedObject != null){ICommand command = this.ResolveCommand();object[] tempObj = { parameter, CommandParameter };if ((command != null) && command.CanExecute(tempObj)){command.Execute(tempObj);}}}public object CommandParameter{get { return GetValue(CommandParameterProperty); }set { SetValue(CommandParameterProperty, value); }}public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(InteractiveCommand), new PropertyMetadata(null, OnCommandParameterChanged));private static void OnCommandParameterChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e){InteractiveCommand ic = sender as InteractiveCommand;if (ic != null){ic.SynchronizeElementState();}}private void SynchronizeElementState(){ICommand command = Command;if (command != null){FrameworkElement associatedObject = AssociatedObject as FrameworkElement;if (associatedObject != null){associatedObject.IsEnabled = command.CanExecute(CommandParameter);}}}private ICommand ResolveCommand(){ICommand command = null;if (this.Command != null){return this.Command;}if (base.AssociatedObject != null){foreach (PropertyInfo info in base.AssociatedObject.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)){if (typeof(ICommand).IsAssignableFrom(info.PropertyType) && string.Equals(info.Name, this.CommandName, StringComparison.Ordinal)){command = (ICommand)info.GetValue(base.AssociatedObject, null);}}}return command;}private string commandName;public string CommandName{get{base.ReadPreamble();return this.commandName;}set{if (this.CommandName != value){base.WritePreamble();this.commandName = value;base.WritePostscript();}}}#region Commandpublic ICommand Command{get { return (ICommand)GetValue(CommandProperty); }set { SetValue(CommandProperty, value); }}public static readonly DependencyProperty CommandProperty =DependencyProperty.Register("Command", typeof(ICommand), typeof(InteractiveCommand), new UIPropertyMetadata(null));#endregion}
}

2.   在XAML中做绑定,把EventName定为”KeyDown“,请参考如下代码:

<PasswordBox x:Name="txtPassword" Height="23" Helper:PasswordBoxHelper.Attach="True" Helper:PasswordBoxHelper.Password="{Binding Path=AuthUser.Password,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="101,92,0,0"  VerticalAlignment="Top" Width="178" TabIndex="2"><i:Interaction.Triggers><i:EventTrigger EventName="KeyDown"><Helper:InteractiveCommand Command="{Binding EnterLoginCommand}" CommandName="EnterLoginCommand" CommandParameter="{Binding ElementName=txtUserName}"/></i:EventTrigger></i:Interaction.Triggers></PasswordBox>

3.   后台的Command声明为DelegateCommand<object[]><object[]><object[]><object[]> _CommandWithEventArgs,并实例化,同时绑定一个带参数object[]的用户验证方法:

public ICommand EnterLoginCommand{get { return _CommandWithEventArgs ?? (_CommandWithEventArgs = new DelegateCommand<object[]>(CheckUser)); }}

绑定的方法为CheckUser,如下

private void CheckUser(object[] objs){KeyEventArgs e = objs[0] as KeyEventArgs;if (e.Key == Key.Enter){object obj = objs[1];VerifyUser(obj);} }private void VerifyUser(object objParam){if (AuthUser.UserName != null && AuthUser.Password != null){if (AuthUser.UserName.ToUpper().Equals("AGAN") && AuthUser.Password.Equals("123")){IsVisibility = Visibility.Hidden;SplashScreen splashScreen = new SplashScreen("Images/SplashScreen.JPG");splashScreen.Show(true);MainWindow window = new MainWindow();window.ShowDialog();}else{MessageBox.Show(@"用户名或密码错误!");TextBox txtUserName = (TextBox)objParam;txtUserName.Focus();txtUserName.SelectAll();}}else{MessageBox.Show(@"用户名或密码不能为空!");TextBox txtUserName = (TextBox)objParam;//转换为TextBox,即为View层的txtUserName控件txtUserName.Focus();//获取焦点txtUserName.SelectAll();//全选文本
            }}

测试

运行程序后,输入用户密码,显示如图:

转载于:https://www.cnblogs.com/aganqin/p/3276891.html

基于WPF系统框架设计(7)-TextBox/PasswordBox在ViewModel中支持回车命令相关推荐

  1. Asp.net基于工作流引擎的系统框架设计开发(源代码+论文)

    工作流就是一系列相互衔接.自动进行的业务活动或任务.工作流引擎是工作流管理系统的核心,它的主要功能是通过计算机技术的支持去定义.执行和管理工作流,协调工作流执行过程中工作之间以及群体成员之间的信息交互 ...

  2. Android源码分析(三)-----系统框架设计思想

    一 : 术在内而道在外 Android系统的精髓在源码之外,而不在源码之内,代码只是一种实现人类思想的工具,仅此而已...... 近来发现很多关于Android文章都是以源码的方向入手分析Androi ...

  3. 追踪(trace)系统框架设计的思考

    开发过稍微大一点的soa服务系统的程序员都听说过trace系统(但真正从零开始设计的人,我个人认为很少).为什么需要trace呢?原因是调用soa服务的调用链路太复杂(什么是调用链路,下面解释),tr ...

  4. 基于PLC系统的设计_kaic

    ​ 摘要 PLC警报器系统是一种基于可编程逻辑控制器(PLC)的警报器系统,主要用于在紧急情况下向公众发出警报信号.本文将介绍PLC警报器系统的设计摘要,包括系统结构.硬件设计.软件设计等方面.PLC ...

  5. 大数据准实时流式系统设计(一)——基于大数据框架设计

    前段时间负责了公司一个新的项目,项目不属于直接面向用户的线上实时响应系统,要求做到尽快毫秒级或者秒级响应的准实时系统.结合以前学习的一些大数据理论方面和参与的准实时系统方面的经验,对准实时系统架构设计 ...

  6. 基于消息系统架构设计

    最近在弄一个业务系统,这个业务系统原本是有一个架构的,但是在后期扩展时发现问题多多,关键扩展很不方便,而且因为业务系统安全规格较高,数据网络连接需要通过多个闸口传递才可,而且业务系统可能需要多地系统联 ...

  7. 系统怎么设计usb启动_在启动中启动设计系统

    系统怎么设计usb启动 重点 (Top highlight) Design systems are all the rage now and you've probably seen this ter ...

  8. linux系统export,Linux入门进阶 - 如何在Linux中使用export命令

    原标题:Linux入门进阶 - 如何在Linux中使用export命令 来自: Linux迷 链接:https://www.linuxmi.com/linux-export.html Linux ex ...

  9. 【毕业设计】asp.net基于工作流引擎的系统框架设计开发(源代码+论文)

    文章目录 目录 一.系统设计 二.系统实现 源文件 目录 一.系统设计 4.1模块的划分 通过对用户需求调研并分析,确定系统应具备的功能,所需模块包括:状态图管理,任务管理,任务指派,任务提交. 4. ...

最新文章

  1. iOS 减少编译时间
  2. 网络安全行业的未来在哪里?
  3. JavaScript面向对象(一)——JS OOP基础与JS 中This指向详解
  4. mysql悲观锁总结和实践--转
  5. NC33-合并两个有序的链表
  6. System.Xml名称空间下的支持DOM的类型
  7. hashmap 存取原理图_HashMap底层实现原理
  8. 设置按钮中的图片的旋转,并且旋转之后不变形
  9. 嵌入式linux组件,嵌入式Linux系统的几大组件!
  10. nacos 本地测试_Nacos入门
  11. 马云背后的女人:原来淘宝、支付宝的名字都是她取的
  12. css模型安装,【CSS】CSS-框模型+定位+实训练习
  13. Spark-Serialization序列化的2种方式解释对比使用场景
  14. 使用UUID和int自增主键的区别
  15. maven的使用--初级篇
  16. 公务员Python培训
  17. 错误:Property or field 'default' cannot be found on object of type 'com.netflix.appinfo.InstanceInfo'
  18. 省级、县级行政区shapefile下载
  19. Docker安装以及docker run hello-world 不能下载镜像报错
  20. 噪声,白噪声,加性噪声和乘性噪声

热门文章

  1. Hue中Sqoop导数报错Could not load db driver class: com.mysql.jdbc.Driver
  2. R+python︱XGBoost极端梯度上升以及forecastxgb(预测)+xgboost(回归)双案例解读
  3. java笔记高级部分
  4. RxJava2.0的初学者必备教程(九)
  5. 1. BeeGo 介绍与项目的创建,启动
  6. 解剖 RxJava 之过滤操作符
  7. 【POJ 1269】判断两直线相交
  8. nginx rwrite及增加不记录特定状态日志nginx模块
  9. 分享一个自己写的基于TP的关系模型(2)
  10. Log4j配置和简单使用