为什么在显示表单时,文本框中的文本突出显示(选中)?
我有一个包含在C#中的文本框,我设置为一个string,如下所示:
textBox.Text = str;
显示表单时,为什么texbox中的文本突出显示/选中?
该文本框的TabIndex
为0, TabStop
设置为true。 这意味着当窗体被显示时,控件将被赋予焦点。
您可以给另一个控件0 TabIndex
(如果有的话),并给文本框一个不同的标签索引(> 0),或者设置TabStop
为false的文本框来阻止这种情况发生。
Windows窗体中TextBox的默认行为是突出显示所有的文本,如果它通过标签首次被关注,而不是被点击进去。 我们可以在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
variables:
public override string Text { get { return base.Text; } set { base.Text = value; this.selectionSet = false; } }
所以如果你有一个文本框和标签,所有的文本将被选中。 如果点击它,突出显示被删除,如果您重新插入它,您的插入位置(和select长度零)被保留。 但是,如果我们以编程方式设置新的Text
,并再次标签到文本框,那么所有的文本将被再次select。
如果你像我一样,发现这种行为烦人和不一致,那么围绕这个问题有两种方法。
第一种,也可能是最简单的,只需通过在Load()
上调用DeselectAll()
,并在Text
发生变化时触发selectionSet
的设置:
protected override void OnLoad(EventArgs e) { base.OnLoad(e); this.textBox2.SelectionStart = this.textBox2.Text.Length; this.textBox2.DeselectAll(); }
( DeselectAll()
只是将SelectionLength
设置为零,实际上是SelectionStart
,它翻转了TextBox
的selectionSet
variables,在这种情况下,调用DeselectAll()
并不是必须的,因为我们将start设置为文本的结尾。如果我们把它设置到任何其他位置,如文本的开始,那么调用它是个好主意。)
更持久的方法是通过inheritance创build我们自己的文本框与所需的行为:
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
类中我们会失去有用的function。 而且你可能会试图不要惹起selectionSet
胡扯,只需在OnGotFocus()中每次取消select该文本,但是如果用户标签出现在字段后面,则会丢失用户的高亮。
丑陋? 完全正确。 但是它就是这样啊。
这个问题的答案帮助了我很多类似的问题,但简单的答案只是暗示与其他很多复杂的build议。 设置文本后,只需将SelectionStart设置为0。 问题解决了!
例:
yourtextbox.Text = "asdf"; yourtextbox.SelectionStart = 0;
您也可以通过打开以下选项来select表单控件的Tab键顺序:
查看 – >标签顺序
请注意,如果打开窗体devise视图,则此选项仅在“查看”中可用。
select“制表顺序”打开窗体的视图,允许您通过单击控件select所需的制表顺序。
为了避免使用VS 2013的文本字段,请尝试使用init:
myTextBox.GotFocus += new System.EventHandler(this.myTextBox_GotFocus);
并添加方法:
public void myTextBox_GotFocus(object sender, EventArgs e) { myTextBox.SelectionLength=0; }
我没有在C#上testing过,但是我用C ++ WIN32对话框遇到了同样的问题。 好像你可以通过从OnInitDialog()或WM_INITDIALOG返回FALSE来改变行为。 希望这可以帮助。