Tại sao văn bản trong TextBox được đánh dấu (được chọn) khi biểu mẫu được hiển thị?


84

Tôi có một biểu mẫu chứa một TextBoxtrong C # mà tôi đặt thành một chuỗi như sau:

textBox.Text = str;

Khi biểu mẫu được hiển thị, tại sao văn bản trong hộp thư lại được đánh dấu / chọn?


Câu hỏi của bạn có thể liên quan đến stackoverflow.com/questions/1140250/…
DarenW

Bạn đã quản lý để sắp xếp điều này? Bạn đã khắc phục điều này như thế nào?
fletcher

@fletcher: Tôi vẫn chưa xem xét nó. Tôi sẽ đưa ra câu trả lời trong vài ngày tới.
CJ7

Bạn có thể thêm một thẻ vb.net, vì vấn đề này thực sự là câu trả lời giống nhau và được chấp nhận là hợp lệ quá
Andrea Antonangeli

Câu trả lời của BenSmith liên quan đến việc xem Thứ tự tab sẽ rất hữu ích trong trường hợp này.
Samitha Chathuranga

Câu trả lời:


128

Hộp văn bản có TabIndex0 và TabStopđược đặt thành true. Điều này có nghĩa là điều khiển sẽ được tập trung khi biểu mẫu được hiển thị.

Bạn có thể đặt một điều khiển khác là 0 TabIndex(nếu có) và cung cấp cho hộp văn bản một chỉ mục tab khác (> 0) hoặc đặt TabStopthành false cho hộp văn bản để ngăn điều này xảy ra.


1
Bạn có chắc chắn rằng hộp văn bản TabIndex được đặt thành 0 không? Nó đi ra từ hành vi của nó?
26071986

@ 26071986 - Chà, tôi đã chạy thử nhanh. Nếu, trên một biểu mẫu có một hộp văn bản và một nút, tôi thay đổi văn bản trong hộp văn bản trong hàm tạo khi tabindex được đặt thành 0 thì văn bản được đánh dấu. Nếu nút có chỉ mục tab 0 và tabindex hộp văn bản> 0, văn bản không được đánh dấu.
fletcher

Nó thực sự có vẻ liên quan đến TabIndex - chỉ là tôi đã thay đổi tất cả các chỉ số tab phần tử của mình một cách thích hợp (vì vậy tôi nghĩ vậy). Hóa ra Nhóm cũng có chỉ mục tab mà bạn cần thay đổi cũng như tất cả các phần tử chứa chúng. Vì vậy, trong khi tôi thiết lập các tab phần tử từ 1-9, một nhóm vẫn có 0, vì vậy hộp văn bản trong nhóm đó trở thành phần tử được kích hoạt đầu tiên (do đó nội dung của nó được đánh dấu).
deed02392

1
Nó không nhất thiết liên quan đến việc có TabIndex = 0, nhưng nó chắc chắn xảy ra nếu TextBox có TabIndex THẤP NHẤT của biểu mẫu. Để xác minh: đặt TabIndex = 5 trong TextBox và đặt một số lớn hơn 5 trong tất cả TabIndex của các điều khiển khác của biểu mẫu.
Andrea Antonangeli

Điều này cũng xảy ra khi bạn chọn một TabPage mới trong một TabControl. Giải pháp tương tự hoạt động.
JonP

43

Hành vi mặc định của TextBox trong Windows Forms là đánh dấu tất cả văn bản nếu nó được tập trung lần đầu tiên bằng cách nhấn tab vào nó, nhưng không đánh dấu nếu nó được nhấp vào. Chúng ta có thể thấy điều này trong Reflector bằng cách xem phần ghi đè TextBoxcủa 's 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();
        }
    }
}

Đó là câu lệnh if gây ra hành vi mà chúng ta không thích. Hơn nữa, để thêm sự xúc phạm đến thương tích, người thiết lập Texttài sản đặt lại một cách mù quáng selectionSetbiến đó bất cứ khi nào văn bản được gán lại:

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

