書名:WPF專業(yè)編程指南
作者:李應(yīng)保
出版社:電子工業(yè)出版社
出版時(shí)間:2010-01
ISBN:9787121100116
數(shù)據(jù)綁定
一、在數(shù)據(jù)綁定中加入校驗(yàn)
幾乎所有人機(jī)界面都要對(duì)用戶輸入進(jìn)行校驗(yàn),否則,一些無(wú)效的輸入就會(huì)進(jìn)入系統(tǒng)。當(dāng)我們使用數(shù)據(jù)綁定后,數(shù)據(jù)就在目標(biāo)對(duì)象和源對(duì)象間自動(dòng)傳遞。我們希望在數(shù)據(jù)開始傳遞之前能對(duì)數(shù)據(jù)進(jìn)行校驗(yàn),若用戶的輸入為無(wú)效輸入,就可以通知用戶該操作是無(wú)效的。
例如,銀行的客戶存取款程序。在客戶輸入賬號(hào)時(shí),需要校驗(yàn)賬號(hào)的格式是否正確,比如說(shuō),賬號(hào)只能是整數(shù),而且第一位不能是0;還要詢問數(shù)據(jù)庫(kù),這個(gè)賬號(hào)是否存在。在用戶取款時(shí),要保證用戶不能透支等。
過去,程序員根據(jù)自己的情況,開發(fā)出各種各樣的校驗(yàn)程序,這些校驗(yàn)程序可以在不同的層次上出現(xiàn)。WPF的數(shù)據(jù)綁定提供了一個(gè)標(biāo)準(zhǔn)的解決方案,其思路和類型轉(zhuǎn)換一樣,即在數(shù)據(jù)綁定中允許用戶插入一定的業(yè)務(wù)規(guī)則。
1、 開發(fā)業(yè)務(wù)規(guī)則類
- 下面通過一個(gè)例子來(lái)說(shuō)明如何在數(shù)據(jù)綁定中插入業(yè)務(wù)規(guī)則。首先,從簡(jiǎn)單的銀行賬戶類開始:
namespace Yingbao.Chapter11.BindingWithBusinessRules
{
using System;
using System.Collections.Generic;
using System.Text;
public class Account
{
string accountNumber;
double totalAmount;
public double TotalAmount
{
get { return this.totalAmount; }
set { this.totalAmount = value; }
}
public double Deposit
{
set { this.totalAmount += value; }
}
public double WithDraw
{
set { this.totalAmount -= value; }
}
public string AccountNumber
{
get { return this.accountNumber; }
set { this.accountNumber = value; }
}
public Account()
{
}
public Account(double amount)
{
this.totalAmount = amount;
}
}
}
- 類Account包括用戶的賬號(hào)和賬號(hào)里結(jié)余的錢款,定義了AccountNumber(賬號(hào))、TotalAmount(現(xiàn)有的存款余額)、Deposit(存款)和WithDraw(取款)這幾個(gè)屬性,Account用于存儲(chǔ)用戶的賬戶信息。
我們要把這個(gè)類綁定到用戶界面元素上,在用戶輸入賬號(hào)時(shí),要確保用戶輸入的賬號(hào)是正確的賬號(hào)。
在實(shí)際應(yīng)用程序中,還要用戶輸入密碼等安全信息,這里為簡(jiǎn)單起見,我們只校驗(yàn)用戶賬戶,其道理是一樣的。
為此,我們需要寫一個(gè)校驗(yàn)賬號(hào)的類AccountNumberRule:
namespace Yingbao.Chapter11.BindingWithBusinessRules
{
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Controls;
public class AccountNumberRule : ValidationRule
{
List<string> accountList = new List<string>();
public AccountNumberRule()
{
accountList.Add("1234567890");
accountList.Add("2234567890");
accountList.Add("3234567890");
accountList.Add("4234567890");
}
public override ValidationResult Validate(object value,
System.Globalization.CultureInfo cultureInfo)
{
string accountNumber =
value.ToString().TrimStart(' ').TrimEnd(' ') ;
bool existAccount = false;
foreach( string account in this.accountList )
{
if( account.Equals( accountNumber ) )
{
existAccount= true;
break;
}
}
if( !existAccount )
{
return new ValidationResult(false,"輸入的賬號(hào)錯(cuò)誤!");
}
return ValidationResult.ValidResult;
}
}
}
為了把AccountNumberRule用在Binding類中,AccountNumberRule需要從ValidationRule類中派生出來(lái),ValidationRule類位于System.Windows.Controls命名空間。
在具體的業(yè)務(wù)規(guī)則類中,需要覆蓋基類中的Validate方法。
在這個(gè)方法中,對(duì)用戶輸入的賬號(hào)和預(yù)先設(shè)定好的4個(gè)賬號(hào)進(jìn)行比較(在實(shí)際應(yīng)用程序中,應(yīng)該詢問數(shù)據(jù)庫(kù)用戶輸入的賬戶是否存在),看看用戶輸入的賬號(hào)是否在這幾個(gè)賬號(hào)中。若用戶輸入的賬號(hào)在這四個(gè)賬號(hào)中,返回ValidationResult.ValidResult;否則返回ValidationResult( false, “輸入賬號(hào)錯(cuò)誤!”)。
ValidationResult類中有三個(gè)屬性:ValidResult表示校驗(yàn)結(jié)果為有效;IsValid屬性為布爾類型,當(dāng)其值為false時(shí),表示用戶輸入的值是無(wú)效的;ErrorContent屬性表示具體的錯(cuò)誤,通常是錯(cuò)誤信息。
認(rèn)為微軟應(yīng)該把ValidResult和IsValid這兩個(gè)屬性合為一個(gè)屬性,并使用枚舉類型,這個(gè)枚舉類型應(yīng)該包括“嚴(yán)重錯(cuò)誤”、“警告錯(cuò)誤”、“提示信息”和“結(jié)果有效”等值。而目前的移植,IsValid為true時(shí),與ValidResult表示的是一個(gè)意思。為了強(qiáng)調(diào)用戶輸入的賬號(hào)為以1到9數(shù)字開頭的數(shù)字,寫了NumericRule類。
這個(gè)類同樣是從ValidationRule類中派生出來(lái),可用正則表達(dá)式(Regular Expression)對(duì)用戶輸入的賬號(hào)進(jìn)行校驗(yàn)。
也可以把NumericRule和Account-Number合為一個(gè)類,這么做是為了演示XAML組合多個(gè)業(yè)務(wù)規(guī)則的能力。
namespace Yingbao.Chapter11.BindingWithBusinessRules
{
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Controls;
class NumericRule: ValidationRule
{
string numericEx = "^([1-9]([0-9]+))$";
public override ValidationResult Validate(object value,
System.Globalization.CultureInfo cultureInfo)
{
Regex rg = new Regex(numericEx);
if( !rg.IsMatch( value.ToString() ) )
{
return new ValidationResult(false,
"輸入的字符中含有非數(shù)字鍵!");
}
return ValidationResult.ValidResult;
}
}
}
- 最后一個(gè)規(guī)則是用來(lái)對(duì)用戶取款進(jìn)行校驗(yàn)的。WithDrawRule用來(lái)強(qiáng)制兩個(gè)規(guī)則:
● 用戶必須輸入有效的浮點(diǎn)數(shù);
● 用戶不能透支。
namespace Yingbao.Chapter11.BindingWithBusinessRules
{
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Controls;
public class WithDrawRule : ValidationRule
{
double accountBalance;
public double AccountBalance
{
get { return this.accountBalance; }
set { this.accountBalance = value; }
}
public WithDrawRule()
{
}
public override ValidationResult Validate(object value,
System.Globalization.CultureInfo
cultureInfo)
{
double amount = 0;
if (!Double.TryParse(value.ToString(), out amount))
{
return new ValidationResult(false, "輸入無(wú)效字符!");
}
if (amount > this.accountBalance)
{
return new ValidationResult(false, "你無(wú)權(quán)透支!");
}
return ValidationResult.ValidResult;
}
}
}