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

应用场景

我现在做一个系统登录功能,要求在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 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();//全选文本

            }

        }

测试

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

image

image

你可能感兴趣的:(password)