Programing

WPF TextBox에서 모든 텍스트를 자동으로 선택하는 방법은 무엇입니까?

lottogame 2020. 5. 1. 08:00
반응형

WPF TextBox에서 모든 텍스트를 자동으로 선택하는 방법은 무엇입니까?


이벤트 처리기 SelectAll에서 호출 GotFocus하면 마우스에서 작동하지 않습니다. 마우스를 놓으면 선택 항목이 사라집니다.

편집 : 사람들은 Donnelle의 대답을 좋아합니다. 왜 내가 받아 들인 대답만큼 그것을 좋아하지 않는지 설명하려고 노력할 것입니다.

  • 허용 된 답변이 더 간단한 방식으로 동일한 작업을 수행하는 동안 더 복잡합니다.
  • 허용 된 답변의 유용성이 더 좋습니다. 텍스트 중간을 클릭하면 마우스를 놓으면 텍스트가 선택 해제되어 즉시 편집을 시작할 수 있으며, 여전히 모두를 선택하려면 버튼을 다시 누르십시오. 이번에는 릴리스시 선택이 해제되지 않습니다. Donelle의 레시피에 따라 텍스트 중간을 클릭하면 편집 할 수 있도록 두 번 클릭해야합니다. 텍스트 내부와 텍스트 외부의 어딘가를 클릭하면 모든 것을 덮어 쓰지 않고 편집을 시작하고 싶습니다.

왜 GotFocus 이벤트에서 선택 항목을 잃는 지 모르겠습니다.

그러나 한 가지 해결책은 GotKeyboardFocus 및 GotMouseCapture 이벤트에서 선택하는 것입니다. 그렇게하면 항상 작동합니다.


우리는 첫 번째 클릭이 모두를 선택하고 다른 클릭이 커서로 이동하도록했습니다 (우리의 응용 프로그램은 펜이있는 태블릿에서 사용하도록 설계되었습니다).

유용 할 수 있습니다.

public class ClickSelectTextBox : TextBox
{
    public ClickSelectTextBox()
    {
        AddHandler(PreviewMouseLeftButtonDownEvent, 
          new MouseButtonEventHandler(SelectivelyIgnoreMouseButton), true);
        AddHandler(GotKeyboardFocusEvent, 
          new RoutedEventHandler(SelectAllText), true);
        AddHandler(MouseDoubleClickEvent, 
          new RoutedEventHandler(SelectAllText), true);
    }

    private static void SelectivelyIgnoreMouseButton(object sender, 
                                                     MouseButtonEventArgs e)
    {
        // Find the TextBox
        DependencyObject parent = e.OriginalSource as UIElement;
        while (parent != null && !(parent is TextBox))
            parent = VisualTreeHelper.GetParent(parent);

        if (parent != null)
        {
            var textBox = (TextBox)parent;
            if (!textBox.IsKeyboardFocusWithin)
            {
                // If the text box is not yet focussed, give it the focus and
                // stop further processing of this click event.
                textBox.Focus();
                e.Handled = true;
            }
        }
    }

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

Donnelle의 답변이 가장 효과적이지만, 그것을 사용하기 위해 새로운 클래스를 이끌어내는 것은 고통입니다.

대신 응용 프로그램의 모든 TextBox에 대해 처리기를 App.xaml.cs의 처리기에 등록합니다. 이를 통해 표준 TextBox 컨트롤과 함께 Donnelle의 답변을 사용할 수 있습니다.

App.xaml.cs에 다음 방법을 추가하십시오.

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e) 
    {
        // Select the text in a TextBox when it receives focus.
        EventManager.RegisterClassHandler(typeof(TextBox), TextBox.PreviewMouseLeftButtonDownEvent,
            new MouseButtonEventHandler(SelectivelyIgnoreMouseButton));
        EventManager.RegisterClassHandler(typeof(TextBox), TextBox.GotKeyboardFocusEvent, 
            new RoutedEventHandler(SelectAllText));
        EventManager.RegisterClassHandler(typeof(TextBox), TextBox.MouseDoubleClickEvent,
            new RoutedEventHandler(SelectAllText));
        base.OnStartup(e); 
    }

    void SelectivelyIgnoreMouseButton(object sender, MouseButtonEventArgs e)
    {
        // Find the TextBox
        DependencyObject parent = e.OriginalSource as UIElement;
        while (parent != null && !(parent is TextBox))
            parent = VisualTreeHelper.GetParent(parent);

        if (parent != null)
        {
            var textBox = (TextBox)parent;
            if (!textBox.IsKeyboardFocusWithin)
            {
                // If the text box is not yet focused, give it the focus and
                // stop further processing of this click event.
                textBox.Focus();
                e.Handled = true;
            }
        }
    }

    void SelectAllText(object sender, RoutedEventArgs e)
    {
        var textBox = e.OriginalSource as TextBox;
        if (textBox != null)
            textBox.SelectAll();
    }
}

