web-dev-qa-db-ja.com

フォームが表示されるときに、TextBoxのテキストが強調表示(選択)されるのはなぜですか?

次のように文字列に設定したC#のTextBoxを含むフォームがあります。

textBox.Text = str;

フォームが表示されているときに、Texboxのテキストが強調表示/選択されているのはなぜですか?

76
CJ7

テキストボックスのTabIndexは0で、TabStopはtrueに設定されています。これは、フォームが表示されるときにコントロールにフォーカスが与えられることを意味します。

別のコントロールに0 TabIndex(ある場合)を与え、テキストボックスに別のタブインデックス(> 0)を与えるか、テキストボックスが停止するようにTabStopをfalseに設定できます。これが起こるから。

115
fletcher

WindowsフォームのTextBoxのデフォルトの動作では、タブをクリックして初めてフォーカスを取得した場合、すべてのテキストが強調表示されますが、クリックされた場合は強調表示されません。 TextBoxOnGotFocus()オーバーライドを見ると、Reflectorでこれを確認できます。

_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ステートメントです。さらに、傷害にin辱を加えるために、Textプロパティのセッターは、テキストが再割り当てされるたびに、そのselectionSet変数を盲目的にリセットします。

_public override string Text
{
    get
    {
        return base.Text;
    }
    set
    {
        base.Text = value;
        this.selectionSet = false;
    }
}
_

そのため、TextBoxがあり、その中にタブがある場合、すべてのテキストが選択されます。クリックするとハイライトが削除され、再度タブで移動すると、キャレットの位置(および選択範囲の長さゼロ)が保持されます。しかし、プログラムで新しいTextを設定し、再度TextBoxにタブすると、すべてのテキストが再び選択されます。

あなたが私のようで、この動作が迷惑で一貫性がないと思う場合、この問題を回避する方法は2つあります。

最初の、おそらく最も簡単な方法は、DeselectAll()Load()を呼び出してselectionSetが変更されるたびにTextの設定をトリガーすることです。

_protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);

    this.textBox2.SelectionStart = this.textBox2.Text.Length;
    this.textBox2.DeselectAll();
}
_

DeselectAll()SelectionLengthをゼロに設定するだけです。実際にSelectionStartTextBox変数を反転させるのは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()で毎回テキストを選択解除するように誘惑されるかもしれませんが、フィールドからタブアウトして戻った場合、ユーザーのハイライトを失います。

醜い?もちろんです。しかし、それはそれです。

41

この質問への答えは、同様の問題で私を大いに助けましたが、簡単な答えは、他の多くの複雑な提案でのみ暗示されています。テキストを設定した後、SelectionStartを0に設定するだけです。問題が解決しました!

例:

yourtextbox.Text = "asdf";
yourtextbox.SelectionStart = 0;
27
Frank T. Clark

次を開いて、フォームのコントロールのタブ順序を選択することもできます。

表示->タブ注文

このオプションは、フォームデザインビューを開いている場合にのみ[表示]で使用できることに注意してください。

[タブ順序]を選択すると、フォームのビューが開き、コントロールをクリックして目的のタブ順序を選択できます。

3
Ben Smith

VS 2013でテキストフィールドのハイライトを解除するには、次を使用してinitを試してください。

myTextBox.GotFocus += new System.EventHandler(this.myTextBox_GotFocus);

そしてメソッドを追加します:

public void myTextBox_GotFocus(object sender, EventArgs e)
{
    myTextBox.SelectionLength=0;
}
1
Marty

私はこれをC#でテストしていませんが、C++ WIN32ダイアログボックスを使用して同じ問題に遭遇しました。 OnInitDialog()またはWM_INITDIALOGからFALSEを返すことで動作を変更できるようです。お役に立てれば。

0
user3658040