سنرى في هذا المقال كيف يمكننا التحقق من البيانات واستكشاف الأخطاء فيها حيث توجد ثلاث خطوات أساسية لإظهار رسائل التحقق
في البداية يجب على الغرض Object الذي يحمل البيانات في النموذج أن يحقق الواجهة IDataErrorInfo وإن كنت تستخدم DataSets فهي تقوم بذلك من أجلك عندها يمكننا كتابة أكواد التحقق من البيانات وإظهار رسائل الأخطاء اعتمادا على حاجة المشروع الذي نقوم بتنفيذه. والأمر الثاني الذي يجب علينا عمله هو ضبط الـ Binding الخاص بالتحكمات بأننا نريد اظهار اخبار مرئي عندما يفشل التحقق ونقوم بذلك بضبط الخاصية ValidatesOnDataErrors وفي الوضع الافتراضي يحيط WPF التحكم بإطار أحمر ولكنه لا يظهر أية رسالة والمرحلة الأخيرة هي ضبط Validation.ErrorTemplate للتحكم كي نتمكن من إظهار الرسائل على التحكمات وجعلها تبدو تماما كما نريد
أنشئ مشروعا جديدا من النوع WPF Application وسمه WPFDataValidation ويتوجب عليك استخدام قاعدة البيانات المرفقة مع القسم الأول من سلسة المواضيع حيث سنقوم بكتابة كود للتحقق من أن الحقل LastName في الجدول Customer غير فارغ قبل الحفظ
من قائمة Data اختر الأمر Add New Data Source لإضافة DataSet للمشروع باختيار الجدول Customer وسمها CustomerDataSet
افتح CustomerDataSet وانقر بزر الفأرة اليميني على الجدول Customer ثم اختر الأمر View Code ليرينا Partial Class Code
في كود الفئة الجزئية CustomerDataTable أضف الدالة التالية للتحقق من أن LastName غير فارغ
Private Sub CheckLastName(ByVal row As CustomerRow)
If row.IsNull("LastName") OrElse row.LastName = "" Then
row.SetColumnError(Me.LastNameColumn, "Please eneter a last name")
Else
row.SetColumnError(Me.LastNameColumn, "")
End If
End Subأضف إجراء معالجة الحدث Column Changed لـ CustomerDataTable من أجل التحقق من قيمة LastName واجعل كوده يبدو كما يلي
Private Sub CustomerDataTable_ColumnChanged(ByVal sender As Object, _ ByVal e As System.Data.DataColumnChangeEventArgs) _ Handles Me.ColumnChanged If e.Column Is LastNameColumn Then Me.CheckLastName(CType(e.Row, CustomerRow)) End If End Sub
ثم أضف إجراء لمعالجة الحدث TableNewRow لـ CustomerDataTable وسيكون كوده كما يلي
Private Sub CustomerDataTable_TableNewRow(ByVal sender As Object, _ ByVal e As System.Data.DataTableNewRowEventArgs) _ Handles Me.TableNewRow Me.CheckLastName(CType(e.Row, CustomerRow)) End Sub
عد إلى محرر تصميم نافذة المشروع كي نقوم بتصميم الواجهة وعدل كود xaml لديك كما في الكود التالي الذي سيشكل واجهة المشروع حيث تم تصميم الواجهة بنفس الطريقة التي اتبعناها سابقا في أقسام الموضوع السابقة
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid Margin="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="95*" />
<ColumnDefinition Width="183*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="207*" />
<RowDefinition Height="55*" />
</Grid.RowDefinitions>
<StackPanel Name="StackPanel1">
<Label Height="28" Name="Label1" Width="Auto" Margin="3">
Last Name</Label>
<Label Height="28" Name="Label2" Width="Auto" Margin="3">
First Name</Label>
<Label Height="28" Name="Label3" Width="Auto"
Margin="3">Address</Label>
<Label Height="28" Name="Label4" Width="Auto"
Margin="3">City</Label>
<Label Height="28" Name="Label5" Width="Auto"
Margin="3">State</Label>
<Label Height="28" Name="Label6" Width="Auto" Margin="3">
Zip</Label>
</StackPanel>
<StackPanel Grid.Column="1" Name="StackPanel2">
<TextBox Height="28" Name="TextBox1" Width="Auto" Margin="3"
Text="{Binding Path=LastName}"/>
<TextBox Height="28" Name="TextBox2" Width="Auto" Margin="3"
Text="{Binding Path=FirstName}"/>
<TextBox Height="28" Name="TextBox3" Width="Auto" Margin="3"
Text="{Binding Path=Address}"/>
<TextBox Height="28" Name="TextBox4" Width="Auto" Margin="3"
Text="{Binding Path=City}" />
<TextBox Height="28" Name="TextBox5" Width="Auto" Margin="3"
Text="{Binding Path=State}"/>
<TextBox Height="28" Name="TextBox6" Width="Auto" Margin="3"
Text="{Binding Path=ZIP}"/>
</StackPanel>
<Button Grid.Column="1" Grid.Row="1" Margin="13,20,0,12"
Name="btnAdd" HorizontalAlignment="Left" Width="75">Add</Button>
<Button Grid.Column="1" Grid.Row="1" HorizontalAlignment="Right"
Margin="0,20,6,12" Name="btnSave" Width="75">Save</Button>
</Grid>
</Window>ومن أجل عملية التحقق من البيانات يجب علينا إضافة خاصية إضافية لـ Binding هي ValidatesOnDataErrors و ضبطها إلى القيمة True وذلك لجميع التحكمات TextBox في كود xaml السابق مثال
Text="{Binding Path=ZIP, ValidatesOnDataErrors=True}انتقل إلى محرر الكود الخاص بالنافذة وأدخل الكود التالي الخاص بملئ البيانات
Class Window1 Private CustomerData As New CustomerDataSet Private taCust As New CustomerDataSetTableAdapters.CustomerTableAdapter Private taManager As New CustomerDataSetTableAdapters.TableAdapterManager Private View As CollectionView Private Sub Window1_Loaded(ByVal sender As System.Object, _ ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded Me.taCust.Fill(Me.CustomerData.Customer) Me.taManager.CustomerTableAdapter = taCust Me.DataContext = Me.CustomerData.Customer Me.View = _ CType(CollectionViewSource.GetDefaultView(Me.CustomerData.Customer), _ CollectionView) End Sub End Class
شغل المشروع وتأكد من رؤية البيانات قم بمسح البيانات من الحقل LastName وانتقل للحقل الذي يليه ستلاحظ أن صندوق النصوص الفارغ قد تمت إحاطته باللون الأحمر دلالة على فشل التحقق من البيانات
أضف إجراء معالجة النقر على الزر Add وضع فيه الكود التالي
If Not Me.CustomerData.HasErrors Then Dim row = Me.CustomerData.Customer.NewCustomerRow() row.LastName = "" Me.CustomerData.Customer.AddCustomerRow(row) Me.View.MoveCurrentToLast() End If
أضف إجراء لمعالجة حدث النقر على الزر Save وضع فيه الكود التالي
Try
If Me.CustomerData.HasErrors Then
MsgBox("Please correct the errors first")
Else
If Me.CustomerData.HasChanges Then
If Me.taManager.UpdateAll(Me.CustomerData) > 0 Then
MsgBox("Saved.")
End If
End If
End If
Catch ex As Exception
MsgBox(ex.ToString)
End Tryافتح الملف Application.xaml واجعل الكود فيه يبدو كما يلي من أجل إنشاء ValidationTemplate
<Application x:Class="Application"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml">
<Application.Resources>
<Style x:Key="myErrorTemplate" TargetType="Control">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<TextBlock DockPanel.Dock="Right"
Foreground="Red"
FontSize="14pt"
Margin="-15,0,0,0" FontWeight="Bold">*
</TextBlock>
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder Name="myControl"/>
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={x:Static RelativeSource.Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="TextBox" BasedOn="{StaticResource myErrorTemplate}" />
<Style TargetType="CheckBox" BasedOn="{StaticResource myErrorTemplate}" />
<Style TargetType="ComboBox" BasedOn="{StaticResource myErrorTemplate}" />
</Application.Resources>
</Application>حيث ضبطنا الخاصية Setter لـ Validation.ErrorTemplate من أجل تحديد أن هذه الـ Control Template هي خاصة بوقت حدوث خطأ وقسم Style.Triggers يقوم بإظهار ToolTip على التحكم عند حدوث خطأ