You would already know this, but in Silverlight when in full-screen mode keyboard input is by design constrained to a limited set of keys - this often takes an end-user by surprise and leaves them with a perception than it's an application problem. To overcome this Silverlight limitation I've created a Virtual Input Keyboard and accompanying behaviours, that allows you to attach an on-screen keyboard to any receptive UI control.
View the demo app here.
The Input Keyboard
It is important to appreciate that the Silverlight Keyboard presented here is an Input Keyboard, which is different from a general purpose Virtual Keyboard found in most Operating Systems. The input keyboard is specifically only made visible on-screen when directly editing/inputting to an attached UI control (e.g. a TextBox), when not editing/inputting it is automatically hidden from view - this is very much like in mobile phones. So for example with the PasswordBox shown above the Input Keyboard will be made visible when the PasswordBox has focus, and in the "focus" state it allows you to "key-in" characters but anytime the PasswordBox looses the focus the keyboard also vanishes.
- All character-keys feature iPhone'que callouts/popouts when pressed
- A symbols mode (bottom right key) features most of the commonly used symbol and non-alphabetic characters (shown above) - however currently there is no support for customizing or appending custom symbols
- There is a sticky shift-key (bottom left) that allows for capitalized alphabets
- The keyboard also allows for a Title, above it is set to "User Password"
- The keyboard is collapsable, see the arrow key show above (top right)
- The keyboard is dragable, and is not constrained to its parent's bounds
- The keyboard is based on the Popup Primitive in Silverlight, so it is not effected by z-index based layering
- A single keyboard control instance can be registered and used throughout the application as the default keyboard
- You avail the keyboard by attaching behaviours to UI controls, included are behaviours for attaching to a Textbox or a PasswordBox control
- You can create custom behaviours to consume the Keyboard with other kinds of UI controls such as a Grid or ListBox (I will post separately about how to do this)
- The behaviours also allow you to configure as to if the Keyboard is only available when in full-screen mode (the default setting)
Like I mentioned included are three behaviours based on the Blend SDK, which allow you the configure and attach the Keyboard with various UI controls.
You put this behaviour onto an Input Keyboard, and it makes it the default application-wide keyboard for use by one or more UI controls. Without this, you'll need to specify onto each attached control the keyboard you want to use it. Further, to make life easy it has no configurable settings, so simply drag and drop this onto an Input Keyboard.
This behaviour is applied onto a TextBox, and it in turn attaches a Keyboard onto it. Using this behaviours is very simple, it has three properties - one to specify the Title that is shown atop the Keyboard (note its use is optional). The second property, takes in the Target Keyboard name, as shown in the screenshot on your right. However, if you wanted to use the default application wide keyboard (as described above), then you leave this empty and it will resolve it automatically. Lastly, the VisibleInNonFullScreenMode property, allows the Keyboard to be visible when not in full-screen mode. Note again, the default behaviour will only show the keyboard when in full-screen mode, so turn this on if you want it available independent of the full-screen mode.
As the name suggests this behaviour is applicable to PasswordBox controls, and the use API is identical to the TextBoxInputKeyboardBehaviour. However, the use-semantics are quite different - the TextBox keyboard behaviour can identify and use text-selection and cursor position information, and therefore the interaction with the Input Keyboard fully mimics the use-semantics we are accustomed too with a physical keyboard and mouse. Now, the PasswordBox control doesn't expose text-selection or cursor position information, which leads to somewhat counter-intuitive use interaction. For example, if you've partially selected some part of the password text and press a key with your physical keyboard it would overwrite the selection with the keyed character. However, with the Virtual Input Keyboard you can only append any keyed character to the end of the password string, because we are not party to selection or cursor-position information with the PasswordBox control. Also the automation API in Silverlight suffers from the same information deficiencies, which is why I've forgone its use.
Since this is just the first shot at this, there are plenty of possible enhancements. Some of the ones I am considering are:
- Customizable key-sets, using predefined profiles - kind of like how iPhone offers a different key-set for entering Urls
- An optional default action key, like one to trigger a "Google" - this is also akin to iPhones
- Key press sounds option
- Configurable relative positioning of Keyboard to any attached UI control
- A numeric-pad version of the Input Keyboard, that only offers numeral characters
- Templat'able Keyboard and Keys UI
- A sharper/better default skin
If you have any other suggestions or ideas, do let me know.
You can download the Input Keyboard dll (16 kb) from the Expression Gallery Site,
and again you can view the demo app here.
The following are two classes that allow you to attach the Keyboard to an AutoCompleteBox Control (found in Silverlight Toolkit). However do note that the AutoCompleteBox does not expose selection information so the keys are added and removed from the end of the text-string only - which unfortunately is not all that intuitive.
1: // Keyboard Input Handler for AutoCompleteBox
2: public class AutoCompleteBoxInputHandler : IInputKeyboardHandler
5: readonly AutoCompleteBox _autoCompleteBox;
7: public event EventHandler InputKeyboardAttached;
8: public event EventHandler InputKeyboardDetached;
10: public AutoCompleteBoxInputHandler(AutoCompleteBox autoCompleteBox)
12: if (autoCompleteBox == null) throw new ArgumentNullException("autoCompleteBox");
13: _autoCompleteBox = autoCompleteBox;
16: #region IKeyboardHandler Implementation
18: public void KeyboadAttached()
20: if (InputKeyboardAttached != null)
21: InputKeyboardAttached(this, EventArgs.Empty);
24: public void KeyboardDetached()
26: if (InputKeyboardDetached != null)
27: InputKeyboardDetached(this, EventArgs.Empty);
30: public void CharacterKeyed(Char character)
32: // we append to the end the added character, also notice there is no max length on auto-complete
33: _autoCompleteBox.Text = _autoCompleteBox.Text + character.ToString();
36: public void BackspaceKeyed()
38: // we remove one letter from the end
39: var _existingText = _autoCompleteBox.Text;
40: if (_existingText.Length > 0)
41: _autoCompleteBox.Text = _existingText.Substring(0, _existingText.Length - 1);
48: // Behaviour Class to Attach to AutoCompleteBox
49: public class AutoCompleteBoxKeyboardBehavior : InputKeyboardBehaviorBase<AutoCompleteBox>
52: #region Override
54: protected override IInputKeyboardHandler ResolveKeyboardHandler()
56: return new AutoCompleteBoxInputHandler(this.AssociatedObject);
59: protected override void OnAttached()
63: // we attach to the textbox
64: AssociatedObject.GotFocus += new System.Windows.RoutedEventHandler(AssociatedObject_GotFocus);
65: AssociatedObject.LostFocus += new System.Windows.RoutedEventHandler(AssociatedObject_LostFocus);
68: protected override void OnDetaching()
72: // detach the handlers
73: AssociatedObject.GotFocus -= new System.Windows.RoutedEventHandler(AssociatedObject_GotFocus);
74: AssociatedObject.LostFocus -= new System.Windows.RoutedEventHandler(AssociatedObject_LostFocus);
79: #region Handler
81: void AssociatedObject_GotFocus(object sender, RoutedEventArgs e)
86: void AssociatedObject_LostFocus(object sender, RoutedEventArgs e)
Also remember, you can create IInputKeyboardHandler implementation along with a matching Behavior for other types of input controls you require.
Posted by Rishi on 09-Nov-09 9:04 AM, 43 Comments