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


232

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

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

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

둘 이상의 양식을 사용하려는 경우, 그녀의 대답은 첫 번째 것보다 덜 복잡해집니다. 두 옵션 중 어느 것이나 작동하는 방식을 변경할 수 있으므로 두 옵션의 유용성은 약합니다.
thepaulpage

1
@Sergey : 이후 더 나은 답변이 있었으므로이 질문에 대한 허용 된 답변을 변경하고 싶을 수 있습니다. 난 내 제안하지 않겠지 만 당신은;)
Grokys

질문에 Silverlight 태그가 있지만 Silverlight에는 대부분의 이벤트 / 모든 종류의 미리보기 이벤트가 없습니다. 그렇다면 실버 라이트에 어떤 솔루션을 사용해야합니까?
Valentin Kuzub

링크 "왜 WPF에 초점이 까다로운가?" 깨짐
Maxence

1
아래 stackoverflow.com/a/2553297/492 에 대한 의견에서 언급했듯이 madprops.org/blog/wpf-textbox-selectall-on-focus 는 쉬운 솔루션이며 원래의 nouse 동작을 유지합니다. 앱에 WPF 컨트롤이 하나만 있기 때문에 생성자에 이벤트 등록을 넣었습니다.
CAD bloke 2

답변:


75

GotFocus이벤트 에서 선택을 잃을 지 모릅니다 .

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


10
아니. 기존 텍스트 중간에 마우스를 클릭하면 마우스 버튼을 놓으면 선택이 손실됩니다.
Sergey Aldoukhov

3
두 번째 클릭 후 모든 텍스트를 다시 선택하지만 WPF 디자이너가 의도 한 동작인지 확실하지 않지만 사용성이 그렇게 나쁘지는 않습니다. 단일 GotFocus 핸들러와 다른 점은 TextBox의 빈 공간을 클릭하면 모두 선택된다는 것입니다.
Sergey Aldoukhov

3
이것도 주먹 솔루션이었습니다. 그러나 사용자가 마우스를 사용하여 텍스트를 선택할 수없는 경우, 사용자가 전체 텍스트를 클릭 할 때마다 선택되기 때문에 사용자가 정말로 짜증이납니다.
Nils

1
이 솔루션의 또 다른 단점은 TextBox의 "잘라 내기 / 복사 / 붙여 넣기"메뉴를 사용할 때 메뉴 항목을 선택할 때 전체 텍스트가 선택된다는 것입니다.

@gcores 이것이 오래되었다는 것을 알고 있지만 GotFocus 이벤트에서 선택한 텍스트가 손실되는 이유를 아는 사람이 있습니까? 당신은 다른 행사에서 일하는 것에 대해 맞습니다.하지만 그것은 저의 책에서 완벽하게 수용 가능한 해결책입니다.
Feign

210

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

유용 할 수 있습니다.

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();
    }
}

9
대단히 감사합니다. 이것은 훌륭하게 작동하며 IMHO의 대답으로 받아 들여 져야합니다. 위의 코드는 TextBox가 키보드 또는 마우스 (및 스타일러스)를 통해 포커스를받을 때 작동합니다. +1
Drew Noakes

5
나는 social.msdn.microsoft.com/Forums/en-US/wpf/thread/… 에서 거의 동일한 대답을 보았습니다 .e.OriginalSource를 사용하지 않거나 시각적 트리를 크롤링하는 방식도 잘 작동합니다. 이 모든 작업을 수행 할 때 어떤 이점이 있습니까?
Marco Luglio

1
잘 작동하지만 마우스로 텍스트를 드래그하여 선택할 수 있으면 완벽합니다. Chrome 주소 표시 줄은 이상적인 시스템의 완벽한 예입니다. 사용자가 드래그하지 않고 클릭하고 놓으면 전체 텍스트가 강조 표시됩니다. 그러나 사용자가 클릭하여 끌면 끌기는 모두 선택하지 않고 텍스트를 정상적으로 선택합니다. SelectAll은 마우스 릴리스 에서만 발생합니다 . 나는이 디자인을 전혀 개선 할 수 있을지 고민하고 살펴볼 것이다.
devios1

2
이 솔루션의 또 다른 단점은 TextBox의 "잘라 내기 / 복사 / 붙여 넣기"메뉴를 사용할 때 메뉴 항목을 선택할 때 전체 텍스트가 선택된다는 것입니다.

