2010-08-06 41 views
63

Tôi có một hình thức có chứa một textbox trong C# mà ta đã đặt cho một chuỗi như sau:Tại sao văn bản trong hộp văn bản được đánh dấu (được chọn) khi biểu mẫu được hiển thị?

textBox.Text = str; 

Khi mẫu được hiển thị, tại sao các văn bản trong texbox xuất hiện nổi bật/chọn?

+0

Câu hỏi của bạn có thể liên quan đến http://stackoverflow.com/ câu hỏi/1140250/cách xóa bỏ tập trung từ một hộp văn bản-trong-c-winforms – DarenW

+0

Bạn có sắp xếp việc này không? Làm thế nào bạn sửa lỗi này? – fletcher

+0

@fletcher: Tôi chưa có vòng để xem nó. Tôi sẽ trả lời câu trả lời trong vài ngày nữa. – CJ7

Trả lời

87

Hộp văn bản có số TabIndex trong số 0 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ể cấp điều khiển khác 0 TabIndex (nếu có) và đặt hộp văn bản một chỉ mục tab khác (> 0) hoặc đặt TabStop thà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ó xuất phát từ hành vi của nó? – 26071986

+0

@ 26071986 - Vâng, tôi đã chạy một bài kiểm tra nhanh. Nếu, trên một biểu mẫu với 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 văn bản được tô sáng. Nếu nút có chỉ mục tab 0 và tab hộp văn bản là> 0 thì văn bản sẽ không được đánh dấu. – fletcher

+0

Thật thú vị ... – 26071986

38

Hành vi mặc định của một TextBox trong Windows Forms là để làm nổi bật tất cả các văn bản nếu nó được tập trung cho lần đầu tiên bằng cách chạm vào nó, nhưng không phải 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 nhìn vào OnGotFocus() ghi đè các 's TextBox:

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

Đó chính là câu lệnh if đó gây ra hành vi mà chúng ta không thích. Bên cạnh đó, để thêm sự xúc phạm đến thương tích, setter các Text sở hữu của một cách mù quáng reset rằng selectionSet biến bất cứ khi nào văn bản được giao 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ó một TextBox và tab vào nó, tất cả các văn bản sẽ được chọn. Nếu bạn nhấp vào nó, đánh dấu sẽ bị xóa và nếu bạn tái tab vào vị trí đó, 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 mới Text và tab lại vào TextBox, thì tất cả văn bản sẽ được chọn lại.

Nếu bạn đang như tôi và thấy hành vi này gây phiền nhiễu và không phù hợp, sau đó có hai cách giải quyết vấn đề này.

Đầu tiên, và có lẽ là dễ nhất, chỉ đơn giản là kích hoạt các thiết lập của selectionSet bằng cách gọi DeselectAll() vào mẫu Load() và bất cứ khi nào Text thay đổi:.

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

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

(DeselectAll() chỉ đặt SelectionLength để zero Nó thực sự SelectionStart 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 tôi đang thiết lập bắt đầu để kết thúc văn bản.Nhưng nếu chúng ta đặt nó vào bất kỳ vị trí nào khác, như bắt đầu của văn bản , sau đó gọi nó là một ý tưởng tốt)

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

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

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

22

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 ý với rất nhiều đề xuất phức tạp khác. Chỉ cần thiết lập SelectionStart là 0 sau khi thiết lập văn bản của bạn. Đã giải quyết được vấn đề!

Ví dụ:

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

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

View-> Tab thứ tự

Lưu ý rằng tùy chọn này chỉ có sẵn trong " Xem "nếu bạn mở dạng 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 tôi lo ngại về thứ tự tab. –

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 trả về FALSE từ 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 winforms. –

1

Để unhighlight một trường văn bản, với VS 2013, thử init với:

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

Và thêm phương pháp:

public void myTextBox_GotFocus(object sender, EventArgs e) 
{ 
    myTextBox.SelectionLength=0; 
} 
Các vấn đề liên quan