基於WPF系統框架設計(7)-TextBox/PasswordBox在ViewModel中支持回車命令

應用場景

我如今作一個系統登陸功能,要求在PasswordBox上輸完密碼後回車,可以響應Enter事件,並執行ViewModel中對應的方法。若是登陸成功則隱藏當前窗口顯示主窗體,登陸失敗則焦點返回到用戶名TextBox中,並全選文字,方便用戶再從新輸入。數組

這個在咱們製造業自動化流程控制中,作防呆功能是很明顯的,由於沒有人爲去參與。ide

若是像Winform同樣的開發模式,就相對很簡單了,如今是要在ViewModel,對一個初學者來講就相對地困難多了,那怎麼辦呢?測試

設計思想

自定義一個Command,支持多參數對象數組,把控件,事件傳到ViewModel中。 this

實現步驟

  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「,請參考以下代碼:spa

<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,以下3d

 

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();//全選文本
            }
        }

測試

運行程序後,輸入用戶密碼,顯示如圖:code

image

image

相關文章
相關標籤/搜索