2013-04-10 38 views
11

Đây là một câu hỏi C#. Tôi có một hộp văn bản với trình xử lý sự kiện xác thực để xác thực nội dung của hộp văn bản với cụm từ thông dụng.Đóng biểu mẫu cửa sổ C# bằng cách tránh xác thực hộp văn bản

Sau khi xác thực, nếu giá trị đã nhập không đúng, tôi đang hiển thị hộp thư và tôi đang hủy sự kiện để con trỏ chuột di chuyển trở lại hộp văn bản có giá trị không đúng.

Điều này có hiệu quả khi tôi chuyển từ hộp văn bản đó sang các nút/hộp văn bản khác.

Nhưng khi tôi nhập giá trị không đúng và đóng biểu mẫu (với nút đóng ở góc trên cùng bên phải), nó xác nhận nội dung hộp văn bản và ném hộp thư và biểu mẫu không gần như tôi đang tạo sự kiện.

Vấn đề là, khi tôi nhấp vào nút X ở góc trên bên phải của biểu mẫu, tôi không muốn xác thực được kích hoạt vì tôi vẫn đóng biểu mẫu. Tôi có thể làm cái này như thế nào?

Tôi sẽ đăng đoạn mã càng sớm càng tốt.

+0

Có lẽ câu trả lời này: http://stackoverflow.com/a/25479010/1586914 có thể giúp ích? – Adiono

Trả lời

2
private void Form1_FormClosing(object sender, FormClosingEventArgs e) { 
    // Assume that X has been clicked and act accordingly. 
} 

Tạo sự kiện đóng, sau đó chỉ cần hủy trình xác thực của bạn.

+0

Tôi quên đề cập đến khung .net. Tôi đang sử dụng .Net Framework 1.1. FormClosingEventArgs không có trong đó. –

15

Để sử dụng xác nhận xử lý như 'txtIPAddress_Validating()' xử lý bên dưới khi có thể đóng biểu mẫu mà không phải nhập các mục hợp lệ để làm như vậy, tôi thực hiện như sau:

1) Trình xử lý bắt buộc xác nhận hợp lệ: Từ các thuộc tính điều khiển của điều khiển mà bạn muốn kích hoạt xác thực, nhấp đúp vào sự kiện 'Đang xác thực' từ danh sách sự kiện kiểm soát này. Danh sách sự kiện kiểm soát được truy cập bằng cách nhấp vào nút thanh công cụ sự kiện của trang thuộc tính (sét tìm kiếm) của bảng điều khiển này. Sau đó, bạn có thể nhập mã trong trình xử lý được tạo tự động với tên kết hợp cả tên của điều khiển và '_Validating'. Một phần của trình xử lý này, nơi một cái gì đó được thiết lập là không hợp lệ có thể ép buộc các mục hợp lệ bằng cách thêm lệnh 'e.Cancel = true'.

Ví dụ về phương pháp xác thực như vậy, hãy xem mã 'txtIPAddress_Validating()' và 'txtMaskBits_Validating()' bên dưới. Không bị phân tâm bởi cơ chế xác thực hoàn chỉnh của các ví dụ cụ thể này. Tất cả những gì bạn cần xem và tái tạo trong mã của riêng bạn để bắt buộc xác nhận là thêm lệnh 'e.Cancel = true' vào đúng vị trí của phương thức xác thực của riêng bạn. Đó là khi giá trị được xác định là không hợp lệ. Tại thời điểm này việc xác nhận sẽ hoạt động tốt nhưng bất kỳ nỗ lực nào để đóng biểu mẫu sẽ kích hoạt xác thực sẽ dừng và nhấn mạnh các giá trị hợp lệ trước khi có thể đóng biểu mẫu. Đây không phải lúc nào bạn muốn. Khi nó không phải như vậy, tôi tiếp tục với những điều sau đây.

2) 'Hủy' nút đó cũng hủy bỏ (disable) tất cả các kiểm chứng thực:

a) Đặt một nút 'Cancel' thường xuyên trên các hình thức đó là liên kết đến một phương pháp như 'btnCancel_Click()' phương pháp phía dưới.

b) Trước thông thường 'this.close();' hướng dẫn, thêm 'AutoValidate = AutoValidate.Disable;' chỉ dẫn. Lệnh này vô hiệu hóa tất cả các trình kích hoạt 'xác thực'. Lưu ý rằng sự kiện 'btnCancel_Click' được kích hoạt trước khi thực hiện bất kỳ xác thực nào. Đó không phải là như vậy cho các sự kiện Form Closing mà tất cả sẽ thực hiện sau khi xác nhận các sự kiện. Đó là lý do tại sao không thể vô hiệu hóa việc xác nhận hợp lệ từ bất kỳ sự kiện nào trong các biểu mẫu này.