1
나는 그것을 향상시키는 SelectAllText방법에 대한 추가 테스트를 발견 textBox.IsFocused했습니다. GetKeyboardFocus프로그램을 alt-tabbing하여 모든 것을 선택하고 싶지는 않습니다 .
Scott Stafford 1

164

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();
    }
}

4
이것은 매우 멋진 솔루션이며, 매트 해밀턴 (Matt Hamilton)이 여기에 설명했습니다 : madprops.org/blog/wpf-textbox-selectall-on-focus
Ashley Davis

'수신', '집중'에서 철자가
틀렸다

2
고마워 네이트, 내 방어에서 철자 실수가 Donnelle의 답변에서 그대로 복사되었다는 것을 지적하고 싶습니다.)
Grokys

질문에 Silverlight 태그가 있지만 Silverlight에는 대부분의 이벤트 / 모든 종류의 미리보기 이벤트가 없습니다. 그렇다면 실버 라이트에 어떤 솔루션을 사용해야합니까? 미리 감사
발렌틴 Kuzub

4
"미국에서는 맞춤법이 훨씬 일반적이지만 영국과 캐나다에서는 맞춤법이 자주 사용되며 특히 호주와 뉴질랜드에서 자주 사용됩니다." So nyah;)
Donnelle

85

이것은 다소 오래되었지만 어쨌든 내 대답을 표시합니다.

나는 이것이 더 자연스러운 것이라고 생각하기 위해 Donnelle의 답변 중 일부를 선택했습니다 (더블 클릭을 건너 뛰었습니다). 그러나 gcore와 마찬가지로 파생 클래스를 만들어야 할 필요가 없습니다. 그러나 나는 또한 gcores OnStartup방법을 좋아하지 않습니다 . 그리고 저는 이것을 "일반적으로 항상 그런 것은 아닙니다"라고 생각합니다.

xaml에서 DependencyProperty설정할 수 있도록 이것을 첨부 파일로 구현했습니다 local:SelectTextOnFocus.Active = "True". 나는이 방법이 가장 기쁘게 생각합니다.

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);
    }
}

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


8
+1 이것은 전 세계적으로 설정하는 것보다 훨씬 낫고 TextBox에서 파생하는 것보다 'WPF 방식'입니다.
stijn

3
+1 stijn에 동의합니다. app.cs에서 코드를 "숨기는"것은 SelectAllOnFocus가 왜 발생하는지 파악해야하는 가난한 개발자에게는 좋지 않습니다. :-) 방금 TextBoxBehaviors 클래스에 이것을 떨어 뜨린 다음 기본 TextBox 스타일을 업데이트했습니다. 치료를했다. 건배
이 캠벨

2
@tronda : TargetType of TextBox를 사용하여 리소스에 스타일을 추가하기 만하면됩니다. 난 당신이 한 번 봐 가지고 제안 wpftutorial.net/Styles.html을
닐스

2
최고의 답변을위한 또 다른 +1. 내가 찾은 문제는 컨텍스트 메뉴를 통해 텍스트를 자주 편집하는 마우스 오른쪽 버튼을 사용하더라도 텍스트가 항상 선택된다는 것입니다.이 경우 솔루션은 작동하지 않습니다. 상황에 맞는 메뉴를 통해 한 단어를 자르고 싶었습니다. 이 문제를 해결하는 방법을 알고 있습니까?
user3313608

2
나는이 대답을 좋아하지만 왜 DependencyObject를 확장해야합니까? 나는 그것을 제거하고 여전히 잘 작동합니다.
Fred

47

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

하나의 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();
    }
}

이것은 지금까지 가장 깨끗하고 깨끗한 솔루션입니다. 공유해 주셔서 감사합니다.
Golvellius

정말 멋져 보이지만 어떤 이유로 탭 제어를 깨뜨립니다 ... 왜 그런지 아십니까?
Marc

yor 솔루션을 사용하고 싶습니다. 그러나 정말로 잃어버린 ... 아마도 당신은 샘플이 있습니까?
후안 파블로 고메즈

