WPF TextBox'ta odaktaki tüm metinler otomatik olarak nasıl seçilir?


232

Ben ararsam SelectAllbir gelen GotFocusolay işleyicisi, bu fare ile değil çalışır - seçimi en kısa sürede fare bırakıldığında olarak kaybolur.

EDIT: İnsanlar Donnelle'nin cevabından hoşlanıyor, kabul edilen cevaptan neden hoşlanmadığımı açıklamaya çalışacağım.

  • Daha karmaşıktır, ancak kabul edilen cevap aynı şeyi daha basit bir şekilde yapar.
  • Kabul edilen cevabın kullanılabilirliği daha iyidir. Metnin ortasına tıkladığınızda, fareyi bıraktığınızda anında düzenlemeye başlamanıza izin veren metin seçimi kaldırılır ve yine de tümünü seçmek istiyorsanız, düğmeye tekrar basın ve bu sefer serbest bırakıldığında seçim kaldırılmaz. Donelle'nin tarifini takiben, metnin ortasına tıklarsam, düzenlemek için ikinci kez tıklamam gerekir. Metin içinde metin dışında bir yere tıklarsam, büyük olasılıkla her şeyin üzerine yazmak yerine düzenlemeye başlamak istediğim anlamına gelir.

Birden fazla forma sahip olacaksanız, cevabı ilkinden daha az karmaşık olmaya devam ediyor. Her ikisinin de çalışabilirliğini değiştirebileceğiniz için her iki seçeneğin kullanılabilirliği tartışmalıdır.
thepaulpage

1
@Sergey: O zamandan beri daha iyi yanıtlar olduğu için bu soru için kabul edilen cevabı değiştirmek isteyebilirsiniz. Benimkini önermeyeceğim, ama sen yapabilirsin;)
Grokys

Soruda Silverlight etiketi var, ancak Silverlight'ta hiçbir etkinlik / önizleme etkinliği yok. Silverlight için hangi çözüm kullanılmalıdır?
Valentin Kuzub

Link "WPF'deki odak neden bu kadar zor?" bozuk
Maxence

1
Aşağıdaki stackoverflow.com/a/2553297/492 ile ilgili bir yorumda belirtildiği gibi, madprops.org/blog/wpf-textbox-selectall-on-focus kolay bir çözümdür ve orijinal nouse davranışını korur. Uygulamada yalnızca bir WPF denetimim olduğu için etkinlik kaydını yapıcıya koydum.
CAD bloke

Yanıtlar:


75

GotFocusEtkinlikte seçimi neden kaybettiğini bilmiyorum .

Ancak bir çözüm GotKeyboardFocusve GotMouseCaptureolayları seçmektir. Bu şekilde her zaman çalışır.


10
Hayır! Mevcut metnin ortasında fare ile tıklandığında - fare düğmesi bırakıldığında seçim kaybolur.
Sergey Aldoukhov

3
Yine de - ikinci bir tıklamadan sonra, tüm metni tekrar seçer ... WPF tasarımcılarının amaçlanan bir davranışı olup olmadığından emin değilsiniz, ancak kullanılabilirlik o kadar da kötü değildir. Tek bir GotFocus işleyicisinden başka bir fark, TextBox'ta boş bir alana tıklamanın tümünü seçmesidir.
Sergey Aldoukhov

3
Bu benim de ilk çözümümdü. Ancak, fareyi kullanarak Metin seçemediklerinde kullanıcıların gerçekten rahatsız olduklarını gördüm, çünkü metnin tamamını her tıkladıklarında seçiliyor ...
Nils

1
Bu çözümün bir başka dezavantajı, TextBox'ın "Kes / Kopyala / Yapıştır" menüsünü kullandığınızda, herhangi bir menü öğesini seçtiğinizde metnin tamamı seçilir.