Vì vậy, nếu bạn có TextBox và tab trong đó, tất cả văn bản sẽ được chọn. Nếu bạn nhấp vào nó, phần đánh dấu sẽ bị xóa và nếu bạn nhấn lại vào nó, vị trí dấu mũ của bạn (và độ dài lựa chọn bằng 0) sẽ được giữ nguyên. Nhưng nếu chúng ta lập trình đặt mới Textvà tab vào TextBox một lần nữa, thì tất cả văn bản sẽ được chọn lại.

Nếu bạn giống tôi và thấy hành vi này gây phiền nhiễu và không nhất quán, thì có hai cách để giải quyết vấn đề này.

Đầu tiên, và có lẽ là dễ nhất, chỉ cần kích hoạt cài đặt selectionSetbằng cách gọi DeselectAll()vào biểu mẫu Load()và bất cứ khi nào Textthay đổi:

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

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

( DeselectAll()Chỉ bộ SelectionLengthkhông. Nó thực sự SelectionStartmà flips TextBox's selectionSetbiến. Trong trường hợp trên, các cuộc gọi đến DeselectAll()là không cần thiết vì chúng ta đang thiết lập khi bắt đầu đến khi kết thúc của văn bản. Nhưng nếu chúng ta đặt nó vào bất kỳ vị trí khác, như đầu văn bản, sau đó gọi nó là một ý kiến ​​hay.)

Cách lâu dài hơn là tạo TextBox của riêng chúng tôi với hành vi mong muốn thông qua kế thừa:

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;
        }
    }
}

Bạn có thể bị cám dỗ để không gọi base.OnGotFocus(), nhưng sau đó chúng ta sẽ mất chức năng hữu ích trong Controllớp cơ sở . Và bạn có thể bị cám dỗ để không gây rối với những selectionSetđiều vô nghĩa và chỉ cần bỏ chọn văn bản mọi lúc trong OnGotFocus (), nhưng sau đó chúng tôi sẽ mất điểm nổi bật của người dùng nếu họ tab ra khỏi trường và quay lại.

Xấu xí? Bạn betcha. Nhưng đó là những gì nó được.


31

Các câu trả lời cho câu hỏi này đã giúp tôi rất nhiều với một vấn đề tương tự, nhưng câu trả lời đơn giản chỉ được gợi ý cùng với rất nhiều gợi ý phức tạp khác. Chỉ cần đặt SelectionStartthành 0sau khi đặt Văn bản của bạn. Vấn đề đã được giải quyết!

Thí dụ:

yourtextbox.Text = "asdf";
yourtextbox.SelectionStart = 0;

4

Bạn cũng có thể chọn thứ tự tab cho các điều khiển biểu mẫu của mình bằng cách mở:

Xem-> Thứ tự tab

Lưu ý rằng tùy chọn này chỉ khả dụng trong "Chế độ xem" nếu bạn mở chế độ xem thiết kế Biểu mẫu.

Chọn "Thứ tự tab" sẽ mở ra dạng xem Biểu mẫu cho phép bạn chọn thứ tự tab mong muốn bằng cách nhấp vào các điều khiển.


1
Điều này đã giúp tôi rất nhiều. Trên thực tế, chỉ mục tab không quan trọng nếu chúng ta quan tâm đến thứ tự tab.
Samitha Chathuranga

1

Để hiển thị trường văn bản, với VS 2013, hãy thử bắt đầu bằng:

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

Và thêm phương thức:

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

Điều này sẽ làm cho văn bản bị bỏ chọn nếu trước đó bạn đặt tiêu điểm hộp văn bản, chọn một số văn bản trong đó, di chuyển ra khỏi nó và sau đó lấy tiêu điểm lại.
Stewart

0

Tôi chưa thử nghiệm điều này trên C # nhưng tôi đã gặp phải vấn đề tương tự khi sử dụng hộp thoại C ++ WIN32. Có vẻ như bạn có thể thay đổi hành vi bằng cách quay lại FALSEtừ OnInitDialog()hoặc WM_INITDIALOG. Hi vọng điêu nay co ich.


1
Tôi không nghĩ rằng điều này sẽ giúp ích nhiều, vì API cửa sổ được đóng gói bên trong các biểu mẫu win.
Nathan A
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.