이것은 다소 오래되었지만 어쨌든 내 대답을 표시합니다.
나는 이것이 사용자에게 가장 놀랍게 만든다고 생각하기 때문에 Donnelle의 답변 중 일부를 선택했습니다 (더블 클릭을 건너 뛰었습니다). 그러나 gcore와 마찬가지로 파생 클래스를 만들어야 할 필요가 없습니다. 그러나 나는 또한 "시작시 ..."방법을 좋아하지 않습니다. 그리고 저는 이것을 "일반적으로 항상 그런 것은 아닙니다"기반으로 필요합니다.

나는 이것을 SelectTextOnFocus.Active=Truexaml에서 설정할 수 있도록 연결된 종속성 속성으로 구현했습니다 . 나는이 방법이 가장 기쁘게 생각합니다.

namespace foo.styles.behaviour
{
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;

    public class SelectTextOnFocus : DependencyObject
    {
        public static readonly DependencyProperty ActiveProperty = DependencyProperty.RegisterAttached(
            "Active",
            typeof(bool),
            typeof(SelectTextOnFocus),
            new PropertyMetadata(false, ActivePropertyChanged));

        private static void ActivePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is TextBox)
            {
                TextBox textBox = d as TextBox;
                if ((e.NewValue as bool?).GetValueOrDefault(false))
                {
                    textBox.GotKeyboardFocus += OnKeyboardFocusSelectText;
                    textBox.PreviewMouseLeftButtonDown += OnMouseLeftButtonDown;
                }
                else
                {
                    textBox.GotKeyboardFocus -= OnKeyboardFocusSelectText;
                    textBox.PreviewMouseLeftButtonDown -= OnMouseLeftButtonDown;
                }
            }
        }

        private static void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            DependencyObject dependencyObject = GetParentFromVisualTree(e.OriginalSource);

            if (dependencyObject == null)
            {
                return;
            }

            var textBox = (TextBox)dependencyObject;
            if (!textBox.IsKeyboardFocusWithin)
            {
                textBox.Focus();
                e.Handled = true;
            }
        }

        private static DependencyObject GetParentFromVisualTree(object source)
        {
            DependencyObject parent = source as UIElement;
            while (parent != null && !(parent is TextBox))
            {
                parent = VisualTreeHelper.GetParent(parent);
            }

            return parent;
        }

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

        [AttachedPropertyBrowsableForChildrenAttribute(IncludeDescendants = false)]
        [AttachedPropertyBrowsableForType(typeof(TextBox))]
        public static bool GetActive(DependencyObject @object)
        {
            return (bool) @object.GetValue(ActiveProperty);
        }

        public static void SetActive(DependencyObject @object, bool value)
        {
            @object.SetValue(ActiveProperty, value);
        }
    }
}

"일반적이지는 않지만 항상"기능을 위해 (글로벌) TextBox 스타일에서이 속성을 True로 설정했습니다. 이 방법으로 "텍스트 선택"은 항상 "켜짐"이지만 텍스트 상자별로 비활성화 할 수 있습니다.


다음은 편의를 위해 답변 솔루션을 구현하는 혼합 동작입니다.

하나의 TextBox에 연결하기위한 것 :

public class SelectAllTextOnFocusBehavior : Behavior<TextBox>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.GotKeyboardFocus += AssociatedObjectGotKeyboardFocus;
        AssociatedObject.GotMouseCapture += AssociatedObjectGotMouseCapture;
        AssociatedObject.PreviewMouseLeftButtonDown += AssociatedObjectPreviewMouseLeftButtonDown;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.GotKeyboardFocus -= AssociatedObjectGotKeyboardFocus;
        AssociatedObject.GotMouseCapture -= AssociatedObjectGotMouseCapture;
        AssociatedObject.PreviewMouseLeftButtonDown -= AssociatedObjectPreviewMouseLeftButtonDown;
    }

    private void AssociatedObjectGotKeyboardFocus(object sender,
        System.Windows.Input.KeyboardFocusChangedEventArgs e)
    {
        AssociatedObject.SelectAll();
    }

    private void AssociatedObjectGotMouseCapture(object sender,
        System.Windows.Input.MouseEventArgs e)
    {
        AssociatedObject.SelectAll();   
    }

    private void AssociatedObjectPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if(!AssociatedObject.IsKeyboardFocusWithin)
        {
            AssociatedObject.Focus();
            e.Handled = true;
        }
    }
}

그리고 여러 TextBox를 포함하는 컨테이너의 루트에 연결하는 하나 :