@gcores Bunun eski olduğunu biliyorum, ancak GotFocus olayında seçilen metnin neden kaybolduğunu bilen var mı? Yine de diğer etkinliklerde çalışmakta haklısın ve bu benim kitabımda mükemmel kabul edilebilir bir çözüm.
Feign

210

Bu yüzden ilk tıklama hepsini seçer ve başka bir tıklama imlece gider (uygulamamız kalemli tabletlerde kullanılmak üzere tasarlanmıştır).

Yararlı bulabilirsiniz.

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
Bunun için çok teşekkür ederim. Bu harika çalışıyor ve kabul edilen cevap IMHO olmalı. Yukarıdaki kod, TextBox klavye veya fare (ve görünüşte ekran kalemi) aracılığıyla odak aldığında çalışır. +1
Drew Noakes

5
Burada neredeyse aynı bir cevap gördüm social.msdn.microsoft.com/Forums/en-US/wpf/thread/… , o da işe yarıyor, e.OriginalSource'u ne kadar kullanmıyorsa, ne de görsel ağaçta geziniyor. Tüm bunları yapmanın herhangi bir avantajı var mı?
Marco Luglio

1
Harika çalışıyor, ancak metnin fare ile sürüklenmesine izin verdiyse mükemmel olurdu. Google Chrome adres çubuğu ideal sistemin mükemmel bir örneğidir: kullanıcı sürüklemeden tıklayıp serbest bırakırsa metnin tamamı vurgulanır. Ancak kullanıcı tıklayıp sürüklerse, sürükleme metni tümünü seçmeden normal olarak seçer. SelectAll yalnızca fare serbest bırakıldığında gerçekleşir . Bu tasarımı hiç geliştirip geliştiremeyeceğimi göreceğim.
devios1

2
Bu çözümün bir başka dezavantajı, TextBox'ın "Kes / Kopyala / Yapıştır" menüsünü kullandığınızda, herhangi bir menü öğesini seçtiğinizde metnin tamamı seçilir.

1
İçinde bir ek test tespit SelectAllTextyöntemine textBox.IsFocusediyileştirir. GetKeyboardFocusProgramın alt sekme işleminden kaynaklandığı zaman tümünü seçmek istemezsiniz .
Scott Stafford

164

Donnelle'nin cevabı en iyi sonucu verir, ancak kullanmak için yeni bir sınıf türetmek zorunda kalmak bir acıdır.

Bunu yapmak yerine uygulamadaki tüm TextBox'lar için App.xaml.cs işleyicilerini kaydediyorum. Bu, Donnelle'nin cevabını standart TextBox kontrolü ile kullanmama izin veriyor.

App.xaml.cs dosyasına aşağıdaki yöntemleri ekleyin:

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
Bu oldukça güzel bir çözüm, aynı zamanda Matt Hamilton tarafından da yıllar
Ashley Davis

'Alındı', 'odaklanmış' bazı yanlış yazımlar var
Nate Zaugg

2
Teşekkürler Nate, düzeltildi, savunmamda yazım hatalarının
Donnelle'nin

Soruda Silverlight etiketi var, ancak Silverlight'ta hiçbir etkinlik / önizleme etkinliği yok. Silverlight için hangi çözüm kullanılmalıdır? şimdiden teşekkürler
Valentin Kuzub

4
"Odaklanan yazım ABD'de çok daha yaygındır; ancak, odaklanan yazım bazen İngiltere ve Kanada'da kullanılır ve özellikle Avustralya ve Yeni Zelanda'da yaygındır." So nyah;)
Donnelle

85

Bu oldukça eski, ama yine de cevabımı göstereceğim.

Donnelle'nin cevabının bir kısmını seçtim (çift tıklama atladı) çünkü bunun daha doğal olduğunu düşünüyorum. Ancak, gcores gibi türetilmiş bir sınıf yaratma ihtiyacından hoşlanmıyorum. Ama ben de gcores OnStartupyöntemini sevmiyorum . Ve buna "genellikle ama her zaman değil" temelinde ihtiyacım var.