포커스가있는 동안 텍스트 상자에서 어딘가를 클릭하면 (캐럿을 다른 장소로 이동한다고 가정) 캐럿을 이동하는 대신 모두 선택을 다시 수행합니다. 예상치 못한 일입니다. GotMouseCapture를 일반적인 MouseDoubleClick으로 대체하여 수정했습니다. MSDN의 후자 덕분입니다.
norekhov

1
텍스트 상자가 FocusManager.FocusedElement를 통해 초기 포커스를 받으면 작동하지 않는 것 같습니다. 어떤 아이디어가 있습니까?
szx

24

이것은 오래된 질문이지만 방금이 문제가 있었지만 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"/>

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


이 방법이 마음에 들지만 Get / Set 메서드는 "Property"로 끝나서는 안됩니다. Xaml 부분을 추가 한 후 코드를 컴파일하려면 제거해야했습니다.
Patrick Quirk

아주 좋은, 예상대로 작동했습니다. MVVM을 수행 할 때 View 문제를 분리 된 상태로 유지하는 데 도움이되므로이 기능이 마음에 듭니다.
Killnine

16

다음은 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();
        }
    }
}

1
본질적으로 이것은이 스레드에서 가장 등급이 높은 솔루션과 동일한 솔루션입니다. 그러나 2 년 전부터 @Donnelle에서 빌린 곳을 알았습니다.)
Sergey Aldoukhov

이 솔루션은 가장 쉬운 것처럼 보였고 나를 위해 일했습니다. 텍스트 상자에 들어갈 때 기본적으로 선택된 특정 텍스트 하위 집합을 원했습니다.
Jack B Nimble

10

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

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. 나는 아래 어딘가에 코드를 발견했으며 (신용이 주어짐) 잘 작동합니다. OP Dispatcher작업과 동일한 패턴을 사용 하기 때문에 OP의 질문과 직접 ​​관련이 없지만 게시합니다 UIElement.

// 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);
}

이것이 가장 간단한 구현 방법이라고 생각합니다. 확장 메서드를 만든 후에는 myTextBox.SelectAllText ()를 호출하면됩니다. 이 답변이 더 많은 점수를받지 못한 이유는 무엇입니까? 다른 솔루션이 왜 그렇게 나을까요?
Tono Nam

2
이 방법은 텍스트 상자의 MouseUp 처리기 이후에 비동기 호출을 사용하기 때문에 피할 수 있습니다. 나는 이것이 100 % 결정적이라고 믿지 않으며 일관성이없는 행동으로 이어질 수 있습니다. 일어날 가능성은 없지만 위의 확실한 방법을 사용합니다.
Rob H

6

다른 솔루션의 일부 문제를 해결하려는 시도는 다음과 같습니다.

  1. 잘라 내기 / 복사 / 붙여 넣기에 마우스 오른쪽 버튼을 클릭하여 상황에 맞는 메뉴를 사용하면 모든 텍스트를 선택하지 않아도 모든 텍스트가 선택됩니다.
  2. 마우스 오른쪽 버튼 클릭 상황에 맞는 메뉴에서 돌아올 때 항상 모든 텍스트가 선택됩니다.
  3. Alt+ 를 사용하여 응용 프로그램으로 돌아 가면 Tab모든 텍스트가 항상 선택됩니다.
  4. 처음 클릭 할 때 텍스트의 일부만 선택하려고하면 모든 항목이 항상 선택됩니다 (예 : Google 크롬 주소 표시 줄과 달리).

내가 작성한 코드는 구성 가능합니다. 당신은 행동이 세 가지 읽기 전용 필드를 설정하여 발생해야하는 모든 행동을 선택 무엇을 선택할 수 있습니다 SelectOnKeybourdFocus, SelectOnMouseLeftClick, SelectOnMouseRightClick.

이 솔루션의 단점은 더 복잡하고 정적 상태가 저장된다는 것입니다. 그것은의 디폴트 동작과 추한 싸움처럼 보인다 TextBox제어 할 수 있습니다. 여전히 작동하며 모든 코드가 연결된 속성 컨테이너 클래스에 숨겨져 있습니다.

public static class TextBoxExtensions
{
    // Configuration fields to choose on what actions the select all behavior should occur.
    static readonly bool SelectOnKeybourdFocus = true;
    static readonly bool SelectOnMouseLeftClick = true;
    static readonly bool SelectOnMouseRightClick = true;

    // Remembers a right click context menu that is opened 
    static ContextMenu ContextMenu = null;