public class SelectAllTextOnFocusMultiBehavior : Behavior<UIElement>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.GotKeyboardFocus += HandleKeyboardFocus;
        AssociatedObject.GotMouseCapture += HandleMouseCapture;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.GotKeyboardFocus -= HandleKeyboardFocus;
        AssociatedObject.GotMouseCapture -= HandleMouseCapture;
    }

    private static void HandleKeyboardFocus(object sender,
        System.Windows.Input.KeyboardFocusChangedEventArgs e)
    {
        var txt = e.NewFocus as TextBox;
        if (txt != null)
            txt.SelectAll();
    }

    private static void HandleMouseCapture(object sender,
        System.Windows.Input.MouseEventArgs e)
    {
        var txt = e.OriginalSource as TextBox;
        if (txt != null)
            txt.SelectAll();
    }
}

이것은 오래된 질문이지만 방금이 문제가 있었지만 Sergey의 답변에서와 같이 표현식 동작이 아닌 첨부 된 동작을 사용하여 문제를 해결했습니다. 이것은 System.Windows.InteractivityBlend SDK에서 종속성이 필요하지 않음을 의미합니다 .

public class TextBoxBehavior
{
    public static bool GetSelectAllTextOnFocus(TextBox textBox)
    {
        return (bool)textBox.GetValue(SelectAllTextOnFocusProperty);
    }

    public static void SetSelectAllTextOnFocus(TextBox textBox, bool value)
    {
        textBox.SetValue(SelectAllTextOnFocusProperty, value);
    }

    public static readonly DependencyProperty SelectAllTextOnFocusProperty =
        DependencyProperty.RegisterAttached(
            "SelectAllTextOnFocus",
            typeof (bool),
            typeof (TextBoxBehavior),
            new UIPropertyMetadata(false, OnSelectAllTextOnFocusChanged));

    private static void OnSelectAllTextOnFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var textBox = d as TextBox;
        if (textBox == null) return;

        if (e.NewValue is bool == false) return;

        if ((bool) e.NewValue)
        {
            textBox.GotFocus += SelectAll;
            textBox.PreviewMouseDown += IgnoreMouseButton;
        }
        else
        {
            textBox.GotFocus -= SelectAll;
            textBox.PreviewMouseDown -= IgnoreMouseButton;
        }
    }

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

    private static void IgnoreMouseButton(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        var textBox = sender as TextBox;
        if (textBox == null || (!textBox.IsReadOnly && textBox.IsKeyboardFocusWithin)) return;

        e.Handled = true;
        textBox.Focus();
    }
}

그런 다음 XAML에서 다음과 같이 사용할 수 있습니다.

<TextBox Text="Some Text" behaviors:TextBoxBehavior.SelectAllTextOnFocus="True"/>

나는 그것에 대해 블로그에 올렸 습니다 .


다음은 MSDN의 매우 간단한 솔루션입니다 .

<TextBox
    MouseDoubleClick="SelectAddress"
    GotKeyboardFocus="SelectAddress"
    PreviewMouseLeftButtonDown="SelectivelyIgnoreMouseButton" />

코드는 다음과 같습니다.

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

private void SelectivelyIgnoreMouseButton(object sender,
    MouseButtonEventArgs e)
{
    TextBox tb = (sender as TextBox);
    if (tb != null)
    {
        if (!tb.IsKeyboardFocusWithin)
        {
            e.Handled = true;
            tb.Focus();
        }
    }
}

나는 이것이 잘 작동한다고 생각한다.

private void ValueText_GotFocus(object sender, RoutedEventArgs e)
    {
        TextBox tb = (TextBox)e.OriginalSource;
        tb.Dispatcher.BeginInvoke(
            new Action(delegate
                {
                    tb.SelectAll();
                }), System.Windows.Threading.DispatcherPriority.Input);
    }

확장 메소드로 구현하려면 다음을 수행하십시오.

public static void SelectAllText(this System.Windows.Controls.TextBox tb)
    {
        tb.Dispatcher.BeginInvoke(
            new Action(delegate
            {
                tb.SelectAll();
            }), System.Windows.Threading.DispatcherPriority.Input);
    }

그리고 GotFocus 이벤트에서 :

private void ValueText_GotFocus(object sender, RoutedEventArgs e)
    {
        TextBox tb = (TextBox)e.OriginalSource;
        tb.SelectAllText();
    }

몇 달 전에 주어진 UIElement에 초점을 맞추는 방법을 찾고 있었기 때문에 위의 솔루션을 발견했습니다. 나는 아래 어딘가에 코드를 발견했고 (신용이 주어짐) 잘 작동합니다. UIElement로 작업하기 위해 Dispatcher를 사용하는 것과 동일한 패턴을 보여주기 때문에 OP의 질문과 직접 ​​관련이 없지만 게시합니다.