Bunu xaml'de DependencyPropertyayarlayabilmem için ekli olarak local:SelectTextOnFocus.Active = "True"uyguladım. Bu yolu en hoş buluyorum.

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

"Genel ama her zaman değil" özelliğim için bu Ataşe Özelliğini True(global) olarak ayarladım TextBox Style. Bu şekilde "Metin seçme" her zaman "açık" olur, ancak metin kutusu temelinde devre dışı bırakabilirim.


8
+1 bu, global olarak ayarlamaktan çok daha iyidir ve TextBox'dan türetmekten daha 'WPF yolu'dur.
stijn

3
+1 stijn ile aynı fikirde. App.cs içindeki kodunuzu "gizlemek" SelectAllOnFocus'un neden olduğunu anlamak zorunda olan fakir geliştiriciler için hoş değil. :-) Ben sadece TextBoxBehaviors için benim sınıf içine düştü ve sonra benim temel TextBox Stili güncelledi. Bir tedavi çalıştı. Şerefe
Lee Campbell

2
@tronda: TextBox'ın TargetType'ı kullanarak kaynaklara bir stil eklemeniz yeterlidir. Wpftutorial.net/Styles.html
Nils

2
En iyi yanıt için bir +1 daha. Bulduğum tek sorun, sağ fare düğmesini kullandığımda bile metnin her zaman seçili olması - metni sık sık bağlam menüsü aracılığıyla düzenlemek için yapıyorum - çözüm bu durumda çalışmıyor çünkü ben her zaman tüm metni seçiyor sadece içerik menüsü ile 1 kelime kesmek istedim. Bunu nasıl düzeltebileceğinizi biliyor musunuz?
user3313608

2
Bu yanıtı beğendim ama neden DependencyObject'i genişletmeniz gerekiyor? Bunu kaldırdım ve hala iyi çalışıyor.
Fred

47

Size kolaylık sağlamak için yanıt çözümünü uygulayan Karışım davranışları şunlardır:

Biri tek bir TextBox'a eklemek için:

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

Ve biri birden fazla TextBox' içeren bir konteynerin köküne iliştirmek için:

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

Bu açık ara en iyi ve en temiz çözümdür. Paylaştığınız için çok teşekkürler.
Golvellius

Gerçekten güzel görünüyor, ama nedense sekme kontrolünü bozuyor ... Neden herhangi bir fikir?
Marc

Çözümü kullanmak istiyorum. Ama gerçekten kayboldu ... belki bir örneğin var mı?
Juan Pablo Gomez

Odaklanırken metin kutusunun herhangi bir yerine tıkladığınızda (düzeltme işaretini başka bir yere taşımak istediğinizi hayal edin) düzeltme işareti yerine yenidenAlll komutunu seçer. Beklenmedik bir şey. GotMouseCapture'ı yaygın olan MouseDoubleClick ile değiştirerek düzeltildi. MSDN'den gelen ikinci çözümler sayesinde.
norekhov

1
Metin kutusu FocusManager.FocusedElement aracılığıyla ilk odağı aldığında çalışmıyor gibi görünüyor. Neden herhangi bir fikir?
szx

24

Bu eski bir soru olmasına rağmen, bu sorunu yeni yaşadım, ancak Sergey'in cevabındaki gibi bir İfade Davranışı yerine Ekli Davranış kullanarak çözdüm. Bu System.Windows.InteractivityBlend SDK bağımlılık gerekmez anlamına gelir :

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

Daha sonra XAML'nizde şu şekilde kullanabilirsiniz:

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

Burada bu konuda blog yazdım .


Bu yaklaşımı seviyorum ama Get / Set yöntemleri "Property" ile bitmemelidir; Ben Xaml bölümü ekledikten sonra derleme kodu almak için kaldırmak zorunda kaldı.
Patrick Quirk

Çok güzel, beklendiği gibi çalıştı. Bunu seviyorum çünkü MVVM yaparken View endişelerini ayrı tutmamı sağlıyor.
Killnine

