• 基于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

  • 相关阅读:
    Centos6.10-FastDFS-存储器Http配置
    Centos6.10-FastDFS-Storage.conf配置示例
    Centos6.10-FastDFS-Tracker.conf示例配置
    sublime不支持ascill编码办法
    VMware虚拟磁盘修复
    Centos610安装Nexus
    JavaWeb项目用浏览器打开网页出现Session Error提示的解决办法
    Ext里dialog弹窗关闭与父窗口刷新问题总结
    js里常见的三种请求方式$.ajax、$.post、$.get分析
    formValidation单个输入框值改变时校验
  • 原文地址:https://www.cnblogs.com/aganqin/p/3276891.html
Copyright © 2020-2023  润新知