2010-08-01 85 views
9

我想擴展as​​p.net驗證器,以便我可以使一個驗證器依賴於另一個驗證器。我的情況是,我們必須在文本框中驗證日期。通常,我只是使用RequiredFieldValidator(確保提供日期),CompareValidator(確保日期是日期)和最後一個RangeValidator(確保日期在所需限制內)的組合。擴展ASP.NET驗證器

這樣做的問題是驗證程序不相互依賴,因此,當我們真正希望他們看到的所有消息都是最相關的消息時,用戶會立即看到每個驗證程序的所有三條消息,即如果他們在日期文本框中輸入「abc」,那麼向他們顯示消息說日期不在有效範圍內(儘管技術上我認爲這是真的)是不合適的。

當前爲了提供這種功能,我們使用CustomValidator,並將所有三個驗證放在服務器驗證事件處理程序中,並根據驗證失敗以編程方式更改錯誤消息。

我想將這個標準化多一點,因爲它在這個應用程序中發生了很多,我想我是否可以使驗證器相互依賴,這將解決問題,並且還允許我們使用客戶端而不必進行回發,特別是處理自定義驗證。

這個想法是,如果一個驗證器依賴另一個,如果該「主」是有效的,那麼依賴將執行其正常驗證(EvaluateIsValid()),否則如果主驗證器無效,則其他依賴驗證器將有效。

我已經通過繼承已經在框架中提供的各種驗證器控件提出了以下解決方案。

public class RequiredFieldDependentValidator : RequiredFieldValidator 
{ 
    [Description("The validation control to depend on for determining if validation should occur")] 
    public string ValidationControlToDependOn 
    { 
     get 
     { 
      object obj = ViewState["ValidationControlToDependOn"]; 
      if (obj != null) return (string) obj; 
      return null; 
     } 
     set 
     { 
      Control control = FindControl(value); 
      if (control is IValidator) 
       ViewState["ValidationControlToDependOn"] = value; 
      else 
       throw new HttpException("ValidationControlToDependOn is not a validation control"); 
     } 
    } 

    protected override bool EvaluateIsValid() 
    { 
     IValidator validationControlToDependOn = FindControl(ValidationControlToDependOn) as IValidator; 

     if(validationControlToDependOn != null) 
     { 
      return !validationControlToDependOn.IsValid || base.EvaluateIsValid(); 
     } 

     return base.EvaluateIsValid(); 
    } 

目前我剛剛編碼它的RequiredFieldValidator的,最好我想所有的驗證都提供了這種功能,但我看不到的方式來做到這一點而不復制上面的代碼到每個類似的類驗證器的個人類型我想提供此功能,因此如果有任何問題,我將不得不返回並單獨更改每個驗證器類型上的此代碼。

有沒有一種方法可以「集中」這段代碼,並且可以很容易地在驗證器中使用它,而無需從頭開始編寫整個驗證器,以便我可以更改它們繼承的類。

乾杯,

回答

0

你可能想看看WebControlAdapter。

基本上可以讓你重寫webcontrols的某些方法(如果需要,有條件地適用於某些瀏覽器,但這裏可以適用於所有方面)。

在你的情況,你會想重寫EvaluateIsValid方法,並檢查控件是否有任何依賴於'父'驗證程序。

作爲示例,我們最近創建了一個TextBox適配器,用於爲控件呈現'maxlength'屬性。

Public Class TextBoxAdapter 
     Inherits WebControlAdapter 

     Private ReadOnly Property TextBoxControl() As TextBox 
      Get 
       Return DirectCast(MyBase.Control, TextBox) 
      End Get 
     End Property 

     Protected Overrides Sub RenderBeginTag(ByVal writer As System.Web.UI.HtmlTextWriter) 
      If TextBoxControl.TextMode = TextBoxMode.MultiLine AndAlso TextBoxControl.MaxLength > 0 Then 
       writer.AddAttribute("maxlength", TextBoxControl.MaxLength.ToString) 
      End If 

      MyBase.RenderBeginTag(writer) 
     End Sub 
    End Class 

要使用它,只需在您的App_Browsers文件目錄,並設置適配器有創建一個.browser文件:

<browsers> 
    <browser refID="Default"> 
     <controlAdapters> 
      <adapter controlType="System.Web.UI.WebControls.TextBox" 
       adapterType="TextBoxAdapter" /> 
     </controlAdapters> 
    </browser> 
</browsers> 

唯一的併發症,仍停留在你的情況是如何存儲相關的驗證以便EvaluateIsValid有權訪問此目錄。你可以考慮一個非呈現控件,比如Onof建議的或者Viewstate/Cookie /其他存儲機制。

1

您可以覆蓋您的頁面庫中的Validate方法。在頁面中添加驗證依賴信息,你可以實現一個沒有渲染控制:

<my:ValidationDependency TargetControl="RegExp1" Dependency="Required1" /> 
0

你可以有ValidationControlToDependOn物業類型列表,並添加驗證到列表中。所以我們可以假設稍後添加的驗證器取決於之前添加的驗證器。

所以你protected override bool EvaluateIsValid()

將改變有些

foreach(IValidator validator in ValidationControlToDependOn) 
{ 
return !validator.IsValid; 

} 
+0

不會讓每個驗證器在頁面上依賴於前一個? 我想我仍然需要繼承我試過的每個驗證器 – 2010-08-01 07:25:54

0

我尋找到這似乎是它可能是有前途的控制擴展,但我無法找到做什麼,但AJAX的東西與它的許多例子。

+0

,但是你不能覆蓋擴展控件的方法。 IMO避免子類化的唯一方法是重寫Page.Validate()。 – onof 2010-08-01 09:32:01