2011-07-07 14 views
5

Tôi đang tạo một biểu mẫu đơn giản trong C# Windows Forms và chạy vào một tình huống chung mà một điều khiển có thể thay đổi trạng thái của một điều khiển khác, nhưng cả hai điều khiển đều kích hoạt một số phương thức khác.Làm cách nào để bỏ qua các sự kiện đơn giản khi kích hoạt các trạng thái điều khiển trong C# Windows Forms?

Ví dụ: xem xét CheckboxNumericUpDown trong đó trạng thái hoặc giá trị của một trong hai kích thước sẽ kích hoạt thứ gì đó để vẽ lại. Các NumericUpDown là phụ thuộc vào Checkbox có nghĩa là nó có thể bị vô hiệu hóa hoặc bỏ qua, trừ khi Checkbox được chọn.

Tuy nhiên, thuận tiện cho người dùng thay đổi giá trị NumericUpDown và tự động kiểm tra Checkbox nếu chưa được.

Vì vậy, đây là những phương pháp trong câu hỏi:

private void chkState_CheckedChanged(object sender, EventArgs e) 
{ 
    RedrawStuff(); 
} 

private void numStateValue_ValueChanged(object sender, EventArgs e) 
{ 
    if (!chkState.Checked) 
     chkState.Checked = true; 
    RedrawStuff(); 
} 

Vấn đề tất nhiên, đó là thay đổi giá trị NumericUpDown gây RedrawStuff() để bắn hai lần.

workaround của tôi là để giới thiệu một boolean nơi tôi có hiệu quả có thể phủ nhận hành vi này, nhưng đôi khi nó có thể nhận được lộn xộn:

bool _preventStateChange; 

private void chkState_CheckedChanged(object sender, EventArgs e) 
{ 
    if (_preventStateChange) 
     return; 
    RedrawStuff(); 
} 

private void numStateValue_ValueChanged(object sender, EventArgs e) 
{ 
    _preventStateChange = true; 
    if (!chkState.Checked) 
     chkState.Checked = true; 
    RedrawStuff(); 
    _preventStateChange = false; 
} 

Đây có phải là cách tốt nhất để xử lý tình huống này?

+0

Tôi đã đơn giản hóa mã ví dụ; có lẽ 'RedrawStuff' là một sự lựa chọn kém. Trong trường hợp này nó liên quan đến việc truy vấn lại một cơ sở dữ liệu, thay đổi một vài databindings, và thay đổi một số trạng thái điều khiển và bảng điều khiển như các nhóm ẩn, vv – JYelton

+0

Tôi đã sử dụng cờ như vậy hàng chục lần, và đã không tìm thấy một thay thế tôi xem xét tốt hơn cho trường hợp chung. – xpda

+0

Hủy đăng ký khỏi các sự kiện bạn không muốn kích hoạt (trong trường hợp này là chkState_CheckedChanged) trong khoảng thời gian bạn không muốn chúng kích hoạt. – Tom

Trả lời

6

Đối với trường hợp tổng quát hơn, nếu bạn có mối quan hệ phức tạp giữa các điều khiển, bạn có thể kiểm tra quyền kiểm soát bắn sự kiện này bằng cách kiểm tra Focused tài sản riêng của mình:

private void chkState_CheckedChanged(object sender, EventArgs e) 
{ 
    if (chkState.Focused) 
     RedrawStuff(); 
} 

private void numStateValue_ValueChanged(object sender, EventArgs e) 
{ 
    if (!chkState.Checked) 
     chkState.Checked = true; 

    if (numStateValue.Focused) 
     RedrawStuff(); 
} 

Bằng cách này, mỗi đối tượng là chỉ phụ thuộc vào chính nó.

Theo như tôi biết, đối tượng phải tập trung để kích hoạt sự kiện của người dùng và chỉ có thể có một đối tượng có tiêu điểm tại bất kỳ thời điểm đã định nào. Tuy nhiên, tôi không chắc chắn nó sẽ làm việc trong mọi trường hợp vì vậy điều này vẫn cần thử nghiệm.

+0

Tôi tin rằng bạn có thể lập trình gây ra sự kiểm soát để kích hoạt. Nếu bạn thay đổi văn bản của hộp văn bản từ bên trong trình xử lý đã chọn, ví dụ, tiêu điểm sẽ vẫn còn trên hộp kiểm khi TextChanged được kích hoạt. – xpda