// Sets focus to uiElement
    public static void DelayedFocus(this UIElement uiElement)
    {
        uiElement.Dispatcher.BeginInvoke(
        new Action(delegate
        {
            uiElement.Focusable = true;
            uiElement.Focus();
            Keyboard.Focus(uiElement);
        }),
        DispatcherPriority.Render);
    }

여기에 제시된 답변 중 어느 것도 표준 Windows 텍스트 상자와 유사하지 않습니다. 예를 들어, 텍스트 상자의 마지막 문자와 텍스트 상자의 오른쪽 사이에있는 공백을 클릭하십시오. 여기에있는 대부분의 솔루션은 항상 전체 내용을 선택하므로 텍스트 상자에 텍스트를 추가하기가 매우 어렵습니다.

여기에 내가 제시 한 대답은이 점에서 더 잘 작동합니다. 동작이므로 Blend SDKSystem.Windows.Interactivity 어셈블리가 필요합니다 . 연결된 속성을 사용하여 다시 작성할 수도 있습니다.

public sealed class SelectAllTextOnFocusBehavior : Behavior<TextBox>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.PreviewMouseLeftButtonDown += AssociatedObject_PreviewMouseLeftButtonDown;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.PreviewMouseLeftButtonDown -= AssociatedObject_PreviewMouseLeftButtonDown;
    }

    void AssociatedObject_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        // Find the textbox
        DependencyObject parent = e.OriginalSource as UIElement;
        while (parent != null && !(parent is TextBox))
            parent = VisualTreeHelper.GetParent(parent);

        var textBox = parent as TextBox;
        Debug.Assert(textBox != null);

        if (textBox.IsFocused) return;

        textBox.SelectAll();
        Keyboard.Focus(textBox);
        e.Handled = true;
    }
}

이것은 내가 찾은 코드를 기반으로 여기에 .


이 간단한 구현은 나에게 완벽하게 작동합니다.

void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    ((TextBox) sender).SelectAll();
}

void TextBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    var TextBox = (TextBox) sender;
    if (!TextBox.IsKeyboardFocusWithin)
    {
        TextBox.Focus();
        e.Handled = true;
    }
}

모두에 적용하려면 TextBox다음 코드를InitializeComponent();

EventManager.RegisterClassHandler(typeof(TextBox), TextBox.GotFocusEvent, new RoutedEventHandler(TextBox_GotFocus));
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.PreviewMouseDownEvent, new MouseButtonEventHandler(TextBox_PreviewMouseDown));

App.xaml 파일에서

<Application.Resources>
    <Style TargetType="TextBox">
        <EventSetter Event="GotKeyboardFocus" Handler="TextBox_GotKeyboardFocus"/>
    </Style>
</Application.Resources>

App.xaml.cs 파일에서

private void TextBox_GotKeyboardFocus(Object sender, KeyboardFocusChangedEventArgs e)
    {
        ((TextBox)sender).SelectAll();
    }

이 코드를 사용하면 응용 프로그램의 모든 TextBox에 도달합니다.


여기 에서 찍은 :

App.xaml.cs 파일에 글로벌 이벤트 핸들러를 등록하십시오.

protected override void OnStartup(StartupEventArgs e)
{
    EventManager.RegisterClassHandler(typeof(TextBox),TextBox.GotFocusEvent,
    new RoutedEventHandler(TextBox_GotFocus));

    base.OnStartup(e);
}

그런 다음 핸들러는 다음과 같이 간단합니다.

private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    (sender as TextBox).SelectAll();
}

브라우저의 일반적인 기능을 모방하는 것처럼 보이는 PreviewMouseLeftButtonDown 이벤트와 함께 약간 단순화 된 답변이 있습니다.

xaml에는 다음과 같은 텍스트 상자가 있습니다.

<TextBox Text="http://www.blabla.com" BorderThickness="2" BorderBrush="Green" VerticalAlignment="Center" Height="25"
                 PreviewMouseLeftButtonDown="SelectAll" />

코드 숨김에서 :

