У меня есть форма, содержащая текстовое поле в С#, которое я задал для строки следующим образом:
textBox.Text = str;
Когда отображается форма, почему текст в texbox отображается выделенным/выбранным?
У меня есть форма, содержащая текстовое поле в С#, которое я задал для строки следующим образом:
textBox.Text = str;
Когда отображается форма, почему текст в texbox отображается выделенным/выбранным?
Текстовое поле имеет TabIndex
от 0 и TabStop
, установленное в значение true. Это означает, что элемент управления будет фокусироваться при отображении формы.
Вы можете либо дать другому элементу управления 0 TabIndex
(если он есть), и дать текстовому полю другой указатель вкладки ( > 0), либо установить TabStop
на false для текстового поля, чтобы это не происходило.
Поведение TextBox по умолчанию в Windows Forms по умолчанию заключается в том, чтобы выделить весь текст, если он будет сфокусирован в первый раз, введя в него вкладку, но не при нажатии на него. Мы можем увидеть это в Reflector, посмотрев на TextBox
OnGotFocus()
override:
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();
}
}
}
Это утверждение if, которое вызывает поведение, которое нам не нравится. Кроме того, чтобы добавить оскорбление к травме, установщик свойств Text
слепо сбрасывает эту переменную selectionSet
всякий раз, когда текст переназначается:
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
this.selectionSet = false;
}
}
Итак, если у вас есть TextBox и вкладка в него, будет выбран весь текст. Если вы нажмете на него, выделение будет удалено, и если вы заново вложите его в него, ваша позиция каретки (и длина выделения равна нулю) будет сохранена. Но если мы программным образом добавим новый Text
и вкладку в TextBox снова, тогда весь текст будет выбран снова.
Если вы похожи на меня и находите это поведение раздражающим и непоследовательным, тогда есть две возможности для решения этой проблемы.
Первый и, вероятно, самый простой - просто вызвать настройку selectionSet
, вызвав DeselectAll()
в форме Load()
и всякий раз, когда изменяется значение Text
:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.textBox2.SelectionStart = this.textBox2.Text.Length;
this.textBox2.DeselectAll();
}
(DeselectAll()
просто устанавливает SelectionLength
в 0. Фактически SelectionStart
, который переворачивает переменную TextBox
selectionSet
. В приведенном выше случае вызов DeselectAll()
не требуется, поскольку мы устанавливаем начните с конца текста, но если мы установим его в любую другую позицию, например, начало текста, тогда вызов это хорошая идея.)
Более постоянным способом является создание нашего собственного TextBox с желаемым поведением через наследование:
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;
}
}
}
Возможно, вам захотелось просто не называть base.OnGotFocus()
, но тогда мы потеряли бы полезную функциональность в базовом классе Control
. И у вас может возникнуть соблазн не путаться с бессмысленностью selectionSet
вообще и просто отменить выбор текста каждый раз в OnGotFocus(), но тогда мы потеряем подсветку пользователя, если они будут выведены из поля и обратно.
Гадкий? Еще бы. Но это то, что есть.
Ответы на этот вопрос помогли мне с подобной проблемой, но простой ответ намечен только на множество других сложных предложений. Просто установите SelectionStart на 0 после настройки текста. Проблема решена!
Пример:
yourtextbox.Text = "asdf";
yourtextbox.SelectionStart = 0;
Вы также можете выбрать порядок вкладок для элементов управления формы, открыв:
View- > Tab Order
Обратите внимание, что этот параметр доступен только в "Вид", если у вас открыто представление формы.
Выбор "Tab Order" открывает вид формы, который позволяет вам выбрать желаемый порядок вкладок, щелкнув элементы управления.
Чтобы высвечивать текстовое поле с VS 2013, попробуйте выполнить init с помощью
myTextBox.GotFocus += new System.EventHandler(this.myTextBox_GotFocus);
И добавьте метод:
public void myTextBox_GotFocus(object sender, EventArgs e)
{
myTextBox.SelectionLength=0;
}
Я не тестировал это на С#, но я столкнулся с той же проблемой, используя диалоговое окно С++ WIN32. Похоже, вы можете изменить поведение, вернув FALSE из OnInitDialog() или WM_INITDIALOG. Надеюсь, это поможет.