    // Remembers if the first action on the TextBox is mouse down 
    static bool FirstActionIsMouseDown = false;

    public static readonly DependencyProperty SelectOnFocusProperty =
        DependencyProperty.RegisterAttached("SelectOnFocus", typeof(bool), typeof(TextBoxExtensions), new PropertyMetadata(false, new PropertyChangedCallback(OnSelectOnFocusChanged)));

    [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(TextBox))]
    public static bool GetSelectOnFocus(DependencyObject obj)
    {
        return (bool)obj.GetValue(SelectOnFocusProperty);
    }

    public static void SetSelectOnFocus(DependencyObject obj, bool value)
    {
        obj.SetValue(SelectOnFocusProperty, value);
    }

    private static void OnSelectOnFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (!(d is TextBox textBox)) return;

        if (GetSelectOnFocus(textBox))
        {
            // Register events
            textBox.PreviewMouseDown += TextBox_PreviewMouseDown;
            textBox.PreviewMouseUp += TextBox_PreviewMouseUp;
            textBox.GotKeyboardFocus += TextBox_GotKeyboardFocus;
            textBox.LostKeyboardFocus += TextBox_LostKeyboardFocus;
        }
        else
        {
            // Unregister events
            textBox.PreviewMouseDown -= TextBox_PreviewMouseDown;
            textBox.PreviewMouseUp -= TextBox_PreviewMouseUp;
            textBox.GotKeyboardFocus -= TextBox_GotKeyboardFocus;
            textBox.LostKeyboardFocus -= TextBox_LostKeyboardFocus;
        }
    }

    private static void TextBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        if (!(sender is TextBox textBox)) return;

        // If mouse clicked and focus was not in text box, remember this is the first click.
        // This will enable to prevent select all when the text box gets the keyboard focus 
        // right after the mouse down event.
        if (!textBox.IsKeyboardFocusWithin)
        {
            FirstActionIsMouseDown = true;
        }
    }

    private static void TextBox_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        if (!(sender is TextBox textBox)) return;

        // Select all only if:
        // 1) SelectOnMouseLeftClick/SelectOnMouseRightClick is true and left/right button was clicked
        // 3) This is the first click
        // 4) No text is selected
        if (((SelectOnMouseLeftClick && e.ChangedButton == MouseButton.Left) || 
            (SelectOnMouseRightClick && e.ChangedButton == MouseButton.Right)) &&
            FirstActionIsMouseDown &&
            string.IsNullOrEmpty(textBox.SelectedText))
        {
            textBox.SelectAll();
        }

        // It is not the first click 
        FirstActionIsMouseDown = false;
    }

    private static void TextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        if (!(sender is TextBox textBox)) return;

        // Select all only if:
        // 1) SelectOnKeybourdFocus is true
        // 2) Focus was not previously out of the application (e.OldFocus != null)
        // 3) The mouse was pressed down for the first after on the text box
        // 4) Focus was not previously in the context menu
        if (SelectOnKeybourdFocus &&
            e.OldFocus != null &&
            !FirstActionIsMouseDown &&
            !IsObjectInObjectTree(e.OldFocus as DependencyObject, ContextMenu))
        {
            textBox.SelectAll();
        }

        // Forget ContextMenu
        ContextMenu = null;
    }

    private static void TextBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        if (!(sender is TextBox textBox)) return;

        // Remember ContextMenu (if opened)
        ContextMenu = e.NewFocus as ContextMenu;

        // Forget selection when focus is lost if:
        // 1) Focus is still in the application
        // 2) The context menu was not opened
        if (e.NewFocus != null
            && ContextMenu == null)
        {
            textBox.SelectionLength = 0;
        }
    }

    // Helper function to look if a DependencyObject is contained in the visual tree of another object
    private static bool IsObjectInObjectTree(DependencyObject searchInObject, DependencyObject compireToObject)
    {
        while (searchInObject != null && searchInObject != compireToObject)
        {
            searchInObject = VisualTreeHelper.GetParent(searchInObject);
        }

        return searchInObject != null;
    }
}

첨부 된 속성을에 첨부하려면 첨부 된 속성 TextBox의 xml 네임 스페이스 ( xmlns)를 추가 한 후 다음과 같이 사용하면됩니다.