16

İşte MSDN'de çok iyi ve çok basit bir çözüm :

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

İşte arkasındaki kod:

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
Temel olarak, bu konudaki en çok puan alan çözümle aynı çözümdür. Ama iki yıl önce beri, şimdi @Donnelle nereden ödünç aldığını biliyorum;)
Sergey Aldoukhov

Bu çözüm en kolay görünüyordu ve benim için çalıştı. Metin kutusuna girerken varsayılan olarak belirli bir metin alt kümesinin seçilmesini istedim.
Jack B Nimble

10

Bence bu iyi çalışıyor:

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

Bir uzantı yöntemi olarak uygulamak isterseniz:

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

Ve GotFocusetkinliğinizde:

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

Yukarıdaki çözümü keşfettim çünkü birkaç ay önce belirli bir konuya odaklanmak için bir yol arıyordum UIElement. Ben bir yerde (kredi burada verilir) aşağıdaki kodu keşfetti ve iyi çalışıyor. OP'nin sorusuyla doğrudan ilişkili olmasa da, Dispatcherbir ile çalışmak için aynı kullanım modelini gösterdiğinden gönderiyorum 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);
}

Sanırım bu uygulamak için en basit yöntem. eklenti yöntemi oluşturduktan sonra sadece myTextBox.SelectAllText () öğesini çağırmanız gerekecektir. Bu cevap neden daha fazla puan almıyor? diğer çözümler neden bu kadar iyi?
Tono Nam

2
Metin kutusunun MouseUp işleyicisinden sonra çalıştırmak için zaman uyumsuz çağrı dayanıyor çünkü bu yöntemi önleyeceğini. Bunun% 100 deterministik olduğuna inanmam ve tutarsız davranışlara yol açabilir. Olması muhtemel olmasa da, yukarıdaki kesin yöntemlerle devam etmeyi tercih ederim.
Rob H

6

İşte diğer çözümlerle ilgili bazı sorunları çözme girişimi:

  1. Kes / kopyala / geçmiş için sağ tıklama bağlam menüsünü kullanmak, tümünü seçmeseniz bile tüm metni seçer.
  2. Sağ tıklama bağlam menüsünden geri dönerken, tüm metin her zaman seçilir.
  3. Alt+ İle uygulamaya geri dönerken Tab, tüm metinler her zaman seçilir.
  4. İlk tıklamada metnin yalnızca bir bölümünü seçmeye çalışırken, tümü her zaman seçilir (örneğin, Google krom adres çubuğunun aksine).

Yazdığım kod yapılandırılabilir. Sen eylemler üç salt okunur alanları belirleyerek gerçekleşmesi gereken tüm davranışlarını seçmek ne seçebilirsiniz: SelectOnKeybourdFocus, SelectOnMouseLeftClick, SelectOnMouseRightClick.

Bu çözümün dezavantajı, daha karmaşık ve statik durumun depolanmasıdır. TextBoxKontrolün varsayılan davranışı ile çirkin bir mücadele gibi görünüyor . Yine de çalışır ve tüm kod Attached Property kapsayıcı sınıfında gizlidir.

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

Ekli Özelliğe a TextBoxeklemek için tek yapmanız gereken Ekli Özelliğin xml ad alanını ( xmlns) eklemektir ve ardından şu şekilde kullanmaktır:

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

Bu çözüm hakkında bazı notlar:

  1. Bir fare aşağı olayının varsayılan davranışını geçersiz kılmak ve ilk tıklatmada metnin yalnızca bir kısmını seçmeyi etkinleştirmek için, fare yukarı olayında tüm metinler seçilir.
  2. TextBoxOdağı kaybettikten sonra seçimini hatırladığı gerçeğiyle uğraşmak zorunda kaldım . Aslında bu davranışı geçersiz kıldım.
  3. Fare düğmesinin aşağı TextBox( FirstActionIsMouseDownstatik alan) üzerindeki ilk eylem olup olmadığını hatırlamak zorundaydım .
  4. Sağ tıklamayla açılan ContextMenustatik menüyü hatırlamam gerekiyordu ( statik alan).

