首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WPF 輸入驗證完全指南:結合異常、ValidationRule、IDataErrorInfo 與 BindingGroup 實現複雜業務規則

     編輯:關於.NET

WPF 擁有豐富的資料繫結與驗證體系,支援從簡單屬性驗證到複雜交叉屬性業務規則。本文系統整理三大核心驗證機制、BindingGroup 進階用法、自訂錯誤顯示樣板,並以現場技術人員活動回報實例完整示範。

三大核心驗證機制對比

機制觸發時機適用場景優點缺點
Exception (ValidatesOnExceptions) 屬性 Setter 擲出異常 / 型別轉換失敗 型別轉換守衛、不可變物件驗證 最簡單、自動捕獲轉換錯誤 異常控制流效能較差、難以表達複雜規則
ValidationRule Binding 管線中 (依 ValidationStep: RawProposedValue/ConvertedProposedValue/UpdatedValue/CommittedValue) 單一層性格式/模式驗證 (如 Regex、範圍) 可在 XAML 宣告、可攜帶參數、支援多規則鏈 無法存取其他屬性值 (跨屬性驗證無力)
IDataErrorInfo 來源屬性更新後、或 BindingGroup 提交時 跨屬性業務規則、整體物件驗證 可存取完整物件狀態、集中管理業務規則 索引器常形成巨大 switch、屬性名稱字串硬編碼、Setter 前不觸發

實例場景:技術人員活動回報表單

實體:Activity (Title, Description, ActivityDate, ActivityType, Inventory, Customer, Objective, Reason)

驗證規則:

  1. Title、Description 必填。
  2. ActivityDate 必須在今天 ±7 天內。
  3. ActivityType = Install 時,Inventory 必填且符合型號格式 (Regex)。
  4. Customer、Objective、Reason 至少填一項 (交叉屬性)。

機制組合實作

1. 型別轉換與基礎必填:Exception + ValidationRule

<TextBox Text="{Binding Activity.Title, ValidatesOnExceptions=True, UpdateSourceTrigger=PropertyChanged}" />
<TextBox>
  <TextBox.Text>
    <Binding Path="Activity.Inventory" ValidatesOnExceptions="True" UpdateSourceTrigger="PropertyChanged">
      <Binding.ValidationRules>
        <local:InventoryValidationRule InventoryPattern="^\D?(\d{3})\D?\D?(\d{3})\D?(\d{4})$" />
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>

InventoryValidationRule 繼承 ValidationRule,覆寫 Validate 以 Regex 驗證逗號分隔型號清單。

2. 跨屬性依賴:IDataErrorInfo + 手動觸發重驗證

ViewModel 實作 IDataErrorInfo:

public string this[string propertyName]
{
    get
    {
        switch (propertyName)
        {
            case "Inventory":
                if (ActivityType?.Name == "Install" && string.IsNullOrWhiteSpace(Inventory))
                    return "安裝類型必須填寫耗材清單";
                break;
            // ... 其他屬性驗證
        }
        return null;
    }
}

關鍵技巧:當 ActivityType 變更時,主動發送 PropertyChanged("Inventory") 強制 Inventory Binding 重新評估 IDataErrorInfo。

3. 多欄位互斥必填:BindingGroup

<Grid x:Name="CrossCoupledPropsGrid">
  <Grid.BindingGroup>
    <BindingGroup>
      <BindingGroup.ValidationRules>
        <local:CustomerObjectiveOrReasonValidationRule ValidationStep="UpdatedValue" ValidatesOnTargetUpdated="True" />
      </BindingGroup.ValidationRules>
    </BindingGroup>
  </Grid.BindingGroup>
  <!-- Customer ComboBox, Objective ComboBox, Reason TextBox -->
</Grid>

CustomerObjectiveOrReasonValidationRule.Validate 接收 BindingGroup,從 Items[0] 取得 ViewModel,檢查三欄位是否至少一個有值。各控件掛接 SelectionChanged/TextChanged 呼叫 BindingGroup.CommitEdit() 即時驗證。

自訂錯誤視覺呈現

ToolTip 顯示錯誤訊息

<Style TargetType="TextBox">
  <Style.Triggers>
    <Trigger Property="Validation.HasError" Value="True">
      <Setter Property="ToolTip">
        <Setter.Value>
          <Binding Path="(Validation.Errors).CurrentItem.ErrorContent" RelativeSource="{x:Static RelativeSource.Self}" />
        </Setter.Value>
      </Setter>
    </Trigger>
  </Style.Triggers>
</Style>

ErrorTemplate 取代預設紅框

<ControlTemplate x:Key="InputErrorTemplate">
  <DockPanel>
    <Ellipse DockPanel.Dock="Right" Width="10" Height="10" Margin="2,0" ToolTip="資料無效">
      <Ellipse.Fill><LinearGradientBrush><GradientStop Color="#11FF1111" Offset="0"/><GradientStop Color="#FFFF0000" Offset="1"/></LinearGradientBrush></Ellipse.Fill>
    </Ellipse>
    <AdornedElementPlaceholder />
  </DockPanel>
</ControlTemplate>

<Style TargetType="TextBox">
  <Setter Property="Validation.ErrorTemplate" Value="{StaticResource InputErrorTemplate}" />
</Style>

總結

實務專案中需組合多種機制:Exception 守衛型別轉換、ValidationRule 處理單欄格式、IDataErrorInfo 解決跨屬性業務邏輯、BindingGroup 處理多欄位整體約束。搭配 Validation.ErrorTemplate 與 ToolTip Style,打造專業級驗證體驗。完整範例碼:MSDN Code Gallery。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved