You are on page 1of 15

‫استخدام قواعد البيانات مع تطبيقات ‪WPF‬‬

‫بقلم‪ :‬محمد سامر أبو سلو‬

‫‪Samer.selo@yahoo.com‬‬
‫‪Samerselo2005@hotmail.com‬‬
‫مالحظة هامة قبل البدء‬

‫حتى تستفٌد من المواضٌع فً هذا الكتٌب حول استخدام قواعد البٌانات مع تطبٌقات ‪ wpf‬بالشكل األمثل ٌجب أن ٌكون لدٌك معرفة ببرمجة‬
‫قواعد البٌانات وأساسٌات ‪ WPF‬و ‪XAML‬‬
‫القسم األول – مدخل إلى قواعد البيانات‬

‫ وأضف للمشروع قاعدة البٌانات المرفقة مع األمثلة وأنشئ‬WpfDataEntery ‫ وسمه‬WPF Application ‫أنشئ مشروعا جدٌدا من نوع‬
‫ وذلك بالطرٌقة االعتٌادٌة عند إضافة مصدر بٌانات جدٌد وبذلك نكون قد أضفنا‬Customer ‫ باالعتماد على الجدول‬DataSet
xaml ‫ ثم عدل كود‬document outline ‫ ثم اختر األمر‬other Window ‫ ثم‬View ‫ ثم افتح قائمة‬.‫ للمشروع‬CustomerDatSet
‫الخاص بالنافذة لٌصبح كما ٌلً كً نقوم بتقسٌم الشبكة إلى أربعة أقسام‬

<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="294" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="46*" />
<RowDefinition Height="216*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="138*" />
<ColumnDefinition Width="140*" />
</Grid.ColumnDefinitions>
</Grid>
</Window>

‫ أنه أصبح بإمكانك سحب وإفالت التحكمات على النافذة تماما كما‬document outline ‫ثم أضف أربعة أزرار للنافذة الحظ انه بعد تفعٌل‬
Revert ‫ و‬Add ‫ و‬Delete ‫ لها إلى‬Content ‫ ثم غٌر خصائص األربعة أزرار لٌتم ضبط خاصٌة‬Windows Forms ‫نفعل فً تطبٌقات‬
‫ ثم أضف أربعة أزرار أخرى من أجل االنتقال‬btnSave ‫ و‬btnRevert ‫ و‬btnAdd ‫ و‬btnDelete ‫ إلى‬Name ‫ و خاصٌة‬Save ‫و‬
btnLast ‫ و‬btnNext ‫ و‬btnPrevious ‫ و‬btnFirst ً‫ كالتال‬name ‫السابق والتالً واألول واألخٌر واجعل خاصٌة‬

‫ وغٌر حجمهما لٌمأل كل واحد كامل مساحة قسم الشبكة الموجود فٌه ثم أضف‬Grid ‫ إلى القسمٌن السفلٌٌن من الـ‬2 ‫ عدد‬stackpanel ‫أضف‬
28 ‫ لصنادٌق النصوص إلى‬height ‫ للٌمٌنً ثم اضبط خاصٌة‬TextBox ‫ الٌساري و أربعة تحكمات‬StackPanel ‫ لـ‬label ‫أربعة تحكمات‬
Auto ‫ إلى‬TextBox ‫و‬Label ‫ لجمٌع تحكمات‬Width ‫ ثم اضبط خاصٌة‬Label ‫لمساواة ارتفاعها مع تحكمات‬

‫ كما اضبط‬txtCustomerID ‫ العلوي‬TextBox ‫ لـ‬name ‫ واجعل خاصٌة‬CustomerID ‫ العلوي إلى‬Label ‫ لـ‬Content ‫اضبط قٌمة‬
‫ و‬City ‫ و‬First Name ‫ و‬Last Name ‫ إلى‬Lable ‫ لبقٌة تحكمات‬Content ‫ ثم اضبط خاصٌة‬True ‫ له إلى‬IsReadOnly ‫خاصٌة‬
txtCity ‫ و‬txtFirstName ‫ و‬txtLastName ‫ إلى‬TextBox ‫ لبقٌة تحكمات‬name ‫خاصٌة‬