Bulduğum tek yan etki ne zaman SelectOnMouseRightClickdoğru. Bazen sağ tıklatma bağlam menüsü açıldığında ve bir boşluk üzerine sağ tıklandığında TextBox"tümünü seç" yapmaz.


5

Burada sunulan cevapların hiçbirini standart bir Windows metin kutusunu taklit etmedim. Örneğin, metin kutusunun son karakteri ile metin kutusunun sağ tarafı arasındaki beyaz boşluğu tıklatmayı deneyin. Buradaki çözümlerin çoğu her zaman tüm içeriği seçecektir, bu da bir metin kutusuna metin eklemeyi çok zorlaştırır.

Burada sunduğum cevap bu açıdan daha iyi davranıyor. Bu bir davranıştır (bu nedenle Blend SDK'sından System.Windows.Interactivity derlemesini gerektirir ). Ekli özellikler kullanılarak da yeniden yazılabilir.

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

Bu, burada bulduğum koda dayanıyor .


1
Bu iyi bir cevap olsa da, kullanıcı beyaz alana tıkladığında niyetinin (bir iş uygulamasında) büyük olasılıkla tüm değeri geçersiz kılmak olduğunu düşünüyorum, bu yüzden hepsini seçmek doğru yaklaşımdır.
Sergey Aldoukhov

1
Sergey: İlk tıklama tüm değeri seçecek, ikinci tıklama imleci değerin sağına yerleştirecektir. Sunulan diğer çözümlerde, ikinci tıklama tüm değerin seçili kalmasını sağlayacak ve değere eklenmesini çok zorlaştıracaktır.
Kristof Verbiest

Bu nasıl kullanılır? Bu kodu App.xaml.cs dosyasına ekledim ancak uygulamamdaki TextBox'lar üzerinde bir etkisi olmadı.
PIntag

5

Bu basit uygulama benim için mükemmel bir şekilde çalışıyor:

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

Hepsini TextBoxuygulamak için aşağıdaki koduInitializeComponent();

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

4

App.xaml dosyasında:

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

App.xaml.cs dosyasında:

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

Bu kod ile TextBoxuygulamanızdaki her şeye ulaşabilirsiniz .


3

Alındığı burada :

Global olay işleyiciyi App.xaml.cs dosyasına kaydedin:

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

    base.OnStartup(e);
}

Ardından işleyici şu kadar basittir:

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

3

Bunun çok eski olduğunu anlıyorum, ama benim çözümüm / microsoft interaktifliği ve etkileşimleri adı alanlarına dayanan çözümüm.

İlk olarak, etkileşim tetikleyicilerini bir stile yerleştirmek için bu bağlantıdaki talimatları izledim .

Sonra buna iner

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

ve bu

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

Benim durumumda, bir metin arkasında olan metin kutuları nerede bir kullanıcı denetimi var. Arkadaki kod işleyici işlevine sahiptir. Kullanıcı kontrolüne XAML'de bir isim verdim ve bu ismi eleman için kullanıyorum. Bu benim için mükemmel çalışıyor. Stili, öğesini TextBoxtıkladığınızda tüm metnin seçilmesini istediğiniz herhangi bir yere uygulayın TextBox.

Birincisi , olay tetiklendiğinde CallMethodActionmetin kutusunun SelectAllyöntemini çağırır .GotKeyboardFocusTextBox

Umarım bu yardımcı olur.


Bu çok eski bir soru olduğu için, birisinin neden bu yaklaşımı seçebileceğini belirtirseniz, yanıtınızın biraz dikkat çekmesine yardımcı olabilir.
divibisan

Öncelikle, bunun bir stile konmasına gerek yok, ancak bence buna ihtiyaç duyan birçok metin kutusu kontrolü var, bir stil gitmenin yoludur.
wiyosaya

