Click here to Skip to main content
15,867,453 members
Articles / Desktop Programming / XAML

UWP TextBox Behaviour for Focus & Command Binding

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
24 Mar 2016CPOL2 min read 22.4K   273   3   2
Adds MVVM focusing and command execution on keypress to universal Windows platorm textbox via attached properties.

Introduction

This is a behaviour class that you can plug into your universal Windows platform to provide a means of focusing a textbox in an MVVM fashion and also provides the ability to execute a command based on a key press.

Background

See the following article for an introduction to the concept of attached behaviours:

Using the Code

The behaviour class provides two features.

Focus

The focusing capabilities have the following elements.

First, an attached property to indicate if the control has focus or not.

C#
/// <summary>
/// Declare new attached property.
/// </summary>
public static readonly DependencyProperty IsFocusedProperty =
      DependencyProperty.RegisterAttached("IsFocused", typeof(bool),
      typeof(TextBoxBehaviour), new PropertyMetadata(default(bool), OnIsFocusedChanged));

When the IsFocused property is changed, the OnIsFocusedChanged method will be called. Within the method; if the IsFocused property is true, then the control is Focused. Additionally, handling is attached for the LostFocus event.

C#
/// <summary>
/// This method will be called when the IsFocused
/// property is changed
/// </summary>
/// <param name="s">System.Object repersenting the source of the event.</param>
/// <param name="e">The arguments for the event.</param>
public static void OnIsFocusedChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
{
    //If the host object is a frame.
    if (s is TextBox)
    {
        //Unbox.
        TextBox t = s as TextBox;

        //If setting is true.
        if ((bool)e.NewValue)
        {
            //Set the Focus
            t.Focus(FocusState.Pointer);

            //Attach handling for lost focus.
            t.LostFocus += textbox_LostFocus;
        }
        else
        {
            //Remove handling.
            t.LostFocus -= textbox_LostFocus;
        }
    }
}

Inside the LostFocus event, the property is reset.

C#
/// <summary>
/// Handling for when the texbox looses focus.
/// </summary>
/// <param name="sender">System.Object repersenting the source of the event.</param>
/// <param name="e">The arguments for the event.</param>
private static void textbox_LostFocus(object sender, RoutedEventArgs e)
{
    //Unbox.
    TextBox t = sender as TextBox;

    //Set dependency property.
    t.SetValue(IsFocusedProperty, false);
}

In your view, add the namespace for the behaviour.

XML
xmlns:behave="using:UtilitiesUniversal.Behaviours"

You could then use the attached property as follows. Note that I have binded the property to the check state of a toggle button element placed elsewhere on the page. Now the focus of the control is toggled along with the toggle button checkstate. A potentially useful feature for one handed use on mobile.

XML
<TextBox Name="filterText" 
behave:TextBoxBehaviour.IsFocused="{Binding ElementName=filterBtn, 
Path=IsChecked, Mode=TwoWay}" Height="48"   
InputScope="AlphanumericFullWidth" 
VerticalContentAlignment="Center" FontSize="25" >

...

 <CommandBar ClosedDisplayMode="Compact" Name="commands">
                <AppBarToggleButton Icon="Filter" 
                x:Uid="Filter" Name="filterBtn" IsChecked="False"/>
  </CommandBar>       

Command Binding

The other feature provided by the behaviour class is for executing a command on a keypress.

The command binding feature has the following elements.

First, there is the property to house the desired command.

C#
public static readonly DependencyProperty CommandProperty =
            DependencyProperty.RegisterAttached("Command", typeof(ICommand),
                typeof(TextBoxBehaviour), new PropertyMetadata(null));     

The other property is of course the desired key that will trigger the command.

C#
public static readonly DependencyProperty CommandKeyProperty =
    DependencyProperty.RegisterAttached("CommandKey", typeof(string),
    typeof(TextBoxBehaviour), new PropertyMetadata(default(string), OnCommandKeyChanged));

In the OnCommandKeyChanged, Callback handling is attached for the KeyDown event.

C#
private static void OnCommandKeyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
       {
           if (d is TextBox)
           {
               //Unbox.
               TextBox t = d as TextBox;


               //If the key is set.
               if (e.NewValue != null && e.NewValue.ToString().Length > 0)
               {
                   t.KeyDown += T_KeyDown;
               }
               else
               {
                   t.KeyDown -= T_KeyDown;
               }
           }
       }

In the KeyDown event handler, the pressed key is compared to the CommandKey property and if it matches, the command is executed.

C#
private static void T_KeyDown(object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs e)
       {
           TextBox t = sender as TextBox;

           if (e.Key.ToString() == t.GetValue(CommandKeyProperty).ToString())
           {
               //Handle.
               e.Handled = true;

               // Get command
               ICommand command = GetCommand(t);

               // Execute command
               command.Execute(null);
           }
       }

In your view, add the namespace for the behaviour:

XML
xmlns:behave="using:UtilitiesUniversal.Behaviours"

Now, you can use the property as follows; In the example, I will execute the ReadCommand in the current datacontext when the enter button is pressed in the textbox.

XML
<TextBox AcceptsReturn="False" 
behave:TextBoxBehaviour.Command="{Binding ReadCommand}" 
behave:TextBoxBehaviour.CommandKey="{Binding FakeBinding,FallbackValue=Enter}"  
InputScope="AlphanumericFullWidth" 
VerticalContentAlignment="Center" FontSize="25"/>

Points of Interest

It is my experience that the universal Windows platform will not allow setting an attached property directly, i.e., you must use a binding. Hence the binding notation above.

History

  • 1.0

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Ireland Ireland
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
BugIsFocus not working! Pin
Jitendra.Jadav13-Jun-16 2:41
Jitendra.Jadav13-Jun-16 2:41 
GeneralMy vote of 5 Pin
Gurvus2-Jun-16 20:52
Gurvus2-Jun-16 20:52 
Very useful, works well! Thanks

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.