2009-03-11 16 views
19

Tôi có trình xử lý sự kiện cho Textbox cũng như cho RichTextBox. Mã này là giống hệt nhau, nhưngTruyền đối tượng người gửi trong trình xử lý sự kiện bằng cách sử dụng GetType(). Tên

Trong handler # 1 tôi làm:

RichTextBox tb = (RichTextBox)sender 

Trong handler # 2 cho phù hợp:

TextBox tb = (TextBox)sender 

Làm như vậy tôi có thể thao tác hoàn toàn sự kiểm soát gửi. gì tôi muốn biết là như thế nào tôi có thể cast đối tượng gửi đến Textbox hoặc richtextbox theo kiểu của nó sử dụng

sender.GetType().Name 

và sau đó tạo ra sự kiểm soát trong thời gian chạy và làm việc với nó. Bằng cách đó tôi chỉ cần chức năng xử lý một sự kiện: mã ít hơn, ít lỗi, dễ dàng hơn để duy trì và DRY :-)

+0

Bạn có thể đưa ra ví dụ về phương pháp đa hình hoặc thuộc tính được chia sẻ giữa hai loại đó không? và chưa được tiếp xúc bởi một giao diện chung? – AnthonyWJones

Trả lời

3

Tùy thuộc vào những gì thuộc tính bạn cần, bạn có thể đúc người gửi dưới dạng TextBoxBase vì cả TextBox và RichTextBox đều được kế thừa từ lớp con đó.

+0

có vẻ đầy hứa hẹn! Tôi sẽ thử ... – tfl

+0

Hy vọng nó hoạt động (: – Kieron

4
RichTextBox textbox = sender as RichTextBox; 
if (textbox != null) 
{ 
    // do stuff as a rtb 
    textbox.Text = "I'm a rtb"; 
    return; 
} 

TextBox textbox = sender as TextBox; 
if (textbox != null) 
{ 
    // do stuff as a textbox 
    textbox.Text = "I'm a textbox"; 
} 
1

Thay vì tên loại bạn có thể sử dụng 'là', nếu bạn chỉ muốn biết nhập và không cần tham chiếu đối tượng.

if (sender is RichTextBox) 
{ 
    // ... 
} 
else if (sender is TextBox) 
{ 
    // ... 
} 

Edit: Tuy nhiên như đã chỉ ra trong một chú thích, bạn thường làm muốn oobject: C# 7 có một cú pháp đẹp cho phép bạn kiểm tra và nhận được inline giá trị:

if (sender is RichTextBox richTextBox) 
{ 
    richTextBox.Text = "I am rich"; 
} 
else if (sender is TextBox textBox) 
{ 
    textBox.Text = "I am not rich"; 
} 
+0

dường như là sự thỏa hiệp tốt nhất - cảm ơn – tfl

+1

Điều này là ổn nhưng đề xuất @Chris là tốt hơn. Kể từ khi bạn sẽ làm một cái gì đó với các đối tượng ngay lập tức nó sẽ giúp bạn tiết kiệm thêm một diễn viên. –

3

Đúc chỉ có thể được thực hiện tại thời gian biên dịch và do đó bạn cần biết các loại mà bạn muốn truyền vào lúc biên dịch. Kiểu thời gian chạy (như được trả về bởi GetType()) do đó không thể được sử dụng khi truyền.

Nếu đó là tính đa hình bạn đang tìm kiếm, bạn có thể truy cập thuộc tính Tên thông qua phản ánh. Tôi sẽ không đi theo cách đó mặc dù chỉ để có thể tái sử dụng xử lý sự kiện.

Nếu bạn muốn gõ mạnh mẽ, một lớp cơ sở chung hoặc giao diện trên hai người gửi là cách duy nhất để đi.

28

Bạn không bao giờ phải truyền. Tôi đã từng nghĩ theo cách tương tự khi tôi bắt đầu, 'mẫu' này là không chính xác, và không thực sự hợp lý.

Tốt nhất là sử dụng một cái gì đó như:

if (sender is TextBox) 
{ 
    TextBox tb = (TextBox)sender; 
} 
else if (sender is RichTextBox) 
{ 
    RichTextBox rtb = (RichTextBox)sender; 
} 
else 
{ 
    // etc 
} 
+1

Bạn đang thực sự đúc khi bạn đã xác định loại của đối tượng, vì vậy bạn * làm * phải truyền, nhưng điều này chắc chắn là cách đúng để làm điều đó vì nó không dựa vào phản xạ (chậm). – idmadj

0

Nếu mã là giống hệt nhau, bạn cần phải quan tâm? Tôi tự hỏi nếu việc đúc thành Control sẽ không cung cấp cho bạn mọi thứ bạn cần ...

Một trình xử lý phức tạp không nhất thiết phải tốt hơn một số trình xử lý đơn giản. Dù bằng cách nào, nếu bạn đi tuyến đường này, "là"/"là" là một lợi thế (nó không phụ thuộc vào dây vv):

TextBox tb = sender as TextBox; 
if(tb!=null) {/* TextBox specific code */} 
... 
0

nếu bạn không muốn lặp lại mã thì bạn có thể truyền cả hai điều khiển, tái cấu trúc các hành động phổ biến thành một phương thức riêng biệt, lấy TextBoxBase làm đối số. Và trong trình xử lý sự kiện của bạn, chuyển đổi các điều khiển thành System.Windows.Forms.TextBoxBase khi cả hai điều khiển đều bắt nguồn từ TexbBoxBase và gọi phương thức.

Xin lưu ý Nếu bạn cần các thuộc tính cụ thể của bất kỳ điều khiển nào trong số các điều khiển này thì việc tái cấu trúc này sẽ không hoạt động.

6

Tôi biết đây là một bài rất cũ nhưng trong Framework 4 bạn có thể cast người gửi như một điều khiển:

Control cntrl = (Control)sender; 
cntrl.Text = "This is a " + sender.GetType().ToString(); 

Lưu ý bạn chỉ có thể tham khảo điều khiển tất cả các điều khiển khác nhau có điểm chung (tức là Văn bản).

0

phiên bản Generic của đoạn code trên:

public static void CastAndUse<T>(object item, Action<T> action) where T : class 
{ 
    T thing = item as T; 

    if (thing != null) 
    { 
     action(thing); 
    } 
} 

Được sử dụng như:

CastAndUse(sender, new Action((foo) => foo = bar)); 

Không hoàn hảo, nhưng tiện dụng.

0

Bạn cũng có thể sử dụng biến cố định nội tuyến để xử lý diễn viên cho bạn.

if (sender is RichTextBox tb) 
{ 
    // ... // 
} 
else if (sender is TextBox tb) 
{ 
    // ... // 
} 
Các vấn đề liên quan