ً‫ و أضف النص التال‬xaml ‫ انتقل إلى كود‬Show Data Sources ‫ ثم اختر‬Data ‫من أجل ربط صنادٌق النصوص بالبٌانات افتح قائمة‬
Text="{Binding ً‫ كما ٌل‬CustomerID ‫ بالحقل‬txtCustomerID ‫ لصندوق النصوص‬text ‫الذي ٌحدد كٌفٌة ربط الخاصٌة‬
‫ ألنه للقراءة فقط‬OneWay ‫ وقمنا بتحدٌد‬Path=CustomerID, Mode=OneWay}

‫ ألنه للقراءة والكتابة‬oneWay ‫ وقد أزلنا القٌمة‬Text="{Binding Path=LastName} ً‫ كما ٌل‬txtLastName ‫ لـ‬text ‫أضف الخاصٌة‬
‫ لصنادٌق النصوص لدٌك مشابها‬xaml ‫كرر نفس العملٌة بالنسبة لصندوقً النصوص الباقٌٌن لربطها مع الحقول المناسبة وبذلك ٌصبح كود‬
ً‫للتال‬

<TextBox Height="28" Name="txtCustomerID" Width="Auto" IsReadOnly="True"


Text="{Binding Path=CustomerID, Mode=OneWay}" />
<TextBox Height="28" Name="txtLastName" Width="Auto"
Text="{Binding Path=LastName}"/>
<TextBox Height="28" Name="txtFirstName" Width="Auto"
Text="{Binding Path=FirstName}"/>
<TextBox Height="28" Name="txtCity" Width="Auto"
Text="{Binding Path=City}"/>
‫ وأضف المتغٌرات التالٌة فً القسم العام للفئة فً ملف الكود‬View Code ‫انقر على نافذة التطبٌق بزر الفأرة الٌمٌنً ثم اختر‬

Private CustomerData As New CustomerDataSet


Private taCust As New CustomerDataSetTableAdapters.CustomerTableAdapter
Private taManager As New CustomerDataSetTableAdapters.TableAdapterManager

‫ للنافذة‬Loaded ‫أضف الكود التالً لحدث‬

Me.taCust.Fill(Me.CustomerData.Customer)

Me.DataContext = Me.CustomerData.Customer

‫ للنافذة‬DataContext ‫ ثم ضبطنا قٌمة الخاصٌة‬Fill ‫ الذي هو عبارة عن محول البٌانات بالبٌانات باستخدام الطرٌقة‬taCust ‫حٌث قمنا بملئ‬
‫ فإن شغلت البرنامج هنا ستالحظ ظهور البٌانات على النافذة‬Customer ‫إلى الجدول‬

‫ فً تطبٌقات النوافذ‬BindingSource ‫ بدٌال عن‬WPF ‫ فً تطبٌقات‬CollectionView ‫عرف المتغٌر التالً على مستوى الفئة حٌث ٌعتبر‬

Private View As CollectionView

‫ للنافذة بعد الكود الذي أدخلناه فٌها سابقا‬Loaded ‫ومن أجل ربطه مع بٌاناتنا نستخدم الكود التالً فً الحدث‬

Me.View= CollectionViewSource.GetDefaultView(Me.CustomerData.Customer)

‫أجعل حدث النقر على أزرار التنقل كما فً الكود التالً من أجل تنفٌذ عملٌات التنقل بٌن السجالت‬

Private Sub btnFirst_Click(ByVal sender As System.Object, _


ByVal e As System.Windows.RoutedEventArgs) Handles btnFirst.Click

Me.View.MoveCurrentToFirst()
End Sub

Private Sub btnPrevious_Click(ByVal sender As System.Object, _


ByVal e As System.Windows.RoutedEventArgs) Handles btnPrevious.Click

If Me.View.CurrentPosition > 0 Then


Me.View.MoveCurrentToPrevious()
End If
End Sub

Private Sub btnNext_Click(ByVal sender As System.Object, _


ByVal e As System.Windows.RoutedEventArgs) Handles btnNext.Click

If Me.View.CurrentPosition < Me.View.Count - 1 Then


Me.View.MoveCurrentToNext()
End If
End Sub