1
Belki bazıları bu yaklaşımı kabul etmeyecektir, ancak, bu yaklaşımı neden kullanabileceğinize ilişkin olarak, TextBox alt sınıfını gerektirmez, sınıf işleyici olaylarını, uzantı yöntemlerini, ekli özellikler oluşturma vb. Gerektirmez. herhangi bir xaml projesinin kaynak sözlüğüne X: Key olmadan, her bir metin kutusunun xaml'sini değiştirmek zorunda kalmadan kaynak sözlüğü kapsamındaki herhangi bir TextBox örneğine uygulanır. Bazı durumlarda, daha temiz bir yaklaşım olabilir.
wiyosaya

2

Nils'in cevabını kullandım ama daha esnek hale geldim.

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'de aşağıdakilerden biri gibi kullanabilirsiniz:

<!-- 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
Şablonlarda kullanmak için gerçekten iyi bir çözüm çünkü gerçek bir kod arkası olmadan xaml'ye bağlayabilirsiniz, sadece metin kutusunun genişletilmiş davranışı.
Eric Johansson

2

İşte @Nasenbaer tarafından verilen cevabın C # versiyonu

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

oysa MyTextBox_GotFocustahsis olayı işleyicisi GotFocusdurumunda MyTextBox.


2

PreviewMouseLeftButtonDownBir tarayıcının olağan işlevselliğini taklit gibi görünüyor (sadece olay ile) bunun için biraz basitleştirilmiş bir cevabım var :

XAML'de bir TextBoxsözün var:

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

Kod arkasında:

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
Uygulamanızın yolunda seken kişiler için TextBox.SelectAll () ile bir GotKeyboardFocus olayı eklemek isteyebilirsiniz. Çözümünüz PasswordBox'lar için de işe yarar (PasswordBox'lar mühürlü tipler olduğundan genişletilemezler).
David Sherret

1

Herhangi bir TextBox denetimine istediğiniz davranışı eklemek için bu uzantı yöntemini deneyin. Henüz kapsamlı bir şekilde test etmedim, ama ihtiyaçlarımı karşılıyor gibi görünüyor.

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

Çözümü çok araştırdım, seçime birkaç çözüm buldum ama sorun, metin kutusundan metnin bir kısmını seçtikten sonra sağ tıklayıp kesme / kopyalama yaptığımız zaman, metnin bir kısmını bile seçtiğimde seçiyor. Bunu düzeltmek için çözüm burada. Keyboard select olayına aşağıdaki kodu eklemeniz yeterlidir. Bu benim için çalıştı.

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

Aynı problemim vardı. VB.Net'te bu şekilde kolay çalışır:

VB XAML:

<TextBox x:Name="txtFilterFrequency" />

Codehind:

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

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

Benim için en iyi çözüm, burada bir C # çeviri yayınladım: stackoverflow.com/a/48385409/3936440
ViRuSTriNiTy

Benim için bu yaklaşım zaman zaman metin seçmekte başarısız oluyor. Bence BeginInvoke nedeniyle yarış durumu.
Vimes

Lütfen belirtiniz. Dağıtım programı önceliği, beklendiği gibi varsayılan uygulamalar üzerinde çalışıyor. Durumun nedir? Açıklandığı gibi denedin mi? Çözümünüzde özel bir şey var mı?
Nasenbaer

1

Bu açık ara en basit çözüm.

Uygulamaya global bir işleyici ekleyin (App.xaml.cs) ve bitti. Sadece birkaç satır koda ihtiyacınız olacak.

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

    base.OnStartup(e);
}

Bu nedenle, bir türe (TextBox) karşı genel bir olay işleyicisi kaydetmek için EventManager sınıfını kullanın. Gerçek işleyici çok basit:

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

Buraya bakın: WPF TextBox SelectTüm Odaklan

Umarım yardımcı olur.


1

