programing

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

subpage 2023. 4. 29. 09:18
반응형

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

내가 전화하면SelectAll에서.GotFocus이벤트 핸들러, 마우스와 함께 작동하지 않습니다. 마우스를 놓자마자 선택 항목이 사라집니다.

편집: 사람들은 도넬의 대답을 좋아합니다, 저는 왜 그것이 받아들여진 대답만큼 마음에 들지 않았는지 설명하려고 노력하겠습니다.

  • 이것은 더 복잡하지만, 받아들여진 대답은 더 간단한 방법으로 같은 일을 합니다.
  • 허용된 답변의 유용성이 더 좋습니다.텍스트 중간을 클릭하면 마우스를 놓으면 텍스트가 선택 해제되어 편집을 즉시 시작할 수 있으며, 계속해서 모두 선택하려면 버튼을 다시 누르면 이번에는 선택 해제되지 않습니다.도넬의 레시피에 따라 텍스트 중간에 클릭하면 두 번째 클릭을 해야 편집이 가능합니다.텍스트 내에서 텍스트 외부를 클릭하면 모든 내용을 덮어쓰는 대신 편집을 시작할 수 있습니다.

처음 클릭하면 모두 선택되고, 다시 클릭하면 커서로 이동합니다(우리의 애플리케이션은 펜이 있는 태블릿에서 사용하도록 설계되었습니다).

유용할 수도 있습니다.

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

도넬의 답변이 가장 효과적이지만, 그것을 사용하기 위해 새로운 수업을 도출해야 하는 것은 고통입니다.

그렇게 하는 대신 App.xaml.cs 에서 응용 프로그램의 모든 TextBox에 대한 핸들러를 등록합니다.이를 통해 표준 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의 답변(더블 클릭 생략)의 일부를 선택했습니다.하지만 그로키스처럼 저는 파생된 클래스를 만들 필요가 없습니다.하지만 저는 또한 그로키스의 것을 좋아하지 않습니다.OnStartup. 는 이것이 항상은합니다.그리고 저는 이것이 "일반적으로 하지만 항상은 아니다"라는 기준으로 필요합니다.

된 습첨같구니로 했습니다.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);
    }
}

항상 는 않은" 이 을 "일반이지항그상않렇은는지기"로 합니다.True (글로벌) TextBox Style이러한 "텍스트 선택"은 항상 "사용"이지만 텍스트 상자 단위로 사용하지 않도록 설정할 수 있습니다.

왜 그것이 선택권을 잃는지 모르겠어요.GotFocus이벤트

하지만 한 가지 해결책은 선택을 하는 것입니다.GotKeyboardFocus 리고그고.GotMouseCapture 효과가있을 입니다.그렇게 하면 항상 효과가 있을 것입니다.

편집 --

여기에 언급된 몇 가지 단점을 해결하는 방법을 보여주는 예를 추가합니다.

private void TextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    // Fixes issue when clicking cut/copy/paste in context menu
    if (textBox.SelectionLength == 0) 
        textBox.SelectAll();
}

private void TextBox_LostMouseCapture(object sender, MouseEventArgs e)
{
    // If user highlights some text, don't override it
    if (textBox.SelectionLength == 0) 
        textBox.SelectAll();

    // further clicks will not select all
    textBox.LostMouseCapture -= TextBox_LostMouseCapture; 
}

private void TextBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    // once we've left the TextBox, return the select all behavior
    textBox.LostMouseCapture += TextBox_LostMouseCapture;
}

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

단일 텍스트 상자에 연결할 수 있는 하나:

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

저는 세르게이의 답변처럼 표현행동보다는 애착행동을 사용하여 이 문제를 해결했습니다.이는 제가 의존할 필요가 없다는 것을 의미합니다.System.Windows.InteractivitySDK:"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저는 아래 코드를 어디선가 발견했고 (신용장은 여기에 부여됩니다) 잘 작동합니다.에도 OP의 질문과 합니다.Dispatcher와 함께 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);
}

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당신의 신청서에.

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

제가 여기서 제시하는 답변은 이 점에서 더 잘 작동합니다.동작이므로 시스템이 필요합니다.윈도우.Blend SDK의 대화형 어셈블리).첨부된 속성을 사용하여 다시 작성할 수도 있습니다.

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

나는 닐스의 답변을 사용했지만 좀 더 유연하게 전환했습니다.

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

여기서 찍은 사진:

글로벌 이벤트 핸들러를 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();
}

저는 이것에 대한 약간 단순한 대답을 가지고 있습니다.PreviewMouseLeftButtonDownevent의 일반적인 한 것처럼 .