Private Sub btnLast_Click(ByVal sender As System.Object, _


ByVal e As System.Windows.RoutedEventArgs) Handles btnLast.Click

Me.View.MoveCurrentToLast()
End Sub

‫أدخل الكود التالً من أجل زر الحذف‬


Private Sub btnDelete_Click(ByVal sender As System.Object, _
ByVal e As System.Windows.RoutedEventArgs) Handles btnDelete.Click

If Me.View.CurrentPosition > -1 Then


Dim row = CType(Me.View.CurrentItem, System.Data.DataRowView).Row
row.Delete()
End If
End Sub

‫ للحصول على السطر الحالً ثم قمنا بعملٌة الحذف‬Ctype ‫حٌث تأكدنا أوال أننا لسنا خارج النطاق قبل عملٌة الحذف ثم استخدمنا الدالة‬

ً‫من أجل زر اإلضافة أدخل الكود التال‬

Private Sub btnAdd_Click(ByVal sender As System.Object, _


ByVal e As System.Windows.RoutedEventArgs) Handles btnAdd.Click

Dim row = Me.CustomerData.Customer.NewCustomerRow


row.LastName = "[New]"
Me.CustomerData.Customer.AddCustomerRow(row)
Me.View.MoveCurrentToLast()
End Sub

‫حٌث أنشانا سطرا جدٌدا وحددنا قٌمة افتراضٌة لحقل االسم األخٌر بما أنه ال ٌمكن أن ٌكون فارغا حسب قاعدة البٌانات ثم قمنا بإضافته‬
‫ والسطر األخٌر من اجل إظهار السجل الجدٌد‬Customer ‫للجدول‬

ً‫ أضف الكود التال‬Revert ‫ومن أجل زر‬

Private Sub btnRevert_Click(ByVal sender As System.Object, _


ByVal e As System.Windows.RoutedEventArgs) Handles btnRevert.Click

If Me.CustomerData.HasChanges Then
Dim msg = "Are you sure that You want to loose all your changes?"
If MessageBox.Show(msg, Me.Title, MessageBoxButton.YesNo) = _
MessageBoxResult.Yes Then

Me.CustomerData.RejectChanges()
End If
End If
End Sub

‫ إللغاء‬RejectChanges ‫حٌث أظهرنا رسالة للمستخدم لٌؤكد أنه ٌرغب فعال بإلغاء جمٌع التعدٌالت التً قام بها وإن وافق نستخدم الطرٌقة‬
‫تلك التغٌٌرات‬

‫ مع الجدول المناسب‬TableAdaptermanager ‫ للنموذج لربط‬Loaded ‫أضف السطر التالً لحدث‬

Me.taManager.CustomerTableAdapter = taCust

ً‫وسوف ٌكون كود زر الحفظ كما ٌل‬

Private Sub btnSave_Click(ByVal sender As System.Object, _


ByVal e As System.Windows.RoutedEventArgs) Handles btnSave.Click