c) Để nút 'Hủy' này hoạt động chính xác, bạn cũng cần đặt thuộc tính 'Nguyên nhân xác thực' của nút 'Hủy' này thành 'sai'. Điều này là cần thiết, nếu không nhấp vào nút này sẽ kích hoạt xác thực trước khi xác thực có thể bị vô hiệu hóa bởi 'AutoValidate = AutoValidate.Disable' ở trên; chỉ dẫn.

Tại thời điểm này, bạn có thể thoát bằng cách nhấp vào nút 'Hủy' mà không phải nhập các giá trị hợp lệ trước tiên. Tuy nhiên, việc nhấp vào nút "X" phía trên bên phải của cửa sổ biểu mẫu sẽ vẫn bắt buộc xác thực.

3) Thực hiện quyền nút trên "X" cũng hủy bỏ xác nhận:

Thách thức ở đây là cái bẫy như vậy "X" nhấp kiện trước khi xác nhận được thực thi. Bất kỳ nỗ lực nào để thực hiện điều đó thông qua trình xử lý Biểu mẫu đóng sẽ không hoạt động vì nó quá muộn sau khi thực hiện đạt được trình xử lý đó. Tuy nhiên, nhấn nút "X" có thể được chụp nhanh bằng cách ghi đè phương thức WndProc() và kiểm tra điều kiện 'm.Msg == 0x10'. Khi điều kiện đó là đúng, 'AutoValidate = AutoValidate.Disable được giới thiệu trước đây' hướng dẫn một lần nữa có thể được sử dụng để vô hiệu hóa xác nhận tổng thể trong trường hợp đó là tốt. Xem phương thức WndProc() bên dưới để biết mẫu mã của phương thức đó. Bạn sẽ có thể sao chép và dán phương thức đó như trong lớp của biểu mẫu của bạn.

Tại thời điểm này, cả nút 'Hủy' một "X" sẽ hủy bỏ các giá trị. Tuy nhiên, phím thoát có thể được sử dụng để đóng một biểu mẫu thì không. Phím thoát như vậy được kích hoạt khi thuộc tính 'CancelButton' của biểu mẫu được sử dụng để liên kết khóa thoát này với nút 'Hủy' của biểu mẫu.

4) Tận dụng phím Esc cũng hủy bỏ xác nhận:

Tương tự như nút "X", chìa khóa thoát có thể được chụp bằng cách ghi đè một existingmethod. Đó là phương thức ProcessDialogKey(). Một lần nữa, 'AutoValidate = AutoValidate.Disable được giới thiệu trước đây' hướng dẫn có thể được sử dụng để vô hiệu hóa xác nhận tổng thể cho phím thoát là tốt. Xem phương thức ghi đè ‘ProcessDialogKey()’ trong mã bên dưới để xem cách thực hiện điều này. Ở đây một lần nữa, bạn sẽ có thể sao chép và dán phương thức đó như trong lớp của biểu mẫu của riêng bạn.

Tại thời điểm này, bạn nên làm!

cân nhắc thêm:

Nó là tốt để nhận thấy rằng hai cách khác sau đây để đóng cửa sổ cũng nên làm việc tốt vào thời điểm này. Hai cách này là:

  • Tùy chọn 'Đóng' của nút biểu tượng cửa sổ phía trên bên trái.
  • Nhấn Alt + F4 sẽ kích hoạt hành động đóng giống như tùy chọn 'Đóng' ở trên.

Hai cách đóng cửa sổ này cũng bắt đầu hủy xác thực khi bạn đã giới thiệu cơ chế chụp nút "X" được mô tả ở điểm 3 ở trên.

Điều đó là dành cho tôi cho đến thời điểm này. Hy vọng điều này sẽ giúp bạn!

mẫu mã của tôi dưới đây:

public partial class frmMyIP : Form 
{ 
    public frmMyIP() 
    { 
      InitializeComponent(); 
    } 

    // To capture the Upper right "X" click 
    protected override void WndProc(ref Message m) 
    { 
     if (m.Msg == 0x10) // The upper right "X" was clicked 
     { 
      AutoValidate = AutoValidate.Disable; //Deactivate all validations 
     } 
     base.WndProc(ref m); 
    } 