+1

Đó chính là điểm; nếu sự kiện được kích hoạt từ mã, chúng tôi không muốn xử lý nó. Tôi cho rằng nó sẽ chỉ nhận được tiêu điểm khi người dùng kích hoạt sự kiện từ giao diện người dùng. Tuy nhiên khi tôi nghi ngờ điều này không phải lúc nào cũng hoạt động - tôi đã chạy thử nghiệm và khi "nhấp vào" một nút bằng phím tắt, nó sẽ không lấy nét. Hầu hết các sự kiện chuột và bàn phím khác gây ra tiêu điểm (ví dụ: khi kiểm tra hộp kiểm bằng cách sử dụng phím tắt, nó sẽ lấy tiêu điểm). –

+0

@Yanir: Đây là một giải pháp rất tốt, và như bạn chỉ ra có một số vấn đề tiềm năng với các phím tắt và các tình huống trong đó tiêu điểm không nằm trên sự kiểm soát được thay đổi bởi người dùng. Thực hiện với những cạm bẫy trong tâm trí, nó là khá hữu ích. – JYelton

1

Chỉ cần di chuyển RedrawStuff(); đến một mệnh đề khác. Bằng cách này, nó được gọi trong cả hai tình huống, nhưng chỉ một lần.

private void chkState_CheckedChanged(object sender, EventArgs e) 
{ 
    RedrawStuff(); 
} 

private void numStateValue_ValueChanged(object sender, EventArgs e) 
{ 
    if (!chkState.Checked) 
     chkState.Checked = true; 
    else 
     RedrawStuff(); 
} 
+1

Điều này rất đơn giản và hoạt động tốt, nhưng có thể phức tạp khi có nhiều điều khiển tương tác. – JYelton

1

Bạn có thể "bỏ dây" các sự kiện thay đổi ở đầu phương thức "RedrawStuff" và nối lại chúng ở cuối.

private void RedrawStuff() { // un-wire the change events chkState.CheckedChanged -= new System.EventHandler(chkState_CheckedChanged); numStateValue.ValueChanged -= new System.EventHandler(chkState_CheckedChanged);

/* .... do you thing...including setting the state of both/either controls based on the state of things, without fear of triggering recursive changes... */ // wire them back up chkState.CheckedChanged += new System.EventHandler(chkState_CheckedChanged); numStateValue.ValueChanged += new System.EventHandler(chkState_CheckedChanged);

}

(Tôi đã sử dụng phương pháp này một vài lần vì nó dường như để đạt được một giải pháp cho vấn đề bạn đã mô tả, nhưng tôi sẽ rất vui nếu ai đó đã chỉ ra lý do tại sao, vì lý do tôi có thể không hiểu, rằng nó có thể là một cách tiếp cận xấu)

+0

Tôi cũng đã làm điều này trước đây. Dường như nó hoạt động tốt, nhưng thỉnh thoảng tôi có các vấn đề về thời gian kỳ lạ khi đăng ký sự kiện (un) dường như không có hiệu lực chính xác khi được mong đợi. – JYelton

1

tôi nghĩ rằng CheckedChanged trên CheckBox không cháy, nếu kiểm soát bị vô hiệu hóa, vì vậy làm điều này:.

private void numStateValue_ValueChanged(object sender, EventArgs e) 
{  
    if (!chkState.Checked)  
    { 
     chkState.Enabled = false; 
     chkState.Checked = true;  
     chkState.Enabled = true; 
    } 
    RedrawStuff(); 
} 

Nếu tôi đang sai, hãy bỏ phiếu xuống.

+0

Thật không may điều này đã không làm việc trong các thử nghiệm của tôi; hộp kiểm đã tắt vẫn kích hoạt sự kiện CheckedChanged. Có thể một người kiểm soát tàn tật đã kích hoạt một số sự kiện nhất định nhưng không phải là những sự kiện khác? – JYelton

+0

Một lời giải thích có khả năng hơn là tôi bị điên. – MusiGenesis

+0

Không hề, bạn đã cung cấp nhiều câu trả lời (có thể không trực tiếp) đã giúp tôi. Có lẽ bạn có thể thay đổi câu trả lời này cho upvotes và cookie. Hoặc ít nhất là upvotes! – JYelton

Các vấn đề liên quan