Mam formularz zawierający a TextBox
w C #, który ustawiam na ciąg w następujący sposób:
textBox.Text = str;
Dlaczego po wyświetleniu formularza tekst w polu tekstowym jest podświetlony / zaznaczony?
Mam formularz zawierający a TextBox
w C #, który ustawiam na ciąg w następujący sposób:
textBox.Text = str;
Dlaczego po wyświetleniu formularza tekst w polu tekstowym jest podświetlony / zaznaczony?
Odpowiedzi:
Pole tekstowe ma TabIndex
0 i jest TabStop
ustawione na true. Oznacza to, że po wyświetleniu formularza fokus zostanie przypisany do kontrolki.
Możesz albo nadać innej kontrolce 0 TabIndex
(jeśli istnieje) i nadać polu tekstowemu inny indeks tabulatora (> 0) lub ustawić TabStop
na fałsz, aby pole tekstowe to powstrzymało.
Domyślnym zachowaniem TextBox w Windows Forms jest podświetlenie całego tekstu, jeśli zostanie on skupiony po raz pierwszy, przechodząc do niego, ale nie, jeśli zostanie kliknięty. Widzimy to w reflektor patrząc na TextBox
„s OnGotFocus()
ręcznym:
protected override void OnGotFocus(EventArgs e)
{
base.OnGotFocus(e);
if (!this.selectionSet)
{
this.selectionSet = true;
if ((this.SelectionLength == 0) && (Control.MouseButtons == MouseButtons.None))
{
base.SelectAll();
}
}
}
Chodzi o to, że jeśli stwierdzenie powoduje zachowanie, którego nie lubimy. Ponadto, aby dodać zniewagę do obrażeń, Text
ustawiacz właściwości ślepo resetuje tę selectionSet
zmienną za każdym razem, gdy tekst jest ponownie przypisywany:
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
this.selectionSet = false;
}
}
Więc jeśli masz TextBox i kartę, cały tekst zostanie zaznaczony. Jeśli klikniesz na niego, podświetlenie zostanie usunięte, a jeśli ponownie przejdziesz do niego tabulatorem, pozycja kursora (i długość zaznaczenia równa zero) zostanie zachowana. Ale jeśli programowo ustawimy nowyText
i ponownie przejdziemy do TextBox, cały tekst zostanie ponownie zaznaczony.
Jeśli jesteś podobny do mnie i uważasz to zachowanie za irytujące i niespójne, istnieją dwa sposoby obejścia tego problemu.
Pierwszym i prawdopodobnie najłatwiejszym jest po prostu wywołanie ustawienia selectionSet
przez wywołanie DeselectAll()
formularza Load()
i za każdym razem, gdy Text
zmiany:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.textBox2.SelectionStart = this.textBox2.Text.Length;
this.textBox2.DeselectAll();
}
( DeselectAll()
po prostu ustawia SelectionLength
na zero. Właściwie SelectionStart
to odwraca zmienną TextBox
' selectionSet
. W powyższym przypadku wywołanie DeselectAll()
nie jest konieczne, ponieważ ustawiamy początek na koniec tekstu. Ale jeśli ustawimy go na inną pozycję, na przykład początek tekstu, a następnie nazwanie go jest dobrym pomysłem).
Bardziej trwałym sposobem jest utworzenie własnego TextBox z pożądanym zachowaniem poprzez dziedziczenie:
public class NonSelectingTextBox : TextBox
{
// Base class has a selectionSet property, but its private.
// We need to shadow with our own variable. If true, this means
// "don't mess with the selection, the user did it."
private bool selectionSet;
protected override void OnGotFocus(EventArgs e)
{
bool needToDeselect = false;
// We don't want to avoid calling the base implementation
// completely. We mirror the logic that we are trying to avoid;
// if the base implementation will select all of the text, we
// set a boolean.
if (!this.selectionSet)
{
this.selectionSet = true;
if ((this.SelectionLength == 0) &&
(Control.MouseButtons == MouseButtons.None))
{
needToDeselect = true;
}
}
// Call the base implementation
base.OnGotFocus(e);
// Did we notice that the text was selected automatically? Let's
// de-select it and put the caret at the end.
if (needToDeselect)
{
this.SelectionStart = this.Text.Length;
this.DeselectAll();
}
}
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
// Update our copy of the variable since the
// base implementation will have flipped its back.
this.selectionSet = false;
}
}
}
Może kusiło Cię, aby po prostu nie dzwonić base.OnGotFocus()
, ale wtedy stracilibyśmy użyteczną funkcjonalność w Control
klasie bazowej . I możesz ulec pokusie, aby nie zadzierać zselectionSet
bzdurami i po prostu odznaczać tekst za każdym razem w OnGotFocus (), ale wtedy stracilibyśmy wyróżnienie użytkownika, gdyby wyszedł z pola iz powrotem.
Brzydki? Jasne. Ale tak właśnie jest.
Odpowiedzi na to pytanie bardzo mi pomogły w podobnym problemie, ale do prostej odpowiedzi podpowiada tylko wiele innych złożonych sugestii. Wystarczy ustawić SelectionStart
, aby 0
po ustawieniu tekstu. Problem rozwiązany!
Przykład:
yourtextbox.Text = "asdf";
yourtextbox.SelectionStart = 0;
Możesz również wybrać kolejność zakładek dla kontrolek formularza, otwierając:
Widok-> Kolejność zakładek
Zauważ, że ta opcja jest dostępna tylko w „Widok”, jeśli masz otwarty widok projektu formularza.
Wybranie „Kolejność zakładek” otwiera widok formularza, który pozwala wybrać żądaną kolejność zakładek, klikając kontrolki.
Aby usunąć podświetlenie pola tekstowego, w VS 2013 spróbuj zainicjować za pomocą:
myTextBox.GotFocus += new System.EventHandler(this.myTextBox_GotFocus);
I dodaj metodę:
public void myTextBox_GotFocus(object sender, EventArgs e)
{
myTextBox.SelectionLength=0;
}
Nie testowałem tego w C #, ale napotkałem ten sam problem przy użyciu okna dialogowego C ++ WIN32. Wygląda na to, że możesz zmienić zachowanie, wracając FALSE
zOnInitDialog()
lub WM_INITDIALOG
. Mam nadzieję że to pomoże.