    // To capture the "Esc" key 
    protected override bool ProcessDialogKey(Keys keyData) 
    { 
     if (keyData == Keys.Escape) 
     { 
      AutoValidate = AutoValidate.Disable; 
      btnCancel.PerformClick(); 
      return true; 
     } 
     return base.ProcessDialogKey(keyData); 
    } 
    public bool IsValidIP(string ipaddr) 
    { 
     string pattern = @"^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"+ 
     @"(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$"; 

     Regex check = new Regex(pattern); 
     bool valid = false; 

     if (ipaddr == "") 
     { 
      valid = false; 
     } 
     else 
     { 
      valid = check.IsMatch(ipaddr, 0); 
     } 

     return valid; 
    } 

    private void txtIPAddress_Validating(object sender, CancelEventArgs e) 
    { 
     string address = txtIPAddress.Text; 
     if (!IsValidIP(address)) 
     { 
      MessageBox.Show("Invalid IP address!"); 
      e.Cancel = true; 
     } 
    } 

    private void cmbMaskBits_Validating(object sender, CancelEventArgs e) 
    { 
     int MaskBitsValue = Convert.ToInt32(cmbMaskBits.Text); 

     if (MaskBitsValue<1 || MaskBitsValue>30) 
     { 
     MessageBox.Show("Please select a 'Mask Bits' value between 1 and 30!"); 
     e.Cancel = true; 
     } 
    } 

    private void btnCancel_Click(object sender, EventArgs e) 
    { 
     // Stop the validation of any controls so the form can close. 
     // Note: The CausesValidation property of this <Cancel> button 
     //  must also be set to false. 

     AutoValidate = AutoValidate.Disable; 
     this.Close(); 
    } 
+0

Hoàn hảo! Cảm ơn! Đây sẽ là câu trả lời đúng. –

+0

Thanh lịch. Đơn giản và hoạt động như được quảng cáo. Cảm ơn!! –

+0

Đây là một câu trả lời nghiêm trọng quá mức và nó cũng cung cấp cho UX khủng khiếp (có thể * bạn * tưởng tượng phải bấm vào một nút trước khi có thể đóng một hình thức tất cả các thời gian). Trong thực tế, tất cả mọi người ở đây dường như nhảy qua hoops để có được điều này để làm việc. Câu trả lời là ** thực sự ** đơn giản, xem của tôi. – MarioDS

2

Chèn sau như dòng đầu tiên trong trường hợp xác nhận của hộp văn bản:

//Allow the form to be closed 
if (this.ActiveControl.Equals(sender)) 
    return; 

Kể từ khi sự kiện chặt chẽ của các mẫu được kích hoạt xác nhận và từ (ít nhất là ít nhất) là sự kiện biểu mẫu duy nhất có thể kích hoạt xác thực, chúng ta có thể giả định rằng bất kỳ sự kiện biểu mẫu nào kích hoạt xác thực là sự kiện đóng.

1

gì bạn cần là một thực hiện như một mô tả dưới đây, nơi nó được giả định rằng bạn có một nút Lưu và một nút Hủy bỏ đối với hình thức:

public Form1() 
    { 
     // Disable validation in constructor 
     textBox.CausesValidation = false; 
    } 

    private void OnSaveClicked(object sender, EventArgs e) 
    { 
     textBox.CausesValidation = true; 
     if (ValidateChildren()) 
     { 
      // 
      // Do saving of the form data or other processing here .... 
      // 
      Close(); 
     } 
     // 
     // Set validation to false, as user may press Cancel next 
     // 
     textBox.CausesValidation = false; 
    } 