Donnelle / Groky'nin yaklaşımı ile ilgilenenler için, ancak TextBoxgirilen metnin sonuna caret yerleştirmek için son karakterin sağına (ama yine de içinde ) bir tıklama isteyenler için, bu çözümü buldum:

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

GetRoundedCharacterIndexFromPointYöntem alındı , bu yazı.


1
İyi çalışıyor, ancak çift tıklama etkinliği tetiklenmiyor
Rodrigo Caballero

Aslında doubleclick olayına girer, ancak OriginalSource özelliği TextBoxView türündedir. Bu yüzden SelectAllText yöntemi şöyle olmalıdır: private static void SelectAllText (nesne gönderen, RoutedEventArgs e) {var textBox = e.OriginalSource olarak TextBox; if (textBox! = null) {textBox.SelectAll (); System.Diagnostics.Debug.WriteLine ("TÜMÜ Seçildi"); } else if (gönderen TextBox'tır) {(TextBox olarak gönderen) .SelectAll (); }
Rodrigo Caballero

1

Google'ı test ettikten ve test ettikten sonra, benim için çalışan basit bir çözüm buldum.

LoadedKapsayıcı pencerenizin etkinliğine bir olay işleyicisi eklemeniz gerekir :

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

Daha sonra, RoutedEventHandlerönceki kodda referans verilen işleyiciyi oluşturmalısınız :

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

Artık olay işleyicilerindeki SelectAll()komutu GotFocusherhangi bir TextBoxdenetime ayrı ayrı ekleyebilirsiniz :

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

Metniniz şimdi odakta seçildi!

Dr. WPF çözümünden uyarlanan MSDN Forumları


Ben sadece kullandım: özel zaman uyumsuz void TBTime_GotFocus (nesne gönderen, RoutedEventArgs e) {TextBox tb = (TextBox) e.OriginalSource; 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

Bir pencerede 20 metin kutunuz varsa, her metin kutusu için 3 yöntem oluşturacak mısınız? Bu yaklaşım iyi değil. Buraya bir göz atın: rachel53461.wordpress.com/2011/11/05/…
Alexandru Dicu

0

Bu benim için iyi çalışıyor gibi görünüyor. Temelde daha önceki yayınların bir özeti. Bunu yapıcıdaki MainWindow.xaml.cs dosyama koydum. Biri klavye ve diğeri fare için olmak üzere iki işleyici oluşturuyorum ve her iki olayı HandleGotFocusEventda aynı dosyada oluşturucudan hemen sonra tanımlanan aynı işleve huniler.

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

Güzel ve kolay, ama bir zamanlama sorunu var gibi görünüyor - diğer her denemek (fare tıklaması), hemen tekrar seçer ...?
T4NK3R

0

MouseDown'ı geçersiz kılmanın ve çift tıkladıktan sonra tümünü seçmenin kolay bir yolu:

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

Bunu, metin kutunuzu barındıran herhangi bir denetimin yapıcısına koymayı deneyin:

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

Bunu bir pencere yapıcısına koyduğunuzda bu yaklaşım çalışmaz.
ViRuSTriNiTy

0

OnFocusFare yukarıdayken metnin seçimini kaldıran bir olay varsa , genellikle tümünü seçmeyi geciktiririm.

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

-1

Hepsini test ettim ama sadece aşağıdakiler işe yaradı:

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
Bu aynı zamanda karma kodların müstehcen bir şekilde yanlış kullanımı. Bunu okurdum, bağlantı
RichK

3
Ve GetType().Nameyerine isveya askullanmak oldukça hacky
RichK 13:11

-1

Çok sayıda cevap olduğunu görüyorum, ancak onaylanan cevap olarak, kullanılması gereken yöntemler EditTextBoxGotCapture

arkasında aşağıdaki kodla:

private void EditTextBoxGotCapture(object sender, MouseEventArgs e)
{
    if (sender is TextBox tb)
    {
        tb.Select(0, tb.Text.Length);
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.