<TextBox attachedprop:TextBoxExtensions.SelectOnFocus="True"/>

이 솔루션에 대한 참고 사항 :

  1. 마우스 다운 이벤트의 기본 동작을 무시하고 처음 클릭 할 때 텍스트의 일부만 선택할 수 있도록하기 위해 마우스 업 이벤트에서 모든 텍스트가 선택됩니다.
  2. 나는 TextBox기억이 초점을 잃은 후에 선택을 기억 한다는 사실을 다루어야 했습니다. 실제로이 동작을 재정의했습니다.
  3. 마우스 버튼 다운이 TextBox( FirstActionIsMouseDown정적 필드) 의 첫 번째 작업인지 기억해야했습니다 .
  4. 마우스 오른쪽 버튼을 클릭하여 열린 컨텍스트 메뉴 ( ContextMenu정적 필드) 를 기억해야했습니다 .

내가 찾은 유일한 부작용 SelectOnMouseRightClick은 사실입니다. 빈칸을 열고 마우스 오른쪽 버튼을 클릭 TextBox해도 "모두 선택"하지 않는 경우 오른쪽 클릭 상황에 맞는 메뉴가 깜박 입니다.


5

여기에 제시된 답변 중 어느 것도 표준 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;
    }
}

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


1
이것은 좋은 대답이지만, 사용자가 공백을 클릭하면 (비즈니스 응용 프로그램에서) 그의 의도는 아마도 전체 가치를 무시하는 것이기 때문에 모든 것을 선택하는 것이 올바른 접근법이라고 생각합니다.
Sergey Aldoukhov

1
Sergey : 첫 번째 클릭은 전체 값을 선택하고 두 번째 클릭은 커서를 값의 오른쪽에 놓습니다. 제시된 다른 솔루션에서 두 번째 클릭은 전체 값을 선택된 상태로 유지하므로 값을 추가하기가 매우 어렵습니다.
Kristof Verbiest

이것은 어떻게 사용됩니까? 이 코드를 App.xaml.cs에 추가했지만 내 앱의 TextBox에 영향을 미치지 않는 것 같습니다.
PIntag

5

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

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));

4

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응용 프로그램에서 모두 도달 할 수 있습니다 .


3

여기 에서 찍은 :

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();
}

3

나는 이것이 매우 오래되었다는 것을 알고 있지만 여기에 표현식 / 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로 이름을 지정했으며 해당 이름을 요소에 사용하고 있습니다. 이것은 나를 위해 완벽하게 작동합니다. TextBox를 클릭 할 때 모든 텍스트를 선택하려는 위치에 스타일을 적용하기 만하면됩니다 TextBox.

첫 번째 는 이벤트가 발생할 때 CallMethodAction텍스트 상자의 SelectAll메서드를 호출합니다 .GotKeyboardFocusTextBox

이게 도움이 되길 바란다.


이것은 오래된 질문이므로 누군가가이 방법을 선택할 수있는 이유를 언급하면 ​​답변에주의를 기울이는 데 도움이 될 수 있습니다.
divibisan

우선, 이것은 스타일에 넣을 필요는 없지만, 이것을 필요로하는 많은 텍스트 상자 컨트롤이 있다는 것이 분명하다고 생각합니다. 스타일은 갈 길입니다.
wiyosaya

1
어쩌면 일부는이 접근법에 동의하지 않을 것입니다.이 접근법을 사용하는 이유에 대해서는 TextBox 서브 클래스 화, 클래스 핸들러 이벤트 등록, 확장 메소드, 첨부 된 속성 작성 등이 필요하지 않습니다. 스타일로 추가 할 수도 있습니다 모든 xaml 프로젝트의 리소스 사전에 추가합니다. x : Key가 없으면 각 개별 텍스트 상자의 xaml을 변경하지 않고도 리소스 사전 범위 내의 모든 TextBox 인스턴스에 적용됩니다. 경우에 따라 더 깔끔한 접근 방법 일 수 있습니다.
wiyosaya

2

나는 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" />

1
실제 코드 숨김없이 텍스트 상자의 확장 된 동작없이 xaml에 바인딩 할 수 있으므로 템플릿에서 사용하기에 정말 좋은 솔루션입니다.
Eric Johansson

2

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


2