    private void OnCancelClicked(object sender, EventArgs e) 
    { 
     Close(); 
    } 
0

Kiểm tra mà nút đã tập trung vào việc kiểm tra xác nhận . Nếu nút hủy (và trong trường hợp của tôi là một nút rõ ràng), hãy ghi đè lên. Đây là một phương thức bên trong mà tôi gọi từ trình xử lý sự kiện xác thực ô của tôi. (Chỉ cần nhận ra đó là một C# câu hỏi, nhưng bạn có thể dịch)

Private Sub validateCell(ByVal tagDesc As String, ByVal userInput As String, ByVal legalRegex As String, ByVal regexDesc As String, ByVal e As DataGridViewCellValidatingEventArgs) 
    Dim match As Match = Regex.Match(userInput, legalRegex) 
    Dim matches = match.Groups() 
    Dim val = match.Value 
    If val.Length = 0 Or userInput.Length > val.Length Then 
     tagGrid.Rows(e.RowIndex).ErrorText = _ 
      tagDesc & " must match pattern: " & regexDesc 
     If Me.Cancel_Button.Focused Or Me.clearButton.Focused Then 
      e.Cancel = False 
      tagGrid.Rows(e.RowIndex).ErrorText = "" 
     Else 
      e.Cancel = True 
      MsgBox(tagDesc & " must match pattern: " & regexDesc, MsgBoxStyle.Critical) 
     End If 
    Else 
     e.Cancel = False 
     tagGrid.Rows(e.RowIndex).ErrorText = "" 
    End If 
End Sub 
0

Tôi đến đây để tìm kiếm một phương pháp đơn giản để gây ra một hình thức để đóng khi một xử lý sự kiện Validating đặt ra một ngoại lệ, báo cáo nó, và nhu cầu để buộc đóng biểu mẫu. Sau khi đọc chủ đề này và nhiều chủ đề khác, tiếp theo là một buổi chiều thử nghiệm, tôi đã thực hiện một số khám phá và phát triển một bản hack đơn giản để buộc biểu mẫu phải đóng lại.

Thứ đầu tiên, mặc dù; Tôi phát hiện ra rằng khi một sự kiện Validating gọi this.Close() các FormClosingEventArgs.Cancel cờ truyền vào thủ tục sự kiện From_Closing của nó được thiết lập để TRUE, gây hiệu quả sự kiện để hủy bỏ bản thân. Ngược lại, sự kiện Đóng bình thường nhận được một lá cờ FormClosingEventArgs.Cancel được đặt thành FALSE.

Vì phương thức Đóng trên biểu mẫu không có đối số, không có cách trực tiếp nào để buộc vấn đề, làm tăng nhu cầu hack. Bài viết này thảo luận về một số hack như vậy, nhưng tôi nghĩ rằng tôi là đơn giản hơn nhiều để thực hiện.

Bản hack bắt đầu bằng biến Boolean cấp biểu mẫu đơn giản.

bool _fExceptionIsFatal = false; 

Ngoài việc xác định một Form_Closing xử lý sự kiện , đây là sự thay đổi về cơ cấu chỉ cần thiết để hình thành.

Sự kiện Form_Closing rất đơn giản.

private void From1_Closing (object sender , FormClosingEventArgs e) 
    { 
     if (this.CausesValidation) 
     { // There is no sense repeating this procedure if another routine already did it. 
      DisableValidation (); 
     } // if (this.CausesValidation)   

     if (_fExceptionIsFatal) 
     { // Cancel False == Allow form to close. 
      e.Cancel = false; 
     } // if (_fExceptionIsFatal) 
    } // From1_Closing 

Mặc dù DisableValidation được thực hiện như một phương pháp cục bộ của hình thức hiện tại, điều tương tự có thể được thực hiện bằng cách đi qua một Mẫu tham chiếu vào một thói quen thư viện, vì một Form là một mẫu, và điều khiển của nó bộ sưu tập là một bộ sưu tập Điều khiển, thời gian. Chẳng bao lâu nữa, tôi sẽ làm như vậy, cùng với việc thực hiện nghịch đảo của nó, để bật xác thực lại.

private void DisableValidation () 
    { 
     foreach (Control ctrl in this.Controls) 
     { 
      ctrl.CausesValidation = false; 
     } // foreach (Control ctrl in this.Controls) 

     this.CausesValidation = false; 
    } // DisableValidation 

Phần thứ tư của giải pháp cũng không kém phần đơn giản; bất cứ khi nào bạn muốn ép buộc biểu mẫu đóng, hãy đặt _intValueAsInteger thành TRUE trước khi bạn gọi this.Close.

0

Thêm mã bên dưới vào biểu mẫu của bạn. Bạn có thể đóng biểu mẫu ngay cả khi các điều khiển con đang xác thực.

protected override void WndProc(ref Message m) 
{ 
    if (m.Msg == 0x10) // The upper right "X" was clicked 
    { 
     this.ActiveControl = null; 
     this.AutoValidate = AutoValidate.Disable; 
    } 
    base.WndProc(ref m); 
} 
0

Câu trả lời thực tế là ridiculously đơn giản so với tất cả những gợi ý ở đây đó liên quan đến hack và mã thêm không cần thiết để undo một cái gì đó.

"Bí quyết" chỉ để cho phép trọng tâm thay đổi và không kích hoạt xác thực từ các nút trên chính biểu mẫu đó.

Bạn chỉ có thể thiết lập hai thuộc tính trên biểu mẫu:

MyForm.CausesValidation = false; 
MyForm.AutoValidate = AutoValidate.EnableAllowFocusChange; 

Et thì đấy, hình thức hoạt động bình thường khi bạn cố gắng để đóng nó lại và xác nhận vẫn hoạt động sau các đầu vào khác như tab thay đổi tập trung hoặc chuột nhấp chuột .

+0

Câu trả lời này không vô hiệu hóa trình xác thực cấp trường – pmartin

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