Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initial Focus and Select All behavior

Tags:

focus

wpf

I have a user control that is nested inside a window that is acting as a shell for a dialog display. I ignore focus in the shell window, and in the hosted user control I use the FocusManager to set the initial focus to a named element (a textbox) as shown below.

This works, setting the cursor at the beginning of the named textbox; however I want all text to be selected.

The TextBoxSelectionBehavior class (below) usually does exactly that, but not in this case. Is there an easy xaml fix to get the text in the named textbox selected on initial focus?

Cheers,
Berryl

TextBox Selection Behavior

// in app startup
TextBoxSelectionBehavior.RegisterTextboxSelectionBehavior();

/// <summary>
/// Helper to select all text in the text box on entry
/// </summary>
public static class TextBoxSelectionBehavior
{
    public static void RegisterTextboxSelectionBehavior()
    {
        EventManager.RegisterClassHandler(typeof(TextBox), UIElement.GotFocusEvent, new RoutedEventHandler(OnTextBox_GotFocus));
    }

    private static void OnTextBox_GotFocus(object sender, RoutedEventArgs e)
    {
        var tb = (sender as TextBox);
        if (tb != null)
            tb.SelectAll();
    }
}

The hosted UserControl

<UserControl   
<DockPanel KeyboardNavigation.TabNavigation="Local" 
    FocusManager.FocusedElement="{Binding ElementName=tbLastName}" >

            <TextBox x:Name="tbLastName" ... />

stop gap solution

Per comments with Rachel below, I ditched the FocusManger in favor of some code behind:

tbLastName.Loaded += (sender, e) => tbLastName.Focus();

Still would love a declarative approach for a simple and common chore though...

like image 964
Berryl Avatar asked Oct 18 '11 14:10

Berryl


2 Answers

I usually use an AttachedProperty to make TextBoxes highlight their text on focus. It is used like

<TextBox local:HighlightTextOnFocus="True" />

Code for attached property

public static readonly DependencyProperty HighlightTextOnFocusProperty =
    DependencyProperty.RegisterAttached("HighlightTextOnFocus", 
    typeof(bool), typeof(TextBoxProperties),
    new PropertyMetadata(false, HighlightTextOnFocusPropertyChanged));


[AttachedPropertyBrowsableForChildrenAttribute(IncludeDescendants = false)]
[AttachedPropertyBrowsableForType(typeof(TextBox))]
public static bool GetHighlightTextOnFocus(DependencyObject obj)
{
    return (bool)obj.GetValue(HighlightTextOnFocusProperty);
}

public static void SetHighlightTextOnFocus(DependencyObject obj, bool value)
{
    obj.SetValue(HighlightTextOnFocusProperty, value);
}

private static void HighlightTextOnFocusPropertyChanged(
        DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
    var sender = obj as UIElement;
    if (sender != null)
    {
        if ((bool)e.NewValue)
        {
            sender.GotKeyboardFocus += OnKeyboardFocusSelectText;
            sender.PreviewMouseLeftButtonDown += OnMouseLeftButtonDownSetFocus;
        }
        else
        {
            sender.GotKeyboardFocus -= OnKeyboardFocusSelectText;
            sender.PreviewMouseLeftButtonDown -= OnMouseLeftButtonDownSetFocus;
        }
    }
}

private static void OnKeyboardFocusSelectText(
    object sender, KeyboardFocusChangedEventArgs e)
{
    var textBox = e.OriginalSource as TextBox;
    if (textBox != null)
    {
        textBox.SelectAll();
    }
}

private static void OnMouseLeftButtonDownSetFocus(
    object sender, MouseButtonEventArgs e)
{
    TextBox tb = FindAncestor<TextBox>((DependencyObject)e.OriginalSource);

    if (tb == null)
        return;

    if (!tb.IsKeyboardFocusWithin)
    {
        tb.Focus();
        e.Handled = true;
    }
}

static T FindAncestor<T>(DependencyObject current)
    where T : DependencyObject
{
    current = VisualTreeHelper.GetParent(current);

    while (current != null)
    {
        if (current is T)
        {
            return (T)current;
        }
        current = VisualTreeHelper.GetParent(current);
    };
    return null;
}

Edit

Based on comments below, what about just getting rid of the FocusManager.FocusedElement and setting tb.Focus() and tb.SelectAll() in the Loaded event of your TextBox?

like image 194
Rachel Avatar answered Sep 27 '22 17:09

Rachel


As stated above, you can add an event handler for the Loaded event to set focus and select all text:

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();

        base.DataContext = new Person { FirstName = "Joe", LastName = "Smith" };

        base.Loaded += delegate
        {
            this._firstNameTextBox.Focus();
            this._firstNameTextBox.SelectAll();
        };
    }
}  
like image 32
Andy Avatar answered Sep 27 '22 18:09

Andy