基于WPF系统框架设计(7)-TextBox/PasswordBox在ViewModel中支持回车命令
应用场景
我现在做一个系统登录功能,要求在PasswordBox上输完密码后回车,能够响应Enter事件,并执行ViewModel中对应的方法。如果登录成功则隐藏当前窗口显示主窗体,登录失败则焦点返回到用户名TextBox中,并全选文字,方便用户再重新输入。
这个在我们制造业自动化流程控制中,做防呆功能是很明显的,因为没有人为去参与。
如果像Winform一样的开发模式,就相对很简单了,现在是要在ViewModel,对一个初学者来说就相对地困难多了,那怎么办呢?
设计思想
自定义一个Command,支持多参数对象数组,把控件,事件传到ViewModel中。
实现步骤
- 自定义命令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 Command
public 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();//全选文本
}
}
测试
运行程序后,输入用户密码,显示如图:


基于WPF系统框架设计(7)-TextBox/PasswordBox在ViewModel中支持回车命令的更多相关文章
- 基于WPF系统框架设计(5)-Ribbon整合Avalondock 2.0实现多文档界面设计(二)
AvalonDock 是一个.NET库,用于在停靠模式布局(docking)中排列一系列WPF/WinForm控件.最新发布的版本原生支持MVVM框架.Aero Snap特效并具有更好的性能. Ava ...
- 基于WPF系统框架设计(1)-为什么要仿Office2010 Ribbon?
为什么系统框架设计使用Ribbon导航模式? 这得从Office软件的演变说起.微软为什么最后选择使用Ribbon,也许就是很多系统设计要使用Ribbon做功能导航的原因. 你是否还记得曾经使用过的M ...
- 基于WPF系统框架设计(8)-PasswordBox传值到ViewMode
应用场景 我要做一个系统登录功能,需要传用户名和密码到ViewModel中,可是PasswordBox传值到ViewModel中好像跟TextBox等控件不一样.这里需要用到附加属性. 附加属性:一个 ...
- 基于WPF系统框架设计(4)-Ribbon整合Avalondock 2.0实现多文档界面设计(一)
前些时间研究了WPF的一些框架,感觉基于Prism框架的MVVM模式对系统的UI与逻辑分离很好,所以就按照之前Winform的框架设计,用WPF做了一套,感觉比Winform要强很多. MVVM模式和 ...
- 基于WPF系统框架设计(3)-Fluent Ribbon界面布局
一个系统框架除了功能菜单导航,有系统内容显示区域,系统状态栏. Silver: Blue: Black: 系统界面设计,就不进行技术细节介绍了,主题以框架设计为主,Xaml源码参考: <Flue ...
- 基于WPF系统框架设计(9)-多值绑定之IMultiValueConverter
应用场景 我想把View层的一个布局控件和功能按钮传到ViewModel层,达到动态变更布局,同时灵活获取功能按钮的属性,让View和ViewModel完全分离,而不受View层影响. 最后我想到使用 ...
- 基于WPF系统框架设计(6)-整合MVVM框架(Prism)
应用场景 我们基础的框架已经搭建起来了,现在整合MVVM框架Prism,在ViewModel做一些逻辑处理,真正把界面设计分离出来. 这样方便我们系统开发分工合作,同时提高系统可维护性和灵活性. 具体 ...
- 基于WPF系统框架设计(2)-Fluent Ribbon之HelloWorld
Fluent/Ribbon是微软在其最新桌面操作系统Windows 7中使用的图形用户界面. Windows平台的进化,伴随着系统图形界面的重新设计.从Windows XP到Windows Vista ...
- 基于WPF系统框架设计(10)-分页控件设计
背景 最近要求项目组成员开发一个通用的分页组件,要求是这个组件简单易用,通用性,兼容现有框架MVVM模式,可是最后给我提交的成果勉强能够用,却欠少灵活性和框架兼容性. 设计的基本思想 传入数据源,总页 ...
随机推荐
- 在Foxmail中添加阿里云企业邮箱账号
1.安装完成Foxmail之后,新建账号 输入阿里云邮箱地址和密码,点击创建 接受服务器类型你可以选择POP3或者IMAP,在这里我选择的是POP3 点击创建,大功告成. 为什么要写这篇文章呢? 因为 ...
- cf965c Greedy Arkady
呸,大傻逼题,我更傻逼ref #include <iostream> using namespace std; typedef long long ll; ll n, k, m, d, a ...
- flex布局之flex-grow和flex-shrink如何计算
此文已由作者张含会授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 关于盒模型布局 如何实现两栏布局? (表格) 流式, 浮动, 定位 如何选择? 流式 > 浮动 > ...
- Boost入门
[转载网友转载的 不过不知道原作者地址] Boost入门向导 简介:boost是一套开源的.高度可移植的C++模板库.它由C++标准委员发起,且里面很多组件有望成为下一代的C++标准库,其地位将会与S ...
- hnust 心电图
问题 A: 心电图 时间限制: 1 Sec 内存限制: 128 MB提交: 621 解决: 250[提交][状态][讨论版] 题目描述 众所周知,ACM/ICPC实验室聚集了一堆学霸Orz 有学霸 ...
- Map-Reduce基础
1.设置文件读入分隔符 默认按行读入; 按句子读入 : conf1.set("textinputformat.record.delimiter", "."); ...
- tomcat 服务不支持 chkconfig 以及其他服务不能添加到开机启动时的操作
在安装完tomcat后想添加的开机自启动的操作,但是报错tomcat 服务不支持 chkconfig,后来在 /etc/init.d/tomcat中的#!/bin/bash后添加上#chkconfi ...
- android AsyncTask使用限制
由于AsyncTask内部是使用线程池(ThreadPoolExecutor)来管理要处理的任务的,所以AsyncTask的弊端就非常明确了:要extcute的任务数量超过线程池最大容量时,必然会报错 ...
- 十一黄(xun)金(lian)周感想
实际上并没有训整整一周-_-|| 只训了三天 听说纪中全员没过节(ΩДΩ)好可怕 这三天考了5场模拟赛,一场初赛模拟 让我感觉我和开学时比起来还是有很大的提升的 最主要就是在dp方面. 经过整个九月疯 ...
- Java Class 与 Object
平时看代码时,总是碰到这些即熟悉又陌生的名次,每天都与他们相见,但见面后又似曾没有任何的交集,所以今天我就来认识下这两个江湖侠客的背景: CLASS 在Java中,每个class都有一个相应的Clas ...