У мене є форма, що містить TextBox
в C #, яку я встановив як рядок наступним чином:
textBox.Text = str;
Чому при відображенні форми текст у текстовому полі відображається виділеним / виділеним?
У мене є форма, що містить TextBox
в C #, яку я встановив як рядок наступним чином:
textBox.Text = str;
Чому при відображенні форми текст у текстовому полі відображається виділеним / виділеним?
Відповіді:
Текстове поле має TabIndex
значення 0 і має TabStop
значення true. Це означає, що елементу керування буде приділено увагу при відображенні форми.
Ви можете або дати іншому елементу керування 0 TabIndex
(якщо він є) і призначити текстовому полі інший індекс вкладки (> 0), або встановити TabStop
значення false для текстового поля, щоб це не відбувалося.
Поведінка TextBox за замовчуванням у Windows Forms полягає у виділенні всього тексту, якщо він вперше сфокусований, вклавши його, але не якщо його клацнути. Ми можемо побачити це в Reflector, подивившись на перевизначення TextBox
' OnGotFocus()
:
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();
}
}
}
Це те, що твердження, яке спричиняє поведінку, яка нам не подобається. Крім того, щоб додати образи до травми, 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
на нуль. Це насправді 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;
Ви також можете вибрати порядок вкладок для елементів керування форми, відкривши:
Вигляд-> Порядок вкладок
Зверніть увагу, що цей параметр доступний лише в "Перегляді", якщо у вас відкрито подання дизайну форми.
Вибір "Порядок вкладок" відкриває вікно форми, яка дозволяє вибрати бажаний порядок вкладок, натиснувши на елементи керування.
Щоб висвітлити текстове поле, у VS 2013 спробуйте ініціювати за допомогою:
myTextBox.GotFocus += new System.EventHandler(this.myTextBox_GotFocus);
І додайте метод:
public void myTextBox_GotFocus(object sender, EventArgs e)
{
myTextBox.SelectionLength=0;
}
Я не тестував це на C #, але зіткнувся з тією ж проблемою за допомогою діалогового вікна C ++ WIN32. Здається, ви можете змінити поведінку, повернувшись FALSE
з OnInitDialog()
або WM_INITDIALOG
. Сподіваюся, це допомагає.