Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Silverlight:SetTextBoxFocusUsingMVVM

0.00/5 (No votes)
19 Sep 2010 1  
How to set focus inside textbox while validating using MVVM pattern

Introduction

The MVVM is an architectural pattern from Microsoft. View Class has no idea about model exist however viewmodel and model don’t know about view. It is a loosely coupled design.
This separates the role of designer to focus on UI instead of programming/business logic and allows application to work in different work streams.

MVVM_Architecture.jpg

If interested, get more details on 5 Minute Overview of MVVM in Silverlight.

This article explains the problem of how to set focus inside textbox(View) when we use validation logic when using MVVM pattern.

Background

One of my friends had given me a problem and asked me for a solution which I feel is required by most developers, so I decided to write an article on this which might be helpful.
As it is a general scenario that an application has some control (Textbox) which needs input from the end user and when end user performs some action (Save or move to another form), we do validation on button click. Now in Silverlight, with the help of ValidatesOnDataErrors=True attribute display UI with red border outside textbox which indicates required field/invalid data. You can see in the below Screen 1 and Screen 2.

Normal.jpg

NoFocusInside_TextBox.jpg

However, it would be good if it will blink cursor inside the textbox so that user does not need to explicitly click mouse to set focus inside textbox after which only he/she can enter input.
So the point of interest here is to achieve this using MVVM model without writing any code in View code-behind file.
The below screen 3 explains more:

Focus_Inside_TextBox.jpg

Using the Code

Currently Silverlight 4.0 doesn’t provide directly CommandManager, with the help of how to Creating a command manager in Silverlight as this command manager will be implemented in View which will bind the command of button with click event.

<Button Content="Click!"="3"Grid.Column="2"Grid.ColumnSpan="2"
Cmd:CommandManager.CommandEventName="Click"
Cmd:CommandManager.Command="{Binding ClickCommand }" />

As currently this CommandManager is created as a separated library which can be used across any other Silverlight class library.

Class TextBoxAttach

Now define a class name as TextBoxAttach which has Dependency property (TextBoxControllerProperty). This property registers a function OnTextBoxControllerChanged which will execute whenever the textbox control loads. The important point in the below code is when this property has been attached to textbox, then it has one dictionary being defined called elements1 which stores the textbox name as ID.

private static readonly Dictionary<string,TextBox> elements1 = 
				new Dictionary<string,TextBox>();

private static void OnTextBoxControllerChanged
	(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var element = d as TextBox;
if (element == null)
throw new ArgumentNullException("d");
var newController = e.NewValue as ITextBoxController;
if (newController != null)
{
elements1.Add(element.Name, element);
newController.ClickButton += ClickButton;
}
}

Now when you click on Button, the ClickButton event fires which checks if textbox is empty to those textboxes which have been attached with TextBoxControllerProperty and it will set the focus inside textbox.

private static void ClickButton(ITextBoxController sender)
{
foreach (KeyValuePair<string,TextBox> pair in elements1)
{
TextBox element;
string key = pair.Key;
element = pair.Value;
if (string.IsNullOrEmpty(element.Text))
{
element.Focus();
break;
}
}
}

So to use this TextBoxAttach to set focus inside a textbox, the XAML code will be something like this:

<TextBox x:Name="textBox1" loc:TextBoxAttach.TextBoxController="{Binding}" /> 

Class MyViewModel

Class MyViewModel inherits from ITextBoxController and uses event ClickEventhandler which is defined in ITextBoxController. And here in the constructor of MyViewModel initialize the ClickCommand with the help of RelayCommand which itself inherits from ICommand.

public MyViewModel()
{
Value1 = "My Text1";
Value2 = "My Text2";

ClickCommand = new RelayCommand(p =>
{
if (ClickButton != null)
ClickButton(this);
});
}

Now to display validation error UI to view MyViewModel class also inherits from IDataErrorInfo which implements the indexer also known as smart arrays in C#. It is pretty much like defining properties:

public string this[string columnName]
{
get 
{
string strMessage = string.Empty;
CustomValidation(ref strMessage, columnName);
return strMessage;
}
}

And to use this validation feature, the XAML code will be like this:

<TextBox x:Name="textBox1" Text="{Binding Path=Value1,
Mode=TwoWay,ValidatesOnDataErrors=True}" /> 

Points of Interest

  1. MVVM- How can I select text in a textbox?
  2. Model-View-ViewModel In Silverlight Apps.

Finally

As there is always scope for improvement, it would be good if you have any comments/complaints/suggestions, kindly let me know. I will try to address those points and your feedback will help me to improve my future articles on CodeProject J.

History

  • Posted on 18-Sep-2010

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here