private void SelectAll(object sender, MouseButtonEventArgs e)
{

    TextBox tb = (sender as TextBox);

    if (tb == null)
    {
        return;
    }

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

나는 이것이 매우 오래되었다는 것을 알고 있지만 여기에 표현식 / Microsoft 상호 작용 및 상호 작용 네임 스페이스를 기반으로하는 솔루션이 있습니다.

먼저이 링크 의 지침 따라 대화 형 트리거를 스타일에 배치했습니다.

그런 다음이

        <Style x:Key="baseTextBox" TargetType="TextBox">
        <Setter Property="gint:InteractivityItems.Template">
            <Setter.Value>
                <gint:InteractivityTemplate>
                    <gint:InteractivityItems>
                        <gint:InteractivityItems.Triggers>
                            <i:EventTrigger EventName="GotKeyboardFocus">
                                <ei:CallMethodAction MethodName="SelectAll"/>
                            </i:EventTrigger>
                            <i:EventTrigger EventName="PreviewMouseLeftButtonDown">
                                <ei:CallMethodAction MethodName="TextBox_PreviewMouseLeftButtonDown"
                                    TargetObject="{Binding ElementName=HostElementName}"/>
                            </i:EventTrigger>
                        </gint:InteractivityItems.Triggers>
                    </gint:InteractivityItems>
                </gint:InteractivityTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    public void TextBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        TextBox tb = e.Source as TextBox;
        if((tb != null) && (tb.IsKeyboardFocusWithin == false))
        {
            tb.Focus();
            e.Handled = true;
        }
    }

필자의 경우 텍스트 상자가 코드 숨김이있는 위치에 사용자 정의 컨트롤이 있습니다. 코드 숨김에는 처리기 기능이 있습니다. 사용자 컨트롤에 xaml로 이름을 지정했으며 요소에 해당 이름을 사용하고 있습니다. 이것은 나를 위해 완벽하게 작동합니다. 텍스트 상자를 클릭 할 때 모든 텍스트를 선택하려는 텍스트 상자에 스타일을 적용하기 만하면됩니다.

첫 번째 CallMethodAction은 텍스트 상자에서 GotKeyboardFocus 이벤트가 발생할 때 텍스트 상자의 SelectAll 함수를 호출합니다.

이게 도움이 되길 바란다.


Donnelle / Groky의 접근 방식에 관심이 있지만 입력 한 텍스트의 끝에 캐럿을 배치하기 위해 마지막 문자 (그러나 여전히 TextBox 내)의 오른쪽 클릭을 원한다면이 솔루션을 생각해 냈습니다.

    int GetRoundedCharacterIndexFromPoint(TextBox textBox, Point clickedPoint)
    {
        int position = textBox.GetCharacterIndexFromPoint(clickedPoint, true);

        // Check if the clicked point is actually closer to the next character
        // or if it exceeds the righmost character in the textbox
        // (in this case return increase the position by 1)
        Rect charLeftEdge = textBox.GetRectFromCharacterIndex(position, false);
        Rect charRightEdge = textBox.GetRectFromCharacterIndex(position, true);
        double charWidth = charRightEdge.X - charLeftEdge.X;
        if (clickedPoint.X + charWidth / 2 > charLeftEdge.X + charWidth) position++;

        return position;
    }

    void SelectivelyIgnoreMouseButton(object sender, MouseButtonEventArgs e)
    {
        // Find the TextBox
        DependencyObject parent = e.OriginalSource as UIElement;
        while (parent != null && !(parent is TextBox))
            parent = VisualTreeHelper.GetParent(parent);

        if (parent != null)
        {
            var textBox = (TextBox)parent;
            if (!textBox.IsKeyboardFocusWithin)
            {
                // If the text box is not yet focused, give it the focus and
                // stop further processing of this click event.
                textBox.Focus();
                e.Handled = true;
            }
            else
            {
                int pos = GetRoundedCharacterIndexFromPoint(textBox, e.GetPosition(textBox));
                textBox.CaretIndex = pos;
            }
        }
    }

    void SelectAllText(object sender, RoutedEventArgs e)
    {
        var textBox = e.OriginalSource as TextBox;
        if (textBox != null)
            textBox.SelectAll();
    }

게시물 에서 GetRoundedCharacterIndexFromPoint 메서드를 가져 왔습니다 .


    #region TextBoxIDCard selection
    private bool textBoxIDCardGotFocus = false;
    private void TextBoxIDCard_GotFocus(object sender, RoutedEventArgs e)
    {
        this.TextBoxIDCard.SelectAll();
    }

    private void TextBoxIDCard_LostFocus(object sender, RoutedEventArgs e)
    {
        textBoxIDCardGotFocus = false;
    }

    private void TextBoxIDCard_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        if (textBoxIDCardGotFocus == false)
        {
            e.Handled = true;
            this.TextBoxIDCard.Focus();
            textBoxIDCardGotFocus = true;
        }
    } 
    #endregion

TextBox 컨트롤에 원하는 동작을 추가하려면이 확장 방법을 사용하십시오. 아직 광범위하게 테스트하지는 않았지만 내 요구를 충족시키는 것 같습니다.

