WPF TextBox SelectAll on Focus
The title of this post is almost pure Google-juice, because this is a trick that I had to relearn on the weekend after a series of unsuccessful searches on the topic.
A behaviour in Windows that most of us are fairly accustomed to (whether we realise it or not) is that upon entering a TextBox, the text is automatically selected. This means that you can tab into a TextBox and then start typing, and whatever was already in there will be automatically overwritten.
In WPF, this behaviour is not present. When you tab into a TextBox your cursor sits at the beginning of the text, and when you start typing, your new text is simply inserted at the beginning. This is really weird for someone who’s used to the “select all on focus” behaviour, and time-consuming for a beginner (who inevitably uses their right-arrow key to scroll to the end of the text, and backspaces to erase it all).
So how do you go about getting this behaviour back? Your first instinct might be to simply catch the GotFocus event on each TextBox and call the SelectAll() method, but that’ll get pretty old by about the thirtieth time you’ve done it. Instead, here’s a simple way to register a global event handler that works on any TextBox in your application:
First, open up your App.xaml.cs file. That’s the file in a WPF project that serves as the entry point for your application. The “App” class has an overridable method called “OnStartup” from which we’ll register our event handler:
protected override void OnStartup(StartupEventArgs e) { EventManager.RegisterClassHandler(typeof(TextBox), TextBox.GotFocusEvent, new RoutedEventHandler(TextBox_GotFocus)); base.OnStartup(e); }
So I’m using the EventManager class to register a global event handler (not to be confused with Evan Handler) against a type (TextBox)! Pretty neat, huh? The actual handler is dead simple:
private void TextBox_GotFocus(object sender, RoutedEventArgs e) { (sender as TextBox).SelectAll(); }
As you’d expect, we’re selecting the text in the supplied TextBox.
You can read more about class-handling of events on MSDN.
Comments
# Chris
3/01/2009 9:37 AM
Yep, totally Google-juiced titled, I plugged in "wpf TextBox select onfocus" and this was the first result. Thanks! totally helped.
# JLM
20/01/2009 10:19 AM
Aaaaaah! Thanks a lot, Matt, that's eXACTly what I was looking for. Bye!
# Drew Noakes
13/02/2009 4:01 AM
Cheers for this one Matt. Very helpful stuff.
# Drew Noakes
13/02/2009 4:26 AM
I think I spoke to soon. Turns out that this doesn't cause the text to be selected when a user clicks in the TextBox, only when tabbing into it. Any ideas anyone? I tried trapping a few other events but couldn't quite swing it.
# mabster
13/02/2009 7:24 AM
Hi Drew,
Yeah, this code won't take mouse clicks into account. Most of the time when I click into a TextBox it's because I want to move the caret to a specific position in the text. Selecting the text on a click would be really annoying in that use case.
# Drew Noakes
14/02/2009 5:28 AM
Hey Matt,
I take your point, but many text boxes out there take the first click to mean 'select all text', and any second click to mean 'position the caret here'. The address bar in most browsers works this way, for example.
I haven't been able to reproduce this behaviour in WPF yet, unfortunately.
Drew.
# Drew Noakes
14/02/2009 5:31 AM
PS. for my last response I had typed the message, clicked 'submit' and the postback gave a blank form with error message along the lines of 'no message'. I had to re-type my comment. The browser had been left on this page for some time. Is there a cookie that times out? This might be happening to other users too. It's lucky I only wrote a short message otherwise I wouldn't have bothered re-typing it.
# Robbert Dam
5/06/2009 7:26 PM
When you want to add "SelectAll on first click" take a look at here. Don't look at the accepted answer, but on the answer below from Donnelle
stackoverflow.com/.../how-to-automati
# gowtham
29/01/2010 10:21 PM
this is my .cs code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Speech;
using System.Speech.Synthesis;
using System.Windows.Forms;
using System.IO;
using System.Windows.Shapes;
namespace TextToSpeech
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
// Setting up the properties to speak.
private void SpeechButton_Click(object sender, RoutedEventArgs e)
{
int Volume;
int Rate;
SpeechSynthesizer foo = new SpeechSynthesizer();
ComboBoxItem volumeItem = (ComboBoxItem)comboBoxVolume.
Items[comboBoxVolume.SelectedIndex];
Volume = Convert.ToInt32(volumeItem.Content.ToString());
ComboBoxItem rateItem = (ComboBoxItem)comboBoxRate.
Items[comboBoxRate.SelectedIndex];
Rate = Convert.ToInt32(rateItem.Content.ToString());
foo.Volume = Volume;
foo.Rate = Rate;
foo.Speak(ConvertRichTextToString());
}
// Convert the contents of rich text box to string.
private string ConvertRichTextToString()
{
TextRange textRange = new TextRange(richTBoxContent.
Document.ContentStart, richTBoxContent.Document.ContentEnd);
return textRange.Text;
}
// Open any text file.
private void OpenTextFileButton_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog fileDialog = new OpenFileDialog();
fileDialog.InitialDirectory = @"C:\gowtham\";
fileDialog.Filter = "Text Files (*.txt)|*.txt";
fileDialog.RestoreDirectory = true;
if (fileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
LoadFile(fileDialog.FileName);
FileNameTextBox.Text = fileDialog.FileName;
}
}
// Load text file to the rich text box.
private void LoadFile(string File)
{
TextRange range;
FileStream fileStream;
if (System.IO.File.Exists(File))
{
range = new TextRange(richTBoxContent.Document.ContentStart,richTBoxContent.Document.ContentEnd);
fileStream = new FileStream(File, FileMode.OpenOrCreate);
range.Load(fileStream, System.Windows.DataFormats.Text);
fileStream.Close();
}
}
private void OpenTextFileButton_IsHitTestVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
}
private void FileNameTextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
}
}
}
# gowtham
29/01/2010 10:21 PM
and the following is my xaml code
<Window x:Class="TextToSpeech.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Text to Speech" Height="380" Width="580"
AllowsTransparency="False" WindowStyle="SingleBorderWindow">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="286*" />
<ColumnDefinition Width="272*" />
</Grid.ColumnDefinitions>
<TextBox Height="23" Margin="9,10,130,0" Name="FileNameTextBox" VerticalAlignment="Top"
Grid.ColumnSpan="2" />
<Button Height="23" HorizontalAlignment="Right" Margin="0,0,12,8" Name="SpeechButton" IsDefault="True"
VerticalAlignment="Bottom" Width="101" Click="SpeechButton_Click" Grid.Column="1">
Speak
</Button>
<RichTextBox Margin="0,45,0,67" Name="richTBoxContent" Background="WhiteSmoke"
Foreground="Black" Grid.ColumnSpan="2" />
<Button Height="23" Margin="0,10,12,0"
Name="OpenTextFileButton" Cursor="Wait" VerticalAlignment="Top"
Click="OpenTextFileButton_Click" Grid.Column="1" HorizontalAlignment="Right"
Width="110">
Open a Text File
</Button>
<ComboBox Height="23" Margin="90,0,76,30"
Name="comboBoxVolume" VerticalAlignment="Bottom"
SelectedIndex="4" >
<ComboBoxItem>10</ComboBoxItem>
<ComboBoxItem>20</ComboBoxItem>
<ComboBoxItem>30</ComboBoxItem>
<ComboBoxItem>40</ComboBoxItem>
<ComboBoxItem>50</ComboBoxItem>
<ComboBoxItem>60</ComboBoxItem>
<ComboBoxItem>70</ComboBoxItem>
<ComboBoxItem>80</ComboBoxItem>
<ComboBoxItem>90</ComboBoxItem>
<ComboBoxItem>100</ComboBoxItem>
</ComboBox>
<Label Height="28" HorizontalAlignment="Left" Margin="32,0,0,25"
Name="labelVolume" VerticalAlignment="Bottom" Width="51">
Volume:</Label>
<ComboBox Height="23" Margin="22,0,130,30"
Name="comboBoxRate" VerticalAlignment="Bottom"
SelectedIndex="2" Grid.Column="1">
<ComboBoxItem>-10</ComboBoxItem>
<ComboBoxItem>-5</ComboBoxItem>
<ComboBoxItem>0</ComboBoxItem>
<ComboBoxItem>5</ComboBoxItem>
<ComboBoxItem>10</ComboBoxItem>
</ComboBox>
<Label Height="28" Margin="268,0,249,25" Name="labelRate"
VerticalAlignment="Bottom" Grid.ColumnSpan="2">
Rate:</Label>
</Grid>
</Window>
# gowtham
29/01/2010 10:23 PM
when i execute it my cursor ll not be placed by default in the text box. i wanted ur help to place the cursor in the text box (open text file) when i run my application
# Luiz Arruda
9/08/2010 8:52 PM
I've seen other solutions on this issue, but yours is by far the most compact and simple! Great Job! Thanks!
# Anonymous
11/11/2010 9:19 AM
Since this is google-juiced I will add this, it extends the example in the original blog to select all on mouse click.
protected override void OnStartup(StartupEventArgs e)
{
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.GotFocusEvent, new RoutedEventHandler(TextBox_GotFocus));
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.PreviewMouseDownEvent, new RoutedEventHandler(TextBox_PreviewMouseDown));
base.OnStartup(e);
}
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
(sender as TextBox).SelectAll();
}
private void TextBox_PreviewMouseDown(object sender, RoutedEventArgs e)
{
TextBox textBox = sender as TextBox;
if (!textBox.IsFocused)
{
textBox.Focus();
textBox.SelectAll();
e.Handled = true;
}
}
# Conrad
24/02/2011 7:04 AM
Ok, I am obviously a newbie who is missing something obvious. I am attempting to implement this, but VS is not liking TextBox.GotFocusEvent - the error I get is:
'System.Windows.Forms.TextBox' does not contain a definition for 'GotFocusEvent'
What am I missing here? Thanks for the assistance.
# Conrad
24/02/2011 7:57 AM
Figured it out - I was 'using System.Windows.Forms' instead of System.Windows.Controls... D'OH!
But now another problem - App.OnStartup is not being called. In App.xaml there is StartupUri="MainWindow.xaml" (and maybe not 'Startup="App.xaml"'?) - is this why OnStartup isn't getting called?
# Conrad
24/02/2011 8:03 AM
Really should look harder first...
The RegisterClassHandler and assoc method needed to be in the MainWindow code, as that is the real "enclosing" class for all the frames. Hope this helps someone avoid my problems in the future.
# Thomas
19/07/2011 11:55 PM
Very usefull! Thank you, for the contribution.
# Liam
16/10/2011 8:39 PM
Hi Mat
your solution for a wpf datepicker matermark is what I am using to try to emulate the UI behaviour whereby a user selects the textbox portion of the datepicker and it will auto SelectAll existing text on one click
However I need the watermark blank also (got a very picky user).
I couldn't seem to register two handlers for datepicker so I just used the solution for the watermark but using the routedevent "PreviewOnMouseDown" and then did a selectAll on the childtype textbox.
This works except I have to double click it to highlight the text. This is still a fail in the users eyes as they just want one click as per web UI behaviour rather than windows UI behaviour.
Interestingly when you single click the DatePicker textbox with text already in it, the textbox is highlighted but very fleetingly and then it is deselected. If I step thru debug it that deselect event never fires and the text remains selected using the SelectAll() method.
If there is no easy solution I don't mind as I can inform the user of this!
Lastly, I hear WPF is to be deprecated (in an unofficial manner. Is this true?
Keep up the good work Mat. Good solutions, very concise and to the point. Well done mate.
# mabster
17/10/2011 7:44 AM
Liam,
The "select all on focus" trick really only works when you focus using the keyboard. Since it's so easy to select all using the mouse (as you say - you can just double click) I didn't bother looking into programatically doing it when the control gains focus via a click.
That'd be why your users are seeing the behaviour you describe - they're clicking rather than than tabbing into the control.
As for WPF being "deprecated" ... I prefer to use the term "done". :) The next version, 4.5, introduces a few new performance-related features, but I don't see the team adding anything major after that. The focus for Windows client apps seems to have shifted to WinRT on Windows 8, which has a lot in common with WPF, so your skills won't go to waste.
Of course, WinRT is *only* for Windows 8, so until the world moves to that your WPF skills are as relevant as ever! And heck, WPF apps still run on Windows 8 so there's no reason to shift even then.
# dwhite
11/01/2012 3:21 AM
Very nice. Thanks for sharing!
# Mike
21/01/2012 4:24 AM
Thanks!
# Doug
3/03/2012 10:48 AM
Very elegant solution. Thanks!
# Vinay
3/03/2012 7:41 PM
nice. helped me
# Srini
2/09/2012 3:50 AM
I thought select all when you tab into was the default Windows does. Why do we even need this handler. Confused on what we get by adding this. Learned something new though!
# Travis
23/03/2013 8:41 AM
This really works well for me ... selects all on keyboard focus, or click, but will allow a user to click and select at the same time to make a selection without the select all...
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
// Select all text only if the mouse isn't down.
// This makes tabbing to the textbox select all.
TextBox textBox = sender as TextBox;
if (Mouse.LeftButton == MouseButtonState.Released)
{
textBox.SelectAll();
textBox.Tag = true; //use the tag propety to signal that the box is already focused
}
}
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
TextBox textBox = sender as TextBox;
textBox.SelectionLength = 0;
textBox.Tag = false; //use the tag propety to signal that the box is already focused
}
private void TextBox_PreviewMouseUp(object sender, RoutedEventArgs e)
{
// If a user clicked in, want to select all text, unless they made a different selection...
// so select all only if the textbox isn't already focused, and the user hasn't selected any text.
TextBox textBox = sender as TextBox;
if ((textBox.Tag == null || (bool)textBox.Tag == false) && textBox.SelectionLength == 0)
{
textBox.Tag = true; //use the tag propety to signal that the box is already focused
textBox.SelectAll();
}
}
# Vishal Agarwal
6/08/2013 5:47 AM
Thanks a lot!
# Gilberto W. Alexandre
12/10/2013 7:16 AM
Thanks! Very nice.
# Ramesh
23/01/2014 7:40 PM
Thanks for the solution. Is there any way to keep the cursor at the beginning of the text but the text should be selected ? I understood that SelectAll() method selects the entire content but the cursor position is moved to the end of the text but I need it at the beginning of text without removing the selection. Highly appreciated if you provide solution.
# Daniel
11/02/2014 7:23 PM
Awesome solution, neat, simple and efficient.
# Tate
19/11/2014 12:27 AM
Just solved a potential headache for me - thanks so much!
# Simon
17/02/2015 7:15 PM
Thanks, works beautifully, I also added the MouseUp Event so it works when clicking on it and not just tabbing to it... thanks again saved days of work
# Mike
31/03/2015 7:20 AM
5 years later,the Google juice is still working splendidly - thanks!
# Irene
19/05/2015 4:01 AM
Very nice and neat. Thanks! I had a problem with the fact that the first textbox is not selected on load, but I solved it by setting the focus to my first textbox and calling select all in the Activate event. (I tried on load but the text box has no contents at that point.)
# Andre
21/07/2015 9:35 PM
Just what i was looking for!
# Rob
26/04/2017 7:11 PM
Not working on DataGrid
# Mike Mohr
10/04/2019 12:16 AM
I realize this is 10 years old, but it works like a charm! And I love that it works for all textboxes!
Really elegant solution! Microsoft should have done this! (or at least made it an option).
Nice job Matt!