에는 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. 잘라내기/복사/과거에 대한 마우스 오른쪽 단추의 상황에 맞는 메뉴를 사용하면 텍스트를 모두 선택하지 않은 경우에도 모든 텍스트가 선택됩니다.
  2. 마우스 오른쪽 버튼을 클릭하여 상황에 맞는 메뉴에서 돌아오면 항상 모든 텍스트가 선택됩니다.
  3. +Tab를 사용하여 응용 프로그램으로 돌아가면 모든 텍스트가 항상 선택됩니다.
  4. 처음 클릭할 때 텍스트의 일부만 선택하려고 하면 항상 모두 선택됩니다(예: Google Chromes 주소 표시줄과 달리).

제가 작성한 코드는 구성 가능합니다.은 세 가지 필드를 할 수 .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를 추가하기만 하면 됩니다xmlns의 )를한 후 과 같이

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

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

  1. 마우스 다운 이벤트의 기본 동작을 재정의하고 첫 번째 클릭 시 텍스트의 일부만 선택할 수 있도록 하려면 마우스 업 이벤트에서 모든 텍스트가 선택됩니다.
  2. 나는 그 사실을 처리해야 했습니다.TextBox초점을 잃은 후 선택 내용을 기억합니다.저는 사실 이 행동을 무시했습니다.
  3. 나는 마우스 버튼을 누르는 것이 컴퓨터에 대한 첫 번째 동작인지 기억해야 했습니다.TextBox(FirstActionIsMouseDown정적 필드)를 선택합니다.
  4. 클릭으로 .ContextMenu정적 필드)를 선택합니다.

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

저는 이것이 매우 오래되었다는 것을 알지만, 여기 표현식/마이크로소프트 상호 작용 및 상호 작용 이름 공간을 기반으로 하는 제 솔루션이 있습니다.

먼저 이 링크의 지침에 따라 상호 작용 트리거를 스타일에 배치했습니다.

결국 이렇게 됩니다.

<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▁in▁you▁▁the▁▁you를 클릭하면 모든 가 선택되도록 할 수 있습니다.TextBox.

번째 첫째번째.CallMethodAction텍스트 상자를 호출합니다.SelectAll방법은 다음과 같습니다.GotKeyboardFocusTextBox 화재.

이것이 도움이 되길 바랍니다.

@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는 에할이처리니다에 입니다.GotFocusMyTextBox.

구글 검색과 테스트를 통해 저에게 맞는 간단한 솔루션을 찾았습니다.

를 이트핸추합니에 .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();
}

이제 텍스트가 포커스에 선택되었습니다!

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

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

코드 몇 줄만 있으면 됩니다.

응용 프로그램(App.xaml.cs )에 글로벌 처리기를 추가합니다.EventManager 클래스를 사용하여 유형(이 경우 TextBox)에 대해 글로벌 이벤트 핸들러를 등록합니다.

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

여기서 확인: WPF 텍스트 상자 포커스에서 모두 선택

도움이 되길 바랍니다.

이 확장 방법을 사용하여 원하는 동작을 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();
}

저도 같은 문제가 있었어요.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# (ViRu 덕분에)STriNiTy)

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

방식에 Donnelle/Groky▁the▁within▁for▁don▁stillgrobut▁(nel▁to위▁of▁click해▁a사▁right을gro).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

이것은 저에게 잘 맞는 것 같습니다.기본적으로 이전 게시물을 요약한 것입니다.저는 방금 이것을 컨스트럭터에 있는 제 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();
}

마우스를 두 번 클릭한 후 아래로 이동하고 모두 선택하는 쉬운 방법은 다음과 같습니다.

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

작업 중에 텍스트를 선택 취소하는 이벤트가 있는 경우OnFocus마우스를 올려주세요, 저는 보통 모두 선택을 지연시킵니다.

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

모든 테스트를 수행했지만 다음 사항만 해결되었습니다.

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

가장 간단하고 완벽한 솔루션은 텍스트 상자가 포커스를 맞춘 후 타이머를 사용하여 모든 텍스트를 20ms 선택하는 것입니다.

Dim WithEvents Timer As New DispatcherTimer()

합니다.Timer.Interval = TimeSpan.FromMilliseconds(20)

이벤트에 응답(여기서 TextBox 컨트롤을 상속하므로 이벤트를 재정의합니다.

Protected Overrides Sub OnGotFocus(e As RoutedEventArgs)
        Timer.Start()
        MyBase.OnGotFocus(e)
    End Sub


    Private Sub Timer_Tick(sender As Object, e As EventArgs) Handles Timer.Tick
        Timer.Stop()
        Me.SelectAll()
    End Sub

그리고 그게 전부야!

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

반응형