PreviewMouseLeftButtonDown브라우저의 일반적인 기능을 모방 한 것으로 보이는 (이벤트 만으로) 약간 단순화 된 답변이 있습니다 .

XAML에서는 다음과 같이 TextBox말합니다.

<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();
    }
}

1
응용 프로그램을 둘러싼 사람들을 위해 TextBox.SelectAll () 안에 GotKeyboardFocus 이벤트를 추가하려고 할 수 있습니다. 귀하의 솔루션은 PasswordBox에서도 작동합니다 (PasswordBox는 봉인 된 유형이므로 확장 할 수 없으므로).
David Sherret 2016 년

1

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();
            }
        }
    }
}

1

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

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();
}

1

나는 같은 문제가 있었다. 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);
}

나를위한 최고의 솔루션, 나는 여기에 C # 번역을 게시했습니다 : stackoverflow.com/a/48385409/3936440
ViRuSTriNiTy

나 에게이 방법은 때로는 텍스트를 선택하지 못합니다. BeginInvoke로 인한 경쟁 조건이라고 생각합니다.
Vimes

명시 해주세요. 디스패처 우선 순위는 기본 애플리케이션에서 예상대로 작동합니다. 당신의 상황은 어떻습니까? 설명 된대로 정확하게 시도 했습니까? 솔루션에 특별한 것이 있습니까?
Nasenbaer

1

이것이 가장 간단한 해결책입니다.

응용 프로그램 (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

도움이 되길 바랍니다.


1

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방법에서 찍은 게시 할 수 있습니다.


1
잘 작동하지만 더블 클릭 이벤트가 발생하지 않습니다
Rodrigo Caballero

실제로 doubleclick 이벤트에 들어 가지 만 OriginalSource 속성은 TextBoxView 유형입니다. 따라서 SelectAllText 메소드는 다음과 같아야합니다. private static void SelectAllText (object sender, RoutedEventArgs e) {var textBox = e.OriginalSource as TextBox; if (textBox! = null) {textBox.SelectAll (); System.Diagnostics.Debug.WriteLine ( "선택한 모든"); } else if (발신자가 TextBox 인 경우) {(TextBox로 보낸 사람) .SelectAll (); }
Rodrigo Caballero

1

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

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();
        }
    }
}

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

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

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

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


방금 사용한 : private async void TBTime_GotFocus (object sender, RoutedEventArgs e) {TextBox tb = (TextBox) e.OriginalSource; await Dispatcher.RunAsync (Windows.UI.Core.CoreDispatcherPriority.Normal, async () => {tb.SelectAll ();}); }
David Jones

1
#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

창에 20 개의 텍스트 상자가있는 경우 모든 텍스트 상자에 대해 3 개의 메소드를 작성 하시겠습니까? 이 방법은 좋지 않습니다. 여기를보십시오 : rachel53461.wordpress.com/2011/11/05/…
Alexandru Dicu

0

이것은 나를 위해 잘 작동하는 것 같습니다. 기본적으로 이전 게시물을 요약 한 것입니다. 방금 생성자의 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();
}

멋지고 쉬우지만 타이밍 문제가있는 것 같습니다-다른 모든 시도 (마우스 클릭), 즉시 다시 선택 취소됩니다 ...?
T4NK3R

0

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();
    }
}

0

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

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

이 방법은 창 생성자에 넣을 때 작동하지 않습니다.
ViRuSTriNiTy

0

OnFocus마우스를 올리는 동안 텍스트를 선택 해제하는 이벤트가 있으면 일반적으로 모두 선택을 지연시킵니다.

private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    if (TextBox.Text != null)
    {
        _ = Task.Run(() =>
        {
            Dispatcher.Invoke(
                async () => {
                    await Task.Delay(100);
                    TextBox.SelectAll();
                }
            );
        });
    }
}

-1

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

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();
}

4
그것은 또한 해시 코드의 외설스러운 오용입니다. 이 링크를
RichK

3
그리고 사용하는 GetType().Name대신에 is또는 것은 as꽤 해키
RichK

-1

많은 답변이 있지만 승인 된 답변으로 사용해야하는 방법은 다음과 같습니다. EditTextBoxGotCapture

다음 코드 뒤에

private void EditTextBoxGotCapture(object sender, MouseEventArgs e)
{
    if (sender is TextBox tb)
    {
        tb.Select(0, tb.Text.Length);
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.