public static class TextBoxExtensions
{
    public static void SetupSelectAllOnGotFocus(this TextBox source)
    {
        source.GotFocus += SelectAll;
        source.PreviewMouseLeftButtonDown += SelectivelyIgnoreMouseButton;
    }

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

    private static void SelectivelyIgnoreMouseButton(object sender, MouseButtonEventArgs e)
    {
        var textBox = (sender as TextBox);
        if (textBox != null)
        {
            if (!textBox.IsKeyboardFocusWithin)
            {
                e.Handled = true;
                textBox.Focus();
            }
        }
    }
}

나는 해결책을 많이 찾았고 선택해야 할 몇 가지 해결책을 찾았지만 문제는 텍스트 상자에서 텍스트의 일부를 선택한 후 마우스 오른쪽 버튼을 클릭하고 잘라 내기 / 복사를 할 때 텍스트의 선택한 부분조차 모두 선택한다는 것입니다. 이 문제를 해결하려면 해결책이 있습니다. 키보드 선택 이벤트에 아래 코드를 추가하십시오. 이것은 나를 위해 일했습니다.

private static void SelectContentsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if (d is TextBox)
    {
        TextBox textBox = d as TextBox;
        if ((e.NewValue as bool?).GetValueOrDefault(false))
        {
            textBox.GotKeyboardFocus += OnKeyboardFocusSelectText;                 
        }
        else
        {
            textBox.GotKeyboardFocus -= OnKeyboardFocusSelectText;

        }
    }
}


private static void OnKeyboardFocusSelectText(object sender, KeyboardFocusChangedEventArgs e)
{
    if (e.KeyboardDevice.IsKeyDown(Key.Tab))
        ((TextBox)sender).SelectAll();
}

나는 Nils의 대답을 사용했지만 더 유연하게 전환했습니다.

public enum SelectAllMode
{

    /// <summary>
    ///  On first focus, it selects all then leave off textbox and doesn't check again
    /// </summary>
    OnFirstFocusThenLeaveOff = 0,

    /// <summary>
    ///  On first focus, it selects all then never selects
    /// </summary>
    OnFirstFocusThenNever = 1,

    /// <summary>
    /// Selects all on every focus
    /// </summary>
    OnEveryFocus = 2,

    /// <summary>
    /// Never selects text (WPF's default attitude)
    /// </summary>
    Never = 4,
}

public partial class TextBox : DependencyObject
{
    public static readonly DependencyProperty SelectAllModeProperty = DependencyProperty.RegisterAttached(
        "SelectAllMode",
        typeof(SelectAllMode?),
        typeof(TextBox),
        new PropertyMetadata(SelectAllModePropertyChanged));

    private static void SelectAllModePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is System.Windows.Controls.TextBox)
        {
            var textBox = d as System.Windows.Controls.TextBox;

            if (e.NewValue != null)
            {
                textBox.GotKeyboardFocus += OnKeyboardFocusSelectText;
                textBox.PreviewMouseLeftButtonDown += OnMouseLeftButtonDown;
            }
            else
            {
                textBox.GotKeyboardFocus -= OnKeyboardFocusSelectText;
                textBox.PreviewMouseLeftButtonDown -= OnMouseLeftButtonDown;
            }
        }
    }

    private static void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        DependencyObject dependencyObject = GetParentFromVisualTree(e.OriginalSource);

        if (dependencyObject == null)
            return;

        var textBox = (System.Windows.Controls.TextBox)dependencyObject;
        if (!textBox.IsKeyboardFocusWithin)
        {
            textBox.Focus();
            e.Handled = true;
        }
    }

    private static DependencyObject GetParentFromVisualTree(object source)
    {
        DependencyObject parent = source as UIElement;
        while (parent != null && !(parent is System.Windows.Controls.TextBox))
        {
            parent = VisualTreeHelper.GetParent(parent);
        }

        return parent;
    }

    private static void OnKeyboardFocusSelectText(object sender, KeyboardFocusChangedEventArgs e)
    {
        var textBox = e.OriginalSource as System.Windows.Controls.TextBox;
        if (textBox == null) return;

        var selectAllMode = GetSelectAllMode(textBox);

        if (selectAllMode == SelectAllMode.Never)
        {
            textBox.SelectionStart = 0;
            textBox.SelectionLength = 0;
        }
        else
            textBox.SelectAll();

        if (selectAllMode == SelectAllMode.OnFirstFocusThenNever)
            SetSelectAllMode(textBox, SelectAllMode.Never);
        else if (selectAllMode == SelectAllMode.OnFirstFocusThenLeaveOff)
            SetSelectAllMode(textBox, null);
    }

    [AttachedPropertyBrowsableForChildrenAttribute(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(System.Windows.Controls.TextBox))]
    public static SelectAllMode? GetSelectAllMode(DependencyObject @object)
    {
        return (SelectAllMode)@object.GetValue(SelectAllModeProperty);
    }

    public static void SetSelectAllMode(DependencyObject @object, SelectAllMode? value)
    {
        @object.SetValue(SelectAllModeProperty, value);
    }
}