Try
If Me.CustomerData.HasChanges Then
If Me.taManager.UpdateAll(Me.CustomerData) > 0 Then
MsgBox("Saved")
End If
‫‪End If‬‬
‫‪Catch ex As Exception‬‬
‫)‪MsgBox(ex.ToString‬‬
‫‪End Try‬‬
‫‪End Sub‬‬

‫حٌث استخدمنا حلقة ‪ Try‬اللتقاط أي خطأ ٌصدر عن قاعدة البٌانات وتأكدنا من أنه توجد تعدٌالت كً نقوم بحفظها وذلك باستخدام الدالة‬
‫‪ HasChanges‬ثم استخدمنا الطرٌقة ‪ UpdateAll‬من أجل عملٌة الحفظ الفعلٌة‬

‫شغل البرنامج واختبره‬


‫القسم الثاني – التعامل مع ‪ListBox‬‬

‫أنشئ مشروعا جدٌدا من النوع ‪ WPF Application‬وسمه ‪ ListBoxData‬ثم أضف قاعدة البٌانات المرفقة األمثلة إلى المشروع وفً معالج‬
‫إنشاء مجموعة البٌانات اختر الجدول ‪ Products‬وسم مجموعة البٌانات ‪ ProductDataSet‬ثم انتقل إلى محرر الكود الخاص بالنافذة‬
‫وأدخل فً الفئة الخاصة بالنافذة الكود التالً من أجل تحمٌل البٌانات‬

‫‪Private taProduct As New ProductDataSetTableAdapters.ProductTableAdapter‬‬


‫‪Private dsProduct As New ProductDataSet‬‬

‫_ ‪Private Sub Window1_Loaded(ByVal sender As System.Object,‬‬


‫‪ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded‬‬

‫)‪Me.taProduct.Fill(Me.dsProduct.Product‬‬

‫‪End Sub‬‬

‫عد إلى محرر النافذة وأضف ‪ ListBox‬إلى سطحها ثم عد إلى محرر الكود وأضف السطر التالً فً بعد السطر الموجود فً حدث ‪Loaded‬‬
‫للنموذج حٌث نقوم بضبط قٌمة الخاصٌة ‪ ItemsSourc e‬لصندوق القائمة إلى الجدول ‪Product‬‬

‫‪Me.ListBox1.ItemsSource=Me.dsProduct.Product‬‬

‫ونقوم بضبط قٌمة الخاصٌة ‪ DisplayMemberPath‬على ‪ name‬من أجل تحدٌد اسم العمود الذي نرٌد أن نظهر بٌاناته ولعمل ذلك أضف‬
‫السطر التالً بعد السطر السابق‬

‫"‪Me.ListBox1.DisplayMemberPath = "Name‬‬

‫شغل التطبٌق والحظ البٌانات فً صندوق القائمة‬

‫ومن أجل ترتٌب البٌانات الظاهرة فً صندوق القائمة ٌمكننا استبدال قٌمة الخاصٌة ‪ ItemsSource‬باستعالم لٌنك ولعمل ذلك استبدل السطر‬

‫‪Me.ListBox1.ItemsSource = Me.dsProduct.Product‬‬

‫بالسطر‬

‫‪Me.ListBox1.ItemsSource = From p In Me.dsProduct.Product Order By p.Name‬‬

‫انتقل إلى محرر النافذة وأضف صندوق نصوص أسفل صندوق القائمة حٌث سنستخدمه إلظهار وصف المنتج ولعمل ذلك سنحتاج لربط كال‬
‫التحكمٌن مع جدول البٌانات وأسهل طرٌقة فً ‪ WPF‬لربط عدة تحكمات هً ضبط ما ٌسمى بـ ‪ DataContext‬للنافذة بحٌث تستخدمها‬
‫التحكمات افتراضٌا‬

‫انتقل إلى محرر الكود واستبدل كافة الكود الخاص بالحدث ‪ Loaded‬للنافذة بالكود التالً‬

‫)‪Me.taProduct.Fill(Me.dsProduct.Product‬‬
‫‪Me.DataContext = From p In Me.dsProduct.Product Order By p.Name‬‬

‫عد إلى محرر ‪ xaml‬الخاص بالنافذة حٌث سنقوم بربط البٌانات من هناك حٌث سنقوم بتعدٌل الكود الخاص بصندوق القائمة لٌضبط قٌمة‬
‫الخاصٌتٌن ‪ ItemsSource‬و ‪ DisplayMemberPath‬حٌث سٌصبح كود ‪ xaml‬الخاص بـ ‪ ListBox‬كما ٌلً مع العلم أن الخاصٌة‬
‫‪ IsSynchronizedWithCurrnetItem‬تتٌح مزامنة القٌمة المختارة فً صندوق القائمة مع السجل الحالً بحٌث تتٌح إظهار الوصف‬
‫المناسب للمنتج المختار فً صندوق النصوص‬

‫"‪<ListBox Margin="12,12,12,120" Name="ListBox1‬‬


‫"}}{=‪ItemsSource="{Binding Path‬‬
‫"‪DisplayMemberPath="Name‬‬
‫>‪IsSynchronizedWithCurrentItem="True"/‬‬

‫واستبدل كود صندوق النصوص بالكود التالً من أجل ربطه مع الحقل ‪Description‬‬

‫"‪<TextBox Text="{Binding Path=Description}" Height="95‬‬


‫>‪Margin="16,0,14,12" Name="TextBox1" VerticalAlignment="Bottom" /‬‬

‫ٌمكننا االستفادة أٌضا من مٌزة فً ‪ WPF‬هً إمكانٌة صنع قوالب للتحكمات ‪ Templates‬ولتجربة ذلك أزل صندوق النصوص من على‬
‫النافذة حٌث سنجعله ٌظهر داخل صندوق القائمة وسع اآلن صندوق القائمة لٌمأل النموذج ثم عدل كود ‪ xaml‬لصندوق القائمة لٌصبح كالتالً‬
‫حتى ٌمكننا إضافة التحكمات داخل صندوق القائمة الحظ حذف الخاصٌة ‪DisplayMemberPath‬‬

‫"‪<ListBox Margin="12" Name="ListBox1‬‬


‫"}}{=‪ItemsSource="{Binding Path‬‬
‫>"‪IsSynchronizedWithCurrentItem="True‬‬

‫>‪</ListBox‬‬

‫داخل كود صندوق القائمة وقبل قسم إغالقها >‪ </ListBox‬أضف الكود التالً الذي ٌعرف قالب بٌانات ‪ DataTemplate‬داخل صندوق‬
‫القائمة ونضٌف بداخله ‪ StackPanel‬باتجاه أفقً كً ٌساعدنا فً ترتٌب التحكمات بداخل صندوق القائمة الحظ هنا أن جمٌع التحكمات فً‬
‫‪ WPF‬هً مستوعبات ‪ٌ Containers‬مكن وضع تحكمات بداخلها‬

‫>‪<ListBox.ItemTemplate‬‬
‫>‪<DataTemplate‬‬
‫>"‪<StackPanel Orientation="Horizontal‬‬

‫>‪</StackPanel‬‬
‫>‪</DataTemplate‬‬
‫>‪</ListBox.ItemTemplate‬‬

‫ضع داخل الـ ‪ StackPanel‬تحكمان ‪ Label‬بحٌث ٌكونان مربوطٌن مع العمودٌن ‪ name‬و ‪ Description‬كما ٌلً‬

‫>‪<Label Width="100" Content="{Binding Path=Name}"></Label‬‬


‫>‪<Label Width="200" Content="{Binding Path=Description}"></Label‬‬

‫شغل المشروع واختبره – الحظ ظهور عمودٌن للبٌانات بداخل صندوق القائمة وفً الحقٌقة بشكل عام ٌمكنك وضع أي تحكم بداخل صندوق‬
‫القائمة مثل األزرار أو صنادٌق النصوص أو مربعات االختٌار ‪ ...‬الخ‬
‫القسم الثالث – التعامل مع ‪ComboBox‬‬

‫أنشئ مشروعا جدٌدا وسمه ‪ WpfLookup_VB‬ثم أضف مصدر بٌانات جدٌد باستخدام المعالج واستخدم قاعدة البٌانات المرفقة مع األمثلة‬
‫واختر الجدول ‪ Orders‬وسم الـ ‪ Dataset‬باالسم ‪ OrdersDataSet‬ثم أضف مصدر بٌانات جدٌد واختر الجدول ‪ Customer‬بحٌث تحدد‬
‫الحقول ‪ CustomerID‬و ‪ FirstName‬و ‪ LastName‬فقط وسم الـ ‪ DataSet‬باالسم ‪CustomerLookupDataSet‬‬

‫افتح ‪ CustomerLookupDataSet‬ثم انقر بزر الفأرة الٌمٌنً على ‪ CustomerTableAdapter‬ثم اختر ‪ Configure‬وأضف قسم‬
‫‪ Order By‬لالستعالم الموجود فً الصفحة بحٌث ٌصبح االستعالم كما ٌلً‬

‫‪SELECT CustomerID, LastName, FirstName FROM Customer ORDER BY LastName, FirstName‬‬

‫ثم اضغط ‪Finish‬‬

‫أغلق محرر مجموعة البٌانات ثم اذهب إلى قائمة ‪ View‬ثم اختر إظهار نافذة ‪ Document Outline‬التً تساعدنا فً االنتقال عبر ‪xaml‬‬

‫عدل كود ‪ Grid‬فً ‪ Xaml‬من أجل تقسٌم الشبكة إلى أربعة أقسام بحٌث ٌصبح كما ٌلً‬

‫>‪<Grid‬‬
‫>‪<Grid.ColumnDefinitions‬‬
‫>‪<ColumnDefinition Width="110*" /‬‬
‫>‪<ColumnDefinition Width="168*" /‬‬
‫>‪</Grid.ColumnDefinitions‬‬
‫>‪<Grid.RowDefinitions‬‬
‫>‪<RowDefinition Height="222*" /‬‬
‫>‪<RowDefinition Height="40*" /‬‬
‫>‪</Grid.RowDefinitions‬‬
‫>‪</Grid‬‬

‫أدرج ‪ StackPanel‬فً كل قسم من القسمٌن العلوٌٌن للشبكة واجعل كل واحد منهما ٌمأل كامل مساحة قسم من أقسام الشبكة ثم أضف زرٌن‬
‫فً القسم الٌمٌنً السفلً للشبكة بحٌث تكون خاصٌة ‪ name‬لهما ‪ btnSave‬و ‪ btnAdd‬و خاصٌة ‪ Contenet‬لهما ‪ Add‬و ‪ Save‬ثم‬
‫أضف أربعة تحكمات ‪ Label‬فً الـ ‪ stackPanel‬العلوي الٌمٌنً واضبط خاصٌة ‪ Width‬لها إلى ‪ Auto‬ثم اضبط خاصٌة ‪ Content‬لها‬
‫بحٌث تكون من األعلى لألسفل ‪ Order ID‬و ‪ Customer‬و ‪ Order Date‬و ‪Ship Date‬‬

‫أدرج فً الـ ‪ StackPanel‬العلوي الٌمٌنً تحكم ‪ TextBox‬ثم تحكم ‪ ComboBox‬ثم تحكمً ‪ TextBox‬ثم اضبط خاصٌة ‪ height‬لهذه‬
‫التحكمات إلى ‪ 28‬كً نضبط ارتفاعها بشكل موازي الرتفاع تحكمات ‪ Label‬فً القسم المقابل واضبط خاصٌة ‪ Width‬لهذه التحكمات أٌضا‬
‫إلى ‪ Auto‬ثم اختر الـ ‪ Grid‬واضبط الخاصٌة ‪ Margin‬إلى ‪ 6‬كما قم بضبط الخاصٌة ‪ Margin‬لجمٌع تحكمات ‪ Label‬و ‪ textbox‬و‬
‫‪ ComboBox‬إلى ‪3‬‬

‫عدل كود ‪ xaml‬لصندوق النصوص األول كً ٌتم ربطه مع الحقل ‪ OrderID‬فٌصبح كما ٌلً‬

‫"‪<TextBox Height="28" Name="TextBox1" Width="Auto" Margin="3‬‬


‫>‪Text="{Binding Path=OrderID, Mode=OneWay}" IsReadOnly="True"/‬‬

‫ثم عدل كود ‪ xaml‬لصندوقً النصوص اآلخرٌن كً ٌتم ربطهما مع الحقلٌن ‪ OrderDate‬و ‪ ShipDate‬فٌصبح كما ٌلً‬

‫"‪<TextBox Height="28" Name="TextBox2" Width="Auto" Margin="3‬‬


‫>‪Text="{Binding Path=OrderDate}"/‬‬
‫"‪<TextBox Height="28" Name="TextBox3" Width="Auto" Margin="3‬‬
‫>‪Text="{Binding Path=ShipDate}"/‬‬
CustomerID ‫ و القٌمة المختارة مع‬LastName ‫ لربط قٌمة اإلظهار مع الحقل‬Combobox ‫اضبط خصائص الـ‬

<ComboBox Height="28" Name="ComboBox1" Width="Auto" Margin="3"


DisplayMemberPath="LastName" SelectedValuePath="CustomerID"
SelectedValue="{Binding Path=CustomerID}"/>

‫انتقل إلى محرر الكود الخاص بالنافذة وأضف المتغٌرات التالٌة العامة على مستوى النموذج كً نستخدمها للتعامل مع قواعد البٌانات‬

Private OrderData As New OrdersDataSet


Private taOrder As New OrdersDataSetTableAdapters.OrdersTableAdapter
Private taManager As New OrdersDataSetTableAdapters.TableAdapterManager
Private CustomerLookup As New CustomerLookupDataSet.CustomerDataTable

‫ الخاص بالنافذة كً ٌتم ربط البٌانات مع النموذج وإظهارها‬loaded ‫أضف الكود التالً فً الحدث‬

Dim taCustomer As New CustomerLookupDataSetTableAdapters.CustomerTableAdapter


taCustomer.Fill(Me.CustomerLookup)

Me.taOrder.Fill(Me.OrderData.Orders)
Me.taManager.OrdersTableAdapter = Me.taOrder

Me.DataContext = Me.OrderData.Orders
Me.ComboBox1.ItemsSource = Me.CustomerLookup

‫ بالبٌانات بواسطة الطرٌقة‬CustometLookup ‫ واستخدمناه لملئ‬Customer ‫ للجدول‬TableAdapterManager ‫حٌث قمنا بتعرٌف‬


‫ العائد لـ‬OrdersTableAdapter ‫ ثم قمنا بضبط‬taOrder ‫ بالبٌانات باستخدام‬OdrerData ‫ وبنفس األسلوب قمنا بملئ‬Fill
‫ كً نعلم جمٌع التحكمات الموجودة‬orders ‫ الخاصة بالنافذة مع الجدول‬DataContext ‫ ثم ربطنا الـ‬taOrder ‫ لٌساوي‬taManager
‫ مع‬ComboBox ‫ العائدة لـ‬itemsSource ‫ ثم ضبطنا خاصٌة‬Orders ‫علٌها بأن الخصائص المرتبطة بقاعدة البٌانات هً عائدة للجدول‬
‫ من أجل إظهار البٌانات بشكل صحٌح فٌه‬CustomerLookup

ً‫ لٌتم إضافة معالج لحدث النقر على الزر ونقلك لمحرر الكود ثم أضف السطر التال‬Add ‫عد إلى محرر النافذة وانقر نقرا مزدوجا على الزر‬
‫مع المتغٌرات التً عرفناها فً القسم العام للفئة‬

Private View As CollectionView

ً‫ للنافذة أضف الكود التال‬Loaded ‫وفً نهاٌة الكود الموجود فً الحدث‬

Me.View= CollectionViewSource.GetDefaultView(Me.OrderData.Orders)

‫ وأضف الكود التالً الذي ٌمثل كود إضافة سطر جدٌد‬Add ‫ الخاص بالزر‬Click ‫ثم انتقل لحدث‬

Dim row = Me.OrderData.Orders.NewOrdersRow


row.CustomerID = 0
Me.OrderData.Orders.AddOrdersRow(row)
Me.View.MoveCurrentToLast()

ً‫أنشئ معالج لحدث النقر على زر الحفظ وأدخل فٌه الكود التال‬

Try
If Me.OrderData.HasChanges Then
If Me.taManager.UpdateAll(Me.OrderData) > 0 Then
MsgBox("Saved")
End If
End If
Catch ex As Exception
MsgBox(ex.ToString)
End Try

ً‫ الذي سنقوم بتعدٌله حتى ٌقوم بإظهار حقلً االسم األخٌر واالسم األول ف‬ComboBox ‫ للنافذة واذهب إلى كود‬xaml ‫انتقل إلى محرر‬
‫ بدال عنها التً تمكننا من إضافة‬ItemsTemplate ‫ حٌث سنضٌف‬DisplayMemberPath="LastName" ‫البداٌة احذف الخاصٌة‬
ً‫ لٌصبح كما ٌل‬ComboBox ‫التحكمات بداخله إلظهار االسم األخٌر واالسم األول عدل كود الـ‬

<ComboBox Height="28" Name="ComboBox1" Width="Auto" Margin="3"


SelectedValuePath="CustomerID"
SelectedValue="{Binding Path=CustomerID}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Name="LastName"
Text="{Binding Path=LastName}"/>
<TextBlock Width="5">,</TextBlock>
<TextBlock Name="FirstName"
Text="{Binding Path=FirstName}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ComboBox>

‫ بترتٌب أفقً الذي سٌحتوي‬StackPanel ‫ ثم أضفنا بداخلها تحكم‬DataTemplate ‫ وحددنا أنها من نوع‬itemTemplate ‫حٌث أضفنا‬
‫ و األخٌر مع‬LastName ‫ داخله األول تم ربطه مع‬TextBlock ‫على تحكماتنا المضافة وٌتحكم بترتٌبها ثم أضفنا ثالثة تحكمات‬
‫ بنفس الطرٌقة التً استخدمناها مع صنادٌق النصوص‬Binding ‫ والوسطً وضعنا فٌه فاصلة فقط وطرٌقة الربط هً باستخدام‬FirstName

‫شغل المشروع واختبره‬


‫القسم الرابع – التحقق من البيانات‬

‫سنرى فً هذا القسم كٌف ٌمكننا التحقق من البٌانات واستكشاف األخطاء فٌها حٌث توجد ثالث خطوات أساسٌة إلظهار رسائل التحقق‬

‫فً البداٌة ٌجب على الغرض ‪ Object‬الذي ٌحمل البٌانات فً النموذج أن ٌحقق الواجهة ‪ IDataErrorInfo‬وإن كنت تستخدم ‪DataSets‬‬
‫فهً تقوم بذلك من أجلك عندها ٌمكننا كتابة أكواد التحقق من البٌانات وإظهار رسائل األخطاء اعتمادا على حاجة المشروع الذي نقوم بتنفٌذه‪.‬‬
‫واألمر الثانً الذي ٌجب علٌنا عمله هو ضبط الـ ‪ Binding‬الخاص بالتحكمات بأننا نرٌد إظهار إخبار مرئً عندما ٌفشل التحقق ونقوم بذلك‬
‫بضبط الخاصٌة ‪ ValidatesOnDataErrors‬إلى ‪ True‬وفً الوضع االفتراضً ٌحٌط ‪ WPF‬التحكم بإطار أحمر ولكنه ال ٌظهر أٌة رسالة‬
‫والمرحلة األخٌرة هً ضبط ‪ Validation.ErrorTemplate‬للتحكم كً نتمكن من إظهار الرسائل على التحكمات وجعلها تبدو تماما كما‬
‫نرٌد‬

‫أنشئ مشروعا جدٌدا من النوع ‪ WPF Application‬وسمه ‪ WPFDataValidation‬وٌتوجب علٌك استخدام قاعدة البٌانات المرفقة مع‬
‫األمثلة حٌث سنقوم بكتابة كود للتحقق من أن الحقل ‪ LastName‬فً الجدول ‪ Customer‬غٌر فارغ قبل الحفظ‬

‫‪ Customer‬وسمها‬ ‫من قائمة ‪ Data‬اختر األمر ‪ Add New Data Source‬إلضافة ‪ DataSet‬للمشروع باختٌار الجدول‬
‫‪ 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>

‫ و ضبطها إلى القٌمة‬ValidatesOnDataErrors ً‫ ه‬Binding ‫ومن أجل عملٌة التحقق من البٌانات ٌجب علٌنا إضافة خاصٌة إضافٌة لـ‬
‫ السابق مثال‬xaml ‫ فً كود‬TextBox ‫ وذلك لجمٌع التحكمات‬True

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

ً‫ كً نتحقق من عدم وجود أخطاء ف‬CuastomerData ‫ العائدة لـ‬HasErrors ‫الحظ فً زري اإلضافة والحفظ أننا استخدمنا الطرٌقة‬
‫البٌانات قبل المتابعة‬

ValidationTemplate ‫ واجعل الكود فٌه ٌبدو كما ٌلً من أجل إنشاء‬Application.xaml ‫افتح الملف‬

<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>

‫ هً خاصة بوقت‬Control Template ‫ من أجل تحدٌد أن هذه الـ‬Validation.ErrorTemplate ‫ لـ‬Setter ‫حٌث ضبطنا الخاصٌة‬
‫ على التحكم عند حدوث خطأ‬ToolTip ‫ ٌقوم بإظهار‬Style.Triggers ‫حدوث خطأ وقسم‬

You might also like