Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

wpf - Initial Focus and Select All behavior

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...

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...