Silverlight Journal

December 21, 2009

Prism commanding: KeyUp example

Filed under: Uncategorized — Tags: , , , , — bobbsmooth @ 9:10 pm

Today, I had to build a simple login form using Silverlight 3 and Prism in a MVVM application.  One requirement that I always put on any login form is that the user can hit the enter key to submit her credentials for validation.  This is my solution:

KeyUpBehavior.cs

using System.Windows.Controls;
using System.Windows.Input;
using Microsoft.Practices.Composite.Presentation.Commands;

namespace Infrastructure.Commands.PasswordCommands
{
    public class KeyUpBehavior : CommandBehaviorBase<Control>
    {
        public KeyUpBehavior(Control element)
            : base(element)
        {
            element.KeyUp += new KeyEventHandler(element_KeyUp);
        }

        void element_KeyUp(object sender, KeyEventArgs e)
        {
            //only execute command if the user pressed the enter key
            if (e.Key == Key.Enter)
                base.ExecuteCommand();
        }
    }
}

KeyUp.cs

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace Infrastructure.Commands.PasswordCommands
{
    public class KeyUp
    {
        #region Command  attached property
        public static ICommand GetCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(CommandProperty);
        }

        public static void SetCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(CommandProperty, value);
        }

        // Using a DependencyProperty as the backing store for Command.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(KeyUp), new PropertyMetadata(OnSetCommandCallback));

        private static void OnSetCommandCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            Control element = dependencyObject as Control;
            if (element != null)
            {
                KeyUpBehavior behavior = GetOrCreateBehavior(element);
                behavior.Command = e.NewValue as ICommand;
            }
        }
        private static KeyUpBehavior GetOrCreateBehavior(Control element)
        {
            KeyUpBehavior behavior = element.GetValue(KeyUpBehaviorProperty) as KeyUpBehavior;
            if (behavior == null)
            {
                behavior = new KeyUpBehavior(element);
                element.SetValue(KeyUpBehaviorProperty, behavior);
            }
            return behavior;
        }
        #endregion

        #region KeyUpBehavior attached property
        public static KeyUpBehavior GetKeyUpBehavior(DependencyObject obj)
        {
            return (KeyUpBehavior)obj.GetValue(KeyUpBehaviorProperty);
        }

        public static void SetKeyUpBehavior(DependencyObject obj, KeyUpBehavior value)
        {
            obj.SetValue(KeyUpBehaviorProperty, value);
        }

        public static readonly DependencyProperty KeyUpBehaviorProperty =
            DependencyProperty.RegisterAttached("KeyUpBehavior", typeof(KeyUpBehavior), typeof(KeyUp), null);
        #endregion

        #region CommandParameter attached property
        public static object GetCommandParameter(DependencyObject obj)
        {
            return (object)obj.GetValue(CommandParameterProperty);
        }

        public static void SetCommandParameter(DependencyObject obj, object value)
        {
            obj.SetValue(CommandParameterProperty, value);
        }

        public static readonly DependencyProperty CommandParameterProperty =
            DependencyProperty.RegisterAttached("CommandParameter", typeof(object), typeof(KeyUp), new PropertyMetadata(OnSetCommandParameterCallback));

        private static void OnSetCommandParameterCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            Control element = dependencyObject as Control;
            if (element != null)
            {
                KeyUpBehavior behavior = GetOrCreateBehavior(element);
                behavior.CommandParameter = e.NewValue;
            }
        }
        #endregion
    }
}

View

        <PasswordBox Grid.Row="2" 
                 Grid.Column="2" 
                 customCommands:KeyUp.Command="{Binding KeyUp_Command}" 
                 customCommands:KeyUp.CommandParameter="{Binding Password, ElementName=txtPassword}" 
                 Password="{Binding Path=User.Password, Mode=TwoWay}" 
                 x:Name="txtPassword" />

ViewModel

        public DelegateCommand<object> KeyUp_Command { get; set; }

        public void KeyUpCommand_Handler(object commandParameter)
        {
            //do authentication, commandParameter is the value stored in PasswordBox.Password.
        }

ViewModel constructor

            KeyUp_Command = new DelegateCommand<object>(KeyUpCommand_Handler);

Advertisement

2 Comments »

  1. Tried this and did not get it to work. The event is set on a textbox, I can see that in the debugger. But it is never fired. So I just to see if a KeyUp event on the textbox actually works , I added the KeyUp=”myEvent” and added MyEvent in the code behind, and even that event does not get triggered. So your sample is probably fine, just in my case (SL3) the keyup does not work at all.

    Any idea why?
    Tnx

    Ben

    Comment by Ben — June 29, 2010 @ 1:35 pm

    • I forgot to put the code to set the ViewModel as the View’s DataContext. In the View’s codebehind, instantiate a new ViewModel. Then, set
      this.DataContext = ViewModel;

      Check out MVVM-Light on codeplex for a much cleaner way to command events back to the view model. Laurent uses Expression interactions to convert the event to a command.
      http://mvvmlight.codeplex.com/

      Comment by bobbsmooth — June 30, 2010 @ 2:31 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Theme: Shocking Blue Green. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.