淺析WPF中Binding的數(shù)據(jù)校驗(yàn)和類型轉(zhuǎn)換
在WPF開發(fā)中,Binding實(shí)現(xiàn)了數(shù)據(jù)在Source和Target之間的傳遞和流通,就像現(xiàn)實(shí)生活中的一條條道路,建立起了城鎮(zhèn)與城鎮(zhèn)之間的銜接,而數(shù)據(jù)校驗(yàn)和類型轉(zhuǎn)換,就像高速公路之間的收費(fèi)站和安檢站。那在WPF開發(fā)中,如何實(shí)現(xiàn)數(shù)據(jù)的校驗(yàn)和類型轉(zhuǎn)換呢?本文以一個(gè)簡(jiǎn)單的小例子,簡(jiǎn)述在WPF開發(fā)中,實(shí)現(xiàn)數(shù)據(jù)校驗(yàn)和類型轉(zhuǎn)換的相關(guān)知識(shí)點(diǎn),僅供學(xué)習(xí)分享使用,如有不足之處,還請(qǐng)指正。
數(shù)據(jù)校驗(yàn)
在WPF開發(fā)中,校驗(yàn)數(shù)據(jù)的有效性,主要步驟如下:
1. 實(shí)現(xiàn)校驗(yàn)規(guī)則
Binding的ValidationRules是Collection<ValidationRule>類型,是一個(gè)校驗(yàn)規(guī)則列表,可以支持多重校驗(yàn)。而ValidationRule是一個(gè)抽象類,所有要實(shí)現(xiàn)業(yè)務(wù)規(guī)則校驗(yàn),就要繼承ValidationRule并實(shí)現(xiàn)抽象方法。
ValidationRule的Validate方法返回一個(gè)ValidationResult對(duì)象,如果校驗(yàn)通過(guò),則ValidationResult的IsValid為true,否則為false。RangeValidationRule主要校驗(yàn)用戶輸入數(shù)據(jù)的范圍:
using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Controls; namespace WpfApp4.DataValidate { public class RangeValidationRule : ValidationRule { public override ValidationResult Validate(object value, CultureInfo cultureInfo) { double d = 0; if(double.TryParse(value.ToString(),out d)) { if(d>=0 && d <= 100) { return new ValidationResult(true,null); } } return new ValidationResult(false, "數(shù)據(jù)必須在0~100之間"); } } }
2. 設(shè)置規(guī)則
要想應(yīng)用規(guī)則,首先需要引入規(guī)則對(duì)應(yīng)的命名空間:xmlns:v="clr-namespace:WpfApp4.DataValidate"
然后設(shè)置Binding的ValidationRules規(guī)則,如下所示:
<TextBlock Text="年齡" VerticalAlignment="Center"></TextBlock> <TextBox x:Name="tbAge" Width="120" Height="25" Margin="10" Validation.Error="tbAge_Error" VerticalContentAlignment="Center"> <TextBox.Text> <Binding Path="Age" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True"> <Binding.ValidationRules> <v:RangeValidationRule ValidatesOnTargetUpdated="True"></v:RangeValidationRule> </Binding.ValidationRules> </Binding> </TextBox.Text> </TextBox> <TextBlock VerticalAlignment="Center" Text="{Binding DataError}" Foreground="Red"></TextBlock>
關(guān)于校驗(yàn)規(guī)則,有以下幾點(diǎn)需要注意:
默認(rèn)情況下,認(rèn)為Source的數(shù)據(jù)總是正確的,規(guī)則校驗(yàn)只有當(dāng)Target更新時(shí),才會(huì)生效,因?yàn)門arget多為用戶輸入;如果當(dāng)Source更新時(shí)也要生效,則需要配置ValidatesOnTargetUpdated為true。
默認(rèn)情況下,校驗(yàn)規(guī)則返回的錯(cuò)誤信息,是不會(huì)輸出到UI的,如果要輸出要UI,需要設(shè)置NotifyOnValidationError屬性為true。
3. 輸出校驗(yàn)信息
默認(rèn)情況下,校驗(yàn)信息不會(huì)輸出到UI,只是顯示用戶控件為紅色邊框,如果要輸出校驗(yàn)信息,除了設(shè)置NotifyOnValidationError屬性外,還要訂閱Validation.Error事件,并在事件中處理要顯示的錯(cuò)誤信息,如下所示:
private void tbAge_Error(object sender, ValidationErrorEventArgs e) { this.viewModel.ValidationErrorCommand.Execute(e); }
其中上述方法中的命令為ViewModel中定義,如下所示:
public class MainWindowViewModel : ObservableObject { private int age; public int Age { get { return age; } set { SetProperty(ref age , value); } } private string dataError; public string DataError { get { return dataError; } set { SetProperty(ref dataError , value); } } private TextBox textBox; private ICommand winLoadedCommand; public ICommand WinLoadedCommand { get { if (winLoadedCommand == null) { winLoadedCommand = new RelayCommand<object>(WinLoaded); } return winLoadedCommand; } } private void WinLoaded(object sender) { if (sender != null) { var win = sender as MainWindow; this.textBox = win.tbAge; } } private ICommand validationErrorCommand; public ICommand ValidationErrorCommand { get { if (validationErrorCommand == null) { validationErrorCommand = new RelayCommand<object>(DisplayValidationError); } return validationErrorCommand; } } private void DisplayValidationError(object obj) { if (Validation.GetErrors(this.textBox).Count > 0) { this.DataError= Validation.GetErrors(this.textBox)[0].ErrorContent.ToString(); } else { this.DataError = string.Empty; } } }
4. 數(shù)據(jù)校驗(yàn)示例演示
經(jīng)過(guò)上述步驟,運(yùn)行程序,如下所示:
數(shù)據(jù)類型轉(zhuǎn)換
在數(shù)據(jù)綁定時(shí),如果Source端的數(shù)據(jù)類型和Target端的數(shù)據(jù)類型不一致時(shí),就需要用到數(shù)據(jù)類型轉(zhuǎn)換,如:true/false與顯示/隱藏之間的轉(zhuǎn)換等,要實(shí)現(xiàn)數(shù)據(jù)轉(zhuǎn)換,需要用到Binding的Converter屬性。步驟如下:
1. 定義轉(zhuǎn)換器
Binding的Converter屬性是IValueConverter類型,所以定義轉(zhuǎn)換器需要實(shí)現(xiàn)IValueConverter接口,如下所示:
namespace WpfApp4.DataConverter { public class BoolToVisilityConverter : IValueConverter { /// <summary> /// Source 到 Target /// </summary> /// <param name="value"></param> /// <param name="targetType"></param> /// <param name="parameter"></param> /// <param name="culture"></param> /// <returns></returns> public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var flag = bool.Parse(value.ToString()); if(flag) { return Visibility.Visible; } else { return Visibility.Collapsed; } } /// <summary> /// Target到Source /// </summary> /// <param name="value"></param> /// <param name="targetType"></param> /// <param name="parameter"></param> /// <param name="culture"></param> /// <returns></returns> public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { var visibility = Visibility.Collapsed; if (Enum.TryParse<Visibility>(value.ToString(), out visibility)) { if (visibility == Visibility.Collapsed) { return false; } else if(visibility == Visibility.Visible) { return true; } else { return false; } } return false; } } }
注意:IValueConverter接口共兩個(gè)方法,其中Convert方法當(dāng)Source到Target時(shí)調(diào)用,ConvertBack方法則是反方向調(diào)用。
2. 定義資源
轉(zhuǎn)換器也是一種資源,要聲明資源,首先引入命名空間xmlns:c="clr-namespace:WpfApp4.DataConverter",如下所示:
<Window.Resources> <c:BoolToVisilityConverter x:Key="boolToVisility"></c:BoolToVisilityConverter> </Window.Resources>
3. 調(diào)用類型轉(zhuǎn)換
在Binding時(shí),調(diào)用資源Visibility="{Binding ElementName=chk01, Path=IsChecked, Converter={StaticResource boolToVisility}}"。通過(guò)復(fù)選框的選擇與否,控制控件的顯示與隱藏,如下所示:
<StackPanel Orientation="Horizontal" Grid.Row="0"> <CheckBox Content="顯示" x:Name="chk01"></CheckBox> </StackPanel> <StackPanel Orientation="Horizontal" Grid.Row="1" Visibility="{Binding ElementName=chk01, Path=IsChecked, Converter={StaticResource boolToVisility}}"> <TextBlock Text="年齡" VerticalAlignment="Center"></TextBlock> <TextBox x:Name="tbAge" Width="120" Height="25" Margin="10" Validation.Error="tbAge_Error" VerticalContentAlignment="Center"> <TextBox.Text> <Binding Path="Age" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True"> <Binding.ValidationRules> <v:RangeValidationRule ValidatesOnTargetUpdated="True"></v:RangeValidationRule> </Binding.ValidationRules> </Binding> </TextBox.Text> </TextBox> <TextBlock VerticalAlignment="Center" Text="{Binding DataError}" Foreground="Red"></TextBlock> </StackPanel>
4. 數(shù)據(jù)類型轉(zhuǎn)換示例演示
到此這篇關(guān)于淺析WPF中Binding的數(shù)據(jù)校驗(yàn)和類型轉(zhuǎn)換的文章就介紹到這了,更多相關(guān)WPF Binding內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
.Net(c#)漢字和Unicode編碼互相轉(zhuǎn)換實(shí)例
下面小編就為大家?guī)?lái)一篇.Net(c#)漢字和Unicode編碼互相轉(zhuǎn)換實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02c# Selenium爬取數(shù)據(jù)時(shí)防止webdriver封爬蟲的方法
這篇文章主要介紹了c# Selenium爬取數(shù)據(jù)時(shí)防止webdriver封爬蟲的方法,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2021-01-01winform用datagridview制作課程表實(shí)例
這篇文章主要介紹了winform用datagridview制作課程表的方法,實(shí)例分析了WinForm實(shí)現(xiàn)課程表的結(jié)構(gòu)、數(shù)據(jù)庫(kù)及調(diào)用技巧,需要的朋友可以參考下2015-01-01.NET中實(shí)現(xiàn)彩色光標(biāo)、動(dòng)畫光標(biāo)及自定義光標(biāo)的方法
這篇文章主要介紹了.NET中實(shí)現(xiàn)彩色光標(biāo)、動(dòng)畫光標(biāo)及自定義光標(biāo)的方法,非常實(shí)用的功能,需要的朋友可以參考下2014-08-08C#實(shí)現(xiàn)路由器斷開連接,更改公網(wǎng)ip的實(shí)例代碼
C#實(shí)現(xiàn)路由器斷開連接,更改公網(wǎng)ip的實(shí)例代碼,需要的朋友可以參考一下2013-05-05C#中的異常處理問(wèn)題try catch finally
這篇文章主要介紹了C#中的異常處理問(wèn)題try catch finally,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11