XAML에서는 다음 중 하나와 같이 사용할 수 있습니다.

<!-- On first focus, it selects all then leave off textbox and doesn't check again -->
<TextBox attprop:TextBox.SelectAllMode="OnFirstFocusThenLeaveOff" />

<!-- On first focus, it selects all then never selects -->
<TextBox attprop:TextBox.SelectAllMode="OnFirstFocusThenNever" />

<!-- Selects all on every focus -->
<TextBox attprop:TextBox.SelectAllMode="OnEveryFocus" />

<!-- Never selects text (WPF's default attitude) -->
<TextBox attprop:TextBox.SelectAllMode="Never" />

@Nasenbaer가 게시 한 답변 의 C # 버전은 다음과 같습니다.

private delegate void TextBoxSelectAllDelegate(object sender);

private void TextBoxSelectAll(object sender)
{
    (sender as System.Windows.Controls.TextBox).SelectAll();
}

private void MyTextBox_GotFocus(object sender, System.Windows.RoutedEventArgs e)
{
    TextBoxSelectAllDelegate d = TextBoxSelectAll;

    this.Dispatcher.BeginInvoke(d,
        System.Windows.Threading.DispatcherPriority.ApplicationIdle, sender);
}

반면 MyTextBox_GotFocus받는 할당 이벤트 핸들러 GotFocus의 이벤트 MyTextBox.


나는 같은 문제가 있었다. VB.Net에서는 다음과 같이 쉽게 작동합니다.

VB XAML :

<TextBox x:Name="txtFilterFrequency" />

코드 힌드 :

Private Sub txtFilterText_GotFocus(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles txtFilterText.GotFocus
    Me.Dispatcher.BeginInvoke(Sub()
                                  txtFilterText.SelectAll()
                              End Sub, DispatcherPriority.ApplicationIdle, Nothing)
End Sub

C # (ViRuSTriNiTy 덕분에)

private delegate void TextBoxSelectAllDelegate(object sender);

private void TextBoxSelectAll(object sender)
{
    (sender as System.Windows.Controls.TextBox).SelectAll();
}

private void MyTextBox_GotFocus(object sender, System.Windows.RoutedEventArgs e)
{
    TextBoxSelectAllDelegate d = TextBoxSelectAll;

    this.Dispatcher.BeginInvoke(d,
        System.Windows.Threading.DispatcherPriority.ApplicationIdle, sender);
}

이것이 가장 간단한 솔루션입니다.

응용 프로그램 (App.xaml.cs)에 전역 처리기를 추가하고 완료합니다. 몇 줄의 코드 만 있으면됩니다.

protected override void OnStartup(StartupEventArgs e)
{
    EventManager.RegisterClassHandler(typeof(TextBox),
        TextBox.GotFocusEvent,
        new RoutedEventHandler(TextBox_GotFocus));

    base.OnStartup(e);
}

따라서 EventManager 클래스를 사용하여 유형 (TextBox)에 대한 전역 이벤트 핸들러를 등록하십시오. 실제 처리기는 간단합니다.

private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    (sender as TextBox).SelectAll();
}

여기를 확인하십시오 : WPF TextBox SelectAll on Focus

도움이 되길 바랍니다.


이것은 나를 위해 잘 작동하는 것 같습니다. 기본적으로 이전 게시물을 요약 한 것입니다. 방금 생성자의 MainWindow.xaml.cs 파일에 넣었습니다. 두 개의 핸들러 (키보드 및 마우스)를 작성하고 두 이벤트를 동일한 함수로 퍼널 링 HandleGotFocusEvent합니다. 이는 동일한 파일에서 생성자 바로 다음에 정의됩니다.

public MainWindow()
{
   InitializeComponent();

   EventManager.RegisterClassHandler(typeof(TextBox), 
      UIElement.GotKeyboardFocusEvent,
      new RoutedEventHandler(HandleGotFocusEvent), true);
   EventManager.RegisterClassHandler(typeof(TextBox),
      UIElement.GotMouseCaptureEvent,
      new RoutedEventHandler(HandleGotFocusEvent), true);   
}
private void HandleGotFocusEvent(object sender, RoutedEventArgs e)
{
   if (sender is TextBox)
      (sender as TextBox).SelectAll();
}

mouseDown을 재정의하고 두 번 클릭 한 후 모두를 선택하는 쉬운 방법은 다음과 같습니다.

public class DoubleClickTextBox: TextBox
{

    public override void EndInit()
    {
        base.EndInit();            
    }

    protected override void OnMouseEnter(System.Windows.Input.MouseEventArgs e)
    {
        base.OnMouseEnter(e);
        this.Cursor = Cursors.Arrow;
    }
    protected override void OnMouseDown(System.Windows.Input.MouseButtonEventArgs e)
    {

    }

    protected override void OnMouseDoubleClick(System.Windows.Input.MouseButtonEventArgs e)
    {
        base.OnMouseDown(e);
        this.SelectAll();
    }
}

텍스트 상자를 포함하는 컨트롤의 생성자에 이것을 넣으십시오.

Loaded += (sender, e) =>
{
    MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
    myTextBox.SelectAll();
}

세르게이.

인터넷 검색 및 테스트 후 나에게 도움이되는 간단한 솔루션을 찾았습니다.

컨테이너 창의 "Loaded"이벤트에 이벤트 핸들러를 추가해야합니다.

    private void yourwindow_Loaded(object sender, RoutedEventArgs e)
    {
        EventManager.RegisterClassHandler(typeof(TextBox),
            TextBox.PreviewMouseLeftButtonDownEvent,
            new RoutedEventHandler(SelectivelyIgnoreMouseButton));
    }

다음으로, 이전 코드에서 참조 된 RoutedEventHandler에 대한 핸들러를 작성해야합니다.

    private void SelectivelyIgnoreMouseButton(object sender, RoutedEventArgs e)
    {
        TextBox tb = (sender as TextBox);
        if (tb != null)
        {
            if (!tb.IsKeyboardFocusWithin)
            {
                e.Handled = true;
                tb.Focus();
            }
        }
    }

이제 GotFocus 이벤트 핸들러의 SelectAll () 명령을 모든 TextBox 컨트롤에 별도로 추가 할 수 있습니다.

    private void myTextBox_GotFocus(object sender, RoutedEventArgs e)
    {
        (sender as TextBox).SelectAll();
    }

당신의 텍스트는 지금 초점에 선택되었습니다!

WPF 솔루션 Dr. MSDN 포럼 에서 채택


나는 그것들을 모두 테스트했지만 다음 만이 해결되었습니다.

        protected override void OnStartup(StartupEventArgs e) 
        {
            EventManager.RegisterClassHandler(typeof(TextBox), UIElement.PreviewMouseLeftButtonDownEvent,
           new MouseButtonEventHandler(SelectivelyHandleMouseButton), true);
            EventManager.RegisterClassHandler(typeof(TextBox), UIElement.GotKeyboardFocusEvent,
              new RoutedEventHandler(SelectAllText), true);
            EventManager.RegisterClassHandler(typeof(TextBox), UIElement.GotFocusEvent,
              new RoutedEventHandler(GotFocus), true);          
        }

        private static void SelectivelyHandleMouseButton(object sender, MouseButtonEventArgs e)
        {
            var textbox = (sender as TextBox);
            if (textbox != null)
            {
                int hc = textbox.GetHashCode();
                if (hc == LastHashCode)
                {
                    if (e.OriginalSource.GetType().Name == "TextBoxView")
                    {
                        e.Handled = true;
                        textbox.Focus();
                        LastHashCode = -1;
                    }
                }
            }
            if (textbox != null) textbox.Focus();
        }

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

        private static int LastHashCode;
        private static void GotFocus(object sender, RoutedEventArgs e)
        {
            var textBox = e.OriginalSource as TextBox;
            if (textBox != null)
                LastHashCode = textBox.GetHashCode();
        }

와! 위의 모든 내용을 읽은 후 나는 압도적이고 혼란스러워합니다. 나는이 게시물에서 배운 것으로 생각한 것을 취하고 완전히 다른 것을 시도했습니다. 포커스가있을 때 텍스트 상자에서 텍스트를 선택하려면 다음을 사용하십시오.

private void TextField_GotFocus(object sender, RoutedEventArgs e)
{
    TextBox tb = (sender as Textbox);
    if(tb != null)
    {
        e.Handled = true;
        tb.Focus();
        tb.SelectAll();
    }
}

텍스트 상자의 GotFocus 속성을이 방법으로 설정하십시오.

응용 프로그램을 실행하고 텍스트 상자에서 한 번 클릭하면 텍스트 상자에 이미있는 모든 것이 강조 표시됩니다.

실제로, 목표는 사용자가 텍스트 상자를 클릭 할 때 텍스트를 선택하는 것입니다. 이것은 간단하고 코드가 훨씬 적습니다. 그냥 ...

참고URL : https://stackoverflow.com/questions/660554/how-to-automatically-select-all-text-on-focus-in-wpf-textbox

반응형