مشاركة عبر


نظرة عامة لربط البيانات

Windows Presentation Foundation (WPF) ربط البيانات توفر طريقة بسيطة و متناسقة للتطبيقات لتقديم وللتفاعل مع البيانات. يمكن ربط العناصر إلى بيانات من مجموعة متنوعة من مصادر البيانات في صورة كائنات وقت تشغيل اللغة العامة (CLR) و XML. ContentControls such as Button and ItemsControls such as ListBox and ListView have built-in functionality to enable flexible styling of single data items or collections of data items. يمكن إنشاء و تصفية وفرز طرق العرض في أعلى البيانات .

وظيفة ربط البيانات في WPF له ميزات عديدة فوق الطرازات التقليدية, بما في ذلك نطاق واسع من الخصائص التي تدعم بالأصل ربط البيانا, مرونة واجهة المستخدم تمثيل البيانات ، وتنظيف فصل منطق تسلسل العمل من واجهة المستخدم.

أولاً يناقش هذا الموضوع المفاهيم الأساسية ل WPF ربط البيانات ثم ينتقل إلى استخدام Binding فئة وميزات أخرى من ربط البيانات.

يشتمل هذا الموضوع على الأقسام التالية.

  • ما هو ربط البيانات
  • المفاهيم الأساسية لربط البيانات
  • إنشاء ربط
  • تحويل البيانات
  • الربط إلى مجموعة
  • قلب البيانات
  • التحقق من صحة البيانات
  • آلية تصحيح الأخطاء
  • موضوعات ذات صلة

ما هو ربط البيانات

ربط البيانات هو عملية تأسيس اتصال بين التطبيق واجهة المستخدم و منطق تسلسل العمل. إذا كان يحتوي الربط على الإعدادات الصحيحة و توفر البيانات الإعلامات المناسبة, ثم عند تغيير القيمة الخاصة بالبيانات , العناصر المنضمة إلى البيانات تعكس التغير تلقائياً. ربط البيانات يمكن أن يعني أيضًا إذا تغير عنصر من التمثيل الخارجي للبيانات ,ثم يمكن تحديث البيانات الأساسية تلقائياً لتعكس التغيير. على سبيل المثال، إذا قام المستخدم بتحرير القيمة في TextBox عنصر, قيمة البيانات الأساسية يتم تحديثها تلقائياً لكي تعكس ذلك التغيير.

استخدام نموذجي لربط البيانات هو لوضع الخادم أو التكوين المحلي للبيانات في نماذج أخرى واجهة المستخدم لعناصر التحكم. في WPF ، يتم توسيع هذا المفهوم ليشمل ربط نطاق واسع من الخصائص إلى مجموعة متنوعة من مصادر البيانات. في WPF ، خصائص التبعية عناصر يمكن ربطها CLR الكائنات (بما في ذلك ADO.NET كائنات أو كائنات مقترنة بخدمات الويب و خصائص الويب ) و XML البيانات.

للحصول على مثال لربط البيانات، إلقي نظرة على التطبيقات التالية واجهة المستخدم من العرض التوضيحي لربط البيانات :

لقطة شاشة لعينة ربط البيانات

هو أعلاه واجهة المستخدم من التطبيق الذي يعرض قائمة من عناصر المزاد . يوضح التطبيق الميزات التالية لربط البيانات:

  • محتوى ListBox منضم لمجموعة من AuctionItemكائنات. يحتوي كائن AuctionItem خصائص مثل الوصف, بدأ الأسعار، بدأ الوقت ، الفئة ، سمات خاصة , الخ.

  • بيانات (كائنات AuctionItem )تعرض في ListBox يعرض بحيث يتم عرض السعر الحالي والوصف لكل صنف. يتم ذلك باستخدام DataTemplate. بالإضافة إلى ذلك، يعتمد مظهر كل عنصر على سمات خاصة قيمة AuctionItem معروضاً. إذا كان سمات خاصة قيمة AuctionItem هو لون ، لدى الصنف حد أزرق. إذا كانت القيمة تمييز ، الصنف له حد برتقالي و نجمة. مقطع عرض البيانات يوفر معلومات حول عرض البيانات.

  • يمكن للمستخدم تجميع أو تصفية أو فرز البيانات باستخدام CheckBox تم توفيرها. في النسخة أعلاه "تجميع حسب الفئة '' و" فرز حسب الفئة و التاريخ " CheckBox محددة . قد يكون لديك ملاحظة أنه يتم تجميع البيانات استناداً إلى الفئة الخاصة للمنتج, ويكون اسم الفئة في ترتيب أبجدي. من الصعب أن تلاحظ من الصورة ولكن يتم أيضاً فرز العناصر حسب تاريخ البدء داخل كل فئة. يتم ذلك باستخدام مجموعة عرض . ربط المجموعاتهذا المقطع يتناول طرق عرض مجموعة.

  • عندما يقوم المستخدم بتحديد صنف ، ContentControl يعرض تفاصيل الصنف المحدد . يسمى هذا السيناريو رئيسي تفصيلي. السيناريو التفصيلي الرئيسي مقطع يوفر معلومات حول هذا النوع من ربط السيناريو.

  • نوع تاريخ البدءخاصية DateTime ، والتي ترجع التاريخ الذي يتضمن الوقت إلى millisecond. في هذا التطبيق, تم استخدام محول مخصص بحيث يتم عرض سلسلة تاريخ أقصر. مقطع تحويل البيانات يوفر معلومات حول المحولات.

عندما يقوم المستخدم بالنقر فوق زر إضافة منتج يظهر النموذج التالي:

صفحة إضافة إدخال قائمة منتج

المستخدم يمكن له تحرير الحقول في النموذج ، معاينة سرد المنتج باستخدام المعاينة القصيرة و جزء المعاينة الأكثر تفصيلاً ثم انقر فوق إرسال لإضافة قائمة المنتج الجديد. أي تجميع موجود ، تصفية وفرز للوظائف سيتم تطبيقها على الإدخال الجديد . في هذه الحالة بالتحديد، إدخال الصنف في النسخة أعلاه ,سيتم عرضه كالصنف الثاني ضمن الفئة الكمبيوتر.

غير مبين في هذه النسخة هو منطق التحقق من الصحة المقدم في تاريخ البدء TextBox. إذا قام المستخدم بإدخال تاريخ غير صالح (تنسيق غير صالح أو تاريخ في الماضي) ، سيتم إعلام المستخدم مع ToolTip و نقطة تعجب حمراء بجانب TextBox. مقطع التحقق من صحة البيانات يتناول كيفية إنشاء منطق التحقق من الصحة.

قبل الانتقال إلى الميزات المختلفة لربط البيانات المفصلة أعلاه, فإننا أولاً سوف نناقش في المقطع التالي المفاهيم الأساسية الحرجة لفهم WPFربط البيانات.

المفاهيم الأساسية لربط البيانات

يشتمل هذا القسم على الأقسام الفرعية التالية.

  • اتجاه تدفق البيانات
  • ماذا يشغل تحديثات المصدر

بغض النظر عن العنصر الذي كنت تقوم بربطه وإلى طبيعة مصدر بياناتك ,كل ربط دوماً يتبع الطراز الموضح بواسطة الشكل التالي:

رسم تخطيطي لربط البيانات الأساسية

كما هو موضح بواسطة الشكل أعلاه ,ربط البيانات هو بشكل أساسي الجسر بين هدف الربط الخاص بك مصدر الربط . يوضح الشكل التالي WPFالمفاهيم الأساسية لربط البيانات:

  • بشكل عام، يكون لكل ربط هذه المكونات الأربعة: كائن هدف الربط ، خاصية الهدف ، مصدر الربط والمسار إلى القيمة الموجودة في مصدر الربط لاستخدام. على سبيل المثال، إذا كنت ترغب في ربط محتوى TextBox إلى اسم خاصية كائن الموظف ، يكون هدف الكائن هو TextBox ، خاصية الهدف هي Text خاصية ، القيمة المستخدمة اسمومصدر الكائن هو كائن الموظف.

  • خاصية الهدف يجب أن تكون خاصية التبعية . معظم UIElement الخصائص خصائص تبعية و معظم خصائص التبعية ، ما عدا تلك للقراءة فقط ,تدعم ربط البيانات بشكل افتراضي. (فقط DependencyObject أنواع يمكنها تعريف خصائص التبعية و كافة UIElement s ينحدر من DependencyObject.)

  • وعلى الرغم من أنه لم يتم تحديد في الشكل، يجب ملاحظة الذي الكائن المصدر الربط هو غير مقيد إلى كونها مخصصة CLRالكائن. WPFبيانات ربط يعتمد بيانات في النموذجCLRالكائنات وXML. لتوفير بعض الأمثلة قد يكون مصدر الربط UIElement ، أي كائن قائمة CLR الكائن المرتبط ب ADO.NET بيانات أو خدمات الويب الخاص بك أو XmlNode التي تحتوي على XML بياناتك. لمزيد من المعلومات، راجع نظرة عامة حول مصادر الربط.

أثناء قراءة خلال عدة تطوير البرامج (SDK) مواضيع أخرى ,فمن المهم تذكر أن عند تأسيس ربط ,كنت تقوم بربط هدف الربط إلى‏‎ مصدر الربط. على سبيل المثال، إذا كان يتم عرض بعض XML البيانات الأساسية في ListBox باستخدام ربط البيانات، كنت تقوم بربط ListBox إلى XML بيانات.

لتأسيس ربط ، يمكنك استخدام Binding الكائن. توضح بقية هذا الموضوع العديد من المفاهيم المرتبطة ببعض الخصائص و استخدام Binding الكائن.

اتجاه تدفق البيانات

كما ذكر مسبقاً و كما هو موضح بواسطة الأسهم في الشكل أعلاه , تدفق بيانات الربط يمكنها الانتقال إلى هدف الربط إلى مصدر الربط (على سبيل المثال، تغيير قيمة المصدر عند قيام المستخدم بتحرير قيمة TextBox) و/أو من مصدر الربط إلى هدف الربط (على سبيل المثال، TextBox يحصل تحديث للمحتوى عند التغيير في مصدر الربط ) إذا وفر مصدر الربط الإعلامات المناسبة.

قد يحتاج التطبيق الخاص بك تمكين المستخدمين من تغيير البيانات ثم نشرها إلى الكائن المصدر. أو قد لا تريد تمكين المستخدمين من تحديث بيانات المصدر . يمكنك التحكم في هذا بواسطة إعداد Mode خاصية من Binding الكائن الخاص بك. يوضح الرسم التالي الأنواع المختلفة من تدفق البيانات:

تدفق بيانات ربط البيانات

  • OneWay الربط يؤدي إلى تغييرات في خاصية المصدر لتحديث خاصية الهدف تلقائيًا ، بينما تغير خاصية الهدف لا يتم نشرها إلى خاصية المصدر . هذا النوع من الربط هو المناسب إذا كان ضمنيًا عنصر التحكم المنضم للقراءة فقط. على سبيل المثال، قد تربط بمصدر مثل مؤشر أسهم أو ربما تكون خاصية الهدف الخاص بك لا تحتوي على واجهة عنصر التحكم المقدمة لإجراء تغييرات , مثل لون خلفية ربط البيانات في جدول. إذا لم يكن هناك حاجة لمراقبة تغييرات خاصية الهدف ، باستخدام OneWayوضع الربط يتجنب الزائد من TwoWay وضع الربط.

  • TwoWay الربط يؤدي إلى التغييرات في خاصية المصدر أو خاصية الهدف لتحديث الآخر تلقائياً. هذا النوع من الربط يتناسب مع النماذج القادرة على التحرير أو واجهة المستخدم السيناريوهات الأخرى التفاعلية بالكامل . معظم الخصائص بشكل افتراضي OneWay الربط ، ولكن بعض خصائص التبعية (عادةً خصائص عناصر تحكم المستخدم القابلة للتحرير مثل Text خاصية TextBox و IsChecked خاصية من CheckBox) الافتراضي إلى TwoWay الربط. طريقة برمجية لتحديد ما إذا كان خاصية التبعية بربط أحادية الاتجاه أو ثنائية الاتجاه بشكل افتراضي للحصول على بيانات تعريف للخاصية باستخدام GetMetadata ثم تحقق من القيمة المنطقية BindsTwoWayByDefaultالخاصية.

  • OneWayToSource هو عكس OneWay الربط; فإنه يقوم بتحديث خاصية المصدر عند تغيير خاصية الهدف. مثال سيناريو واحد هو إذا احتجت فقط إعادة تقييم قيمة مصدر من واجهة المستخدم.

  • غير موضحة في الشكل OneTime الربط ,الذي يجعل خاصية المصدر لتهيئة خاصية الهدف ، ولكن لا تنشر التغييرات اللاحقة. وهذا يعني أنه إذا خضع سياق البيانات لتغيير أو الكائن في سياق البيانات تغيرت ،التغيير ينعكس على خاصية الهدف. يكون هذا النوع من الربط مناسباً إذا كنت تستخدم البيانات حيث يتم أخذ لقطة للحالة الحالية مناسبة للاستخدام أو البيانات ثابتة حقا. هذا النوع من الربط مفيد أيضاً إذا كنت تريد تهيئة خاصية الهدف بقيمة من خاصية المصدر و بيانات السياق غير معروفة مقدماً. بشكل أساسي هذا أبسط نموذج من OneWay الربط الذي يوفر أداء أفضل في الحالات حيث قيمة المصدر لا تتغير.

لاحظ أن للكشف عن تغيير المصدر (للتطبيق على OneWay و TwoWay روابط) ، يجب على المصدر أن يقوم بتنفيذ آلية إعلام مناسبة عند تغيير خاصية مثل INotifyPropertyChanged. راجع كيفية القيام بما يلي: تطبيق إعلام تغيير الخاصية للحصول على مثال INotifyPropertyChanged التنفيذ.

Mode صفحة الخاصية توفر المزيد من المعلومات حول أوضاع الربط و مثال عن كيفية تعيين اتجاه الربط.

ماذا يشغل تحديثات المصدر

الروابط التي TwoWay أو OneWayToSource استمع إلى التغييرات في خاصية الهدف ثم انشرها إلى المصدر. ويعرف هذا بتحديث المصدر. على سبيل المثال، يمكنك تحرير النص في مربع نص لتغيير قيمة المصدر الأساسية. كما هو موضح في المقطع الأخير , اتجاه انسياب البيانات تحدده قيمة Mode خاصية الربط.

ومع ذلك، هل تحدث قيمة المصدر أثناء تحرير النص أو بعد الانتهاء من تحرير النص و اشارة الماوس بعيداً عن مربع النص ؟ UpdateSourceTrigger خاصية الربط تحدد ما يقوم بتشغيل تحديث المصدر. النقاط في الأسهم على اليمين في الشكل التالي توضح دور UpdateSourceTrigger الخاصية:

رسم تخطيطي لـ UpdateSourceTrigger

إذا كان UpdateSourceTrigger القيمة PropertyChanged ، القيمة المشار إليها بواسطة السهم الأيمن من TwoWay أو OneWayToSource يتم تحديث الارتباطات بمجرد تغيير خاصية الهدف. ومع ذلك، إذا UpdateSourceTrigger كانت القيمة LostFocus ، يتم تحديث هذه القيمة فقط مع القيمة الجديدة عندما تفقد خاصية الهدف التركيز.

تشبه Mode خاصية, مختلفة خصائص التبعية يكون له قيم افتراضية مختلفة UpdateSourceTrigger . القيمة الافتراضية لـ معظم خصائص التبعية PropertyChanged ، أثناء Text خاصية لـها قيمة افتراضية من LostFocus. وهذا يعني أن تحديثات المصدر عادة ما تحدث عندما تتغير خاصية الهدف, هذا جيد ل CheckBoxو عناصر تحكم أخرى بسيطة . ومع ذلك، بالنسبة للحقول النصية, تحديث بعد كل ضغطة مفتاح يمكن تقليل الأداء وهو يمنع المستخدم الفرصة المعتادة لإعادة الكتابة و إصلاح أخطاء الكتابة قبل الالتزام بالقيمة الجديدة. هذا هو سبب Text تحتوي الخاصية على قيمة افتراضية LostFocus بدلاً من PropertyChanged.

راجع UpdateSourceTriggerصفحة الخاصية للحصول على معلومات حول كيفية البحث عن القيمة الافتراضية ل UpdateSourceTrigger خاصية التبعية .

يوفر الجدول التالي مثال لسيناريو لكل UpdateSourceTrigger قيمة باستخدام TextBox كمثال:

قيمة UpdateSourceTrigger

عند تحديث قيمة المصدر

مثال لسيناريو عن مربع نص

LostFocus (افتراضي لـ TextBox.Text)

عندما يفقد عنصر التحكم بمربع النص التركيز

TextBox الذي يقترن بمنطق التحقق من الصحة (انظر قسم التحقق من صحة البيانات)

تم تغيير الخاصية

عندما تقوم بالطبع في TextBox

TextBox عناصر التحكم في نافذة غرفة المحادثة

واضح

عندما يستدعي التطبيق UpdateSource

TextBox عناصر التحكم في نموذج قابل للتحرير (تقوم بتحديث قيم المصدر فقط عندما يقوم المستخدم بالنقر فوق زر الإرسال)

على سبيل المثال ، راجع كيفية القيام بما يلي: التحكم عندما يحدث نص مربع النص المصدر.

إنشاء ربط

يشتمل هذا القسم على الأقسام الفرعية التالية.

  • تحديد مصدر الربط
  • تحديد المسار إلى القيمة
  • الربط و تعبير الربط

لإعادة بعض المفاهيم التي تم مناقشتها في الأقسام السابقةبإختصار, تقوم بتأسيس ربط باستخدام Binding الكائن و لكل ربط عادةً أربعة مكوّنات: ربط الهدف ، خاصية الهدف ، مصدر الربط, والمسار إلى قيمة المصدر لاستخدامها. هذا المقطع يتناول كيفية إعداد ربط.

خذ بعين الاعتبار المثال التالي، حيث كائن مصدر الربط هو فئة باسم MyData يتم تعريفه في مساحة الاسم SDKSample. لأغراض العرض التوضيحي, فئة MyDataتحتوي على خاصية السلسلة باسم ColorName ، التي تم تعيين قيمتها إلى "أحمر". لذا فإن هذا المثال يقوم بإنشاء زر له خلفية باللون أحمر.

<DockPanel
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:c="clr-namespace:SDKSample">
  <DockPanel.Resources>
    <c:MyData x:Key="myDataSource"/>
  </DockPanel.Resources>
  <DockPanel.DataContext>
    <Binding Source="{StaticResource myDataSource}"/>
  </DockPanel.DataContext>
  <Button Background="{Binding Path=ColorName}"
          Width="150" Height="30">I am bound to be RED!</Button>
</DockPanel>

لمزيد من التفاصيل حول بناء جملة تعريف الربط وللحصول على أمثلة حول كيف تقوم بإعداد ربط في التعليمات البرمجية, راجع نظرة عامة حول تعريفات الربط.

إذا قمنا بتطبيق هذا المثال على الرسم التخطيطي الأساسي الخاص بنا, يبدو الشكل الناتج كالتالي. هذا هو OneWay الربط لأن خاصية الخلفية تدعم OneWay الربط بشكل افتراضي.

رسم تخطيطي لربط البيانات

قد تتساءل لماذا يعمل هذا بالرغم من أن ColorName خاصية من نوع السلسلة و Background خاصية من نوع Brush. هذا هو نوع التحويل الافتراضي في العمل وقد تمت مناقشته في مقطع تحويل البيانات .

تحديد مصدر الربط

لاحظ أن في المثال السابق، يتم تحديد مصدر الربط عن طريق إعداد خاصية DataContext على عنصر DockPanel . Button ثم يرث قيمة DataContext من DockPanel ، التي هي عنصر الأصل. لنكرر القول, كائن مصدر الربط هو أحد مكوّنات الربط الأربعة الضرورية . لذلك، دون تحديد كائن مصدر الربط، الربط لا يفعل شيئاً.

هناك عدة طرق لتحديد كائن مصدر الربط. استخدام خاصية DataContext على عنصر الأصل مفيد عندما يتم ربط العديد من الخصائص إلى نفس المصدر. ومع ذلك، في بعض الأحيان قد يكون تعيين مصدر الربط على تعريفات الربط الفردية أكثر ملائمة. في المثال السابق, بدلاً من استخدام خاصية DataContext ، يمكنك تحديد مصدر الربط عن طريق تعيين خاصية Source مباشرة على زر تصريح الربط كما في المثال التالي:

<DockPanel.Resources>
  <c:MyData x:Key="myDataSource"/>
</DockPanel.Resources>
<Button Width="150" Height="30"
        Background="{Binding Source={StaticResource myDataSource},
                             Path=ColorName}">I am bound to be RED!</Button>

غير إعداد خاصية DataContext على عنصر مباشرةً، وراثة قيمة DataContext من عنصر الأصل (مثل الزر في المثال الأول) وتحديد بشكل صريح مصدر الربط عن طريق تعيين خاصية Source على Binding (مثل الزر في المثال الأخير) ، يمكنك أيضاً استخدام خاصية ElementName أو خاصية RelativeSource لتحديد مصدر الربط. خاصيةElementName مفيدة عندما يتم ربط بالعناصر الأخرى في التطبيق الخاص بك, كما هو الحال عند استخدام شريط التمرير لضبط عرض الزر. خاصيةRelativeSource مفيدة عند تحديد الربط في ControlTemplate أو Style. لمزيد من المعلومات، راجع كيفية القيام بما يلي: تحديد مصدر الربط.

تحديد المسار إلى القيمة

إذا كان مصدر الربط كائن, يمكنك استخدام خاصية Path لتحديد القيمة المستخدمة في الربط. إذا كنت تقوم بربط بـبيانات XML ، يمكنك استخدام خاصية XPath لتحديد القيمة. في بعض الحالات، قد ينطبق استخدام خاصية Path حتى عندما تكون بياناتك XML. على سبيل المثال، إذا كنت ترغب في الوصول إلى خاصية الاسم من XmlNode التي تم إرجاعها (نتيجة استعلام XPath) ، يجب استخدام خاصية Path بالإضافة إلى خاصية XPath .

للحصول على معلومات عن بناء الجملة وأمثلة راجع Path و XPath صفحات الخصائص.

لاحظ أنه بالرغم من أننا نقوم بتأكيد Path الي القيمة المستخدمة التي هي أحد المكونات الأربعة الضرورية للربط, في السيناريو الذي تريد ربطه بكائن بأكمله "،" القيمة المستخدمة ستكون نفس كائن مصدر الربط . وفي تلك الحالات، يكون مناسبًا ان لا تحدد Path. الرجاء مراجعة المثال التالي:

<ListBox ItemsSource="{Binding}"
         IsSynchronizedWithCurrentItem="true"/>

يستخدم المثال أعلاه ربط بناء الجملة الفارغ: الربط في هذه الحالة، ListBox يرث في DataContext من عنصر DockPanel أصل (غير مبين في هذا المثال). عند عدم تحديد المسار, يجب الربط بالكائن بأكمله بشكل افتراضي. بعبارة أخرى، في هذا المثال، المسار تم تركه لأننا نقوم بربط خاصية ItemsSource بالكائن بأكمله. (راجع مقطع الربط إلى مجموعات للحصول على مناقشة تفصيلية.)

بخلاف الربط إلى مجموعة, هذا السيناريو مفيداً أيضاً عندما تريد ربط كائن بكامله بدلاً من خاصية واحدة فقط للكائن. على سبيل المثال، إذا كان كائن مصدر ببساطة من نوع السلسلة وكنت تريد صواب ربط صواب السلسلة نفسها. السيناريو الشائع الآخر هو عندما تريد ربط عنصر إلى كائن به العديد من الخصائص.

يجب ملاحظة أنك قد تحتاج إلى تطبيق منطق مخصص بحيث يكون للبيانات معنى منضم بخاصية الهدف . قد يكون المنطق المخصص في نموذج محول مخصص (إذا كان تحويل النوع افتراضيا غير موجود). راجع تحويل البيانات للحصول على معلومات حول المحولات.

الربط و تعبير الربط

قبل الشروع في الاستخدامات و الميزات الأخرى لربط البيانات ، قد يكون مفيداً تقديم فئة BindingExpression . كما قمت بالمشاهدة في الأقسام السابقة Binding الفئة هي فئة عالية المستوى لتعريف الربط; Binding توفر الفئة العديد من الخصائص التي تسمح لك أن تحدد مواصفات الربط. فئة ذات صلة ، BindingExpression ، هو الكائن الأساسي الذي يحفظ الاتصال بين المصدر و الهدف. الربط يحتوي على كل المعلومات التي يمكن مشاركتها عبر تعبيرات الربط. BindingExpression هو تعبير مثيل لا يمكن مشاركته و يحتوي على كافة مثيل المعلومات Binding.

على سبيل المثال، يجب مراعاة ما يلي، حيث myDataObject مثيل فئة MyData ، myBinding هو مصدر كائن Binding ، ثم فئة MyData هى فئة معرفة تحتوي على خاصية السلسلة باسم MyDataProperty. هذا المثال يربط محتوى نص mytext ، مثيل TextBlock ، إلى MyDataProperty.

Dim data1 As New MyData(DateTime.Now)
Dim binding1 As New Binding("MyDataProperty")
binding1.Source = data1
Me.myText.SetBinding(TextBlock.TextProperty, binding1)
//make a new source
  MyData myDataObject = new MyData(DateTime.Now);      
  Binding myBinding = new Binding("MyDataProperty");
  myBinding.Source = myDataObject;
  myText.SetBinding(TextBlock.TextProperty, myBinding);

يمكنك استخدام نفس الكائن myBinding لإنشاء روابط أخرى. على سبيل المثال، يمكنك استخدام كائن myBinding لربط محتوى النص في خانة اختيار إلى MyDataProperty. في هذا السيناريو، يكون هناك مثيلين من BindingExpression مشاركة كائن myBinding .

كائنBindingExpression يمكن الحصول عليه من خلال القيمة المرجعة للاتصال GetBindingExpression على كائن ربط-البيانات . توضح المواضيع التالية بعض استخدامات فئة BindingExpression :

تحويل البيانات

في المثال السابق، يكون الزر أحمر لأن Background خاصيته ترتبط بخاصية السلسلة بقيمة "أحمر". يعمل هذا بسبب وجود محول نوع على نوع Brush لتحويل قيمة السلسلة إلى Brush.

لإضافة هذه المعلومات إلى الشكل في مقطع إنشاء ربط ، يبدو الرسم التخطيطي كالتالي:

مخطط ربط البيانات

ومع ذلك ، ماذا لو بدلاً من وجود خاصية من نوع السلسلة يكون كائن مصدر الربط الخاص بك لديه خاصية لون من نوع Color ؟ في هذه الحالة من أجل الربط أن يعمل عليك أولاً تحويل قيمة خاصية لون إلى الشيء الذي Background تقبله الخاصية. قد تحتاج إلى إنشاء محول مخصص عن طريق تطبيق واجهة IValueConverter كما في المثال التالي:

    <ValueConversion(GetType(Color), GetType(SolidColorBrush))>
    Public Class ColorBrushConverter
        Implements IValueConverter
        Public Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.Convert
            Dim color As Color = CType(value, Color)
            Return New SolidColorBrush(color)
        End Function

        Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
            Return Nothing
        End Function
    End Class
[ValueConversion(typeof(Color), typeof(SolidColorBrush))]
public class ColorBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Color color = (Color)value;
        return new SolidColorBrush(color);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
}

IValueConverter صفحة المرجع توفر مزيد من المعلومات.

يستخدم الآن المحول المخصص بدلاً من التحويل الافتراضي, و ‏‫الرسم التخطيطي الخاص بنا يبدو مثل هذا:

رسم تخطيطي لربط البيانات

‏‫لنكرر القول, التحويلات الافتراضية قد تتوفر وذلك بسبب محولات النوع الموجودة في النوع الذي يتم الربط به . يعتمد هذا السلوك على محولات النوع المتوفرة في الهدف. إذا في شك، قم بإنشاء‬ المحول الخاص بك.

فيما يلي بعض السيناريوهات النموذجية حيث من المنطقي تنفيذ محول البيانات :

  • يجب عرض البيانات الخاصة بك بشكل مختلف, استناداً إلى الثقافة. على سبيل المثال، قد تحتاج إلى تنفيذ محول عملة أو محول تقويم تاريخ/وقت استناداً إلى القيم أو المعايير المستخدمة في ثقافة معينة.

  • غير مقصود بالضرورة تغيير قيمة نص لخاصية بسبب البيانات التي يتم استخدامها ، ولكن بدلاً من ذلك يكون الغرض تغيير قيمة أخرى, مثل مصدر صورة، أو لون أو نمط لعرض النص. يمكن استخدام المحولات في هذا المثيل عن طريق تحويل ربط خاصية قد لا تبدو مناسبة, مثل ربط حقل نص إلى خلفية خلية جدول.

  • أكثر من عنصر تحكم واحد أو خصائص عدة لعناصر التحكم, منضمة إلى نفس البيانات. في هذه الحالة، الربط الأساسي قد يعرض النص فقط، بينما الروابط الأخرى تعالج مشكلات عرض معينة ولكن لا تزال تستخدم نفس الربط كـ مصدر المعلومات.

  • حتى الآن ونحن لم نناقش بعد MultiBinding ، حيث خاصية الهدف تحتوي على مجموعة من الروابط. في حالة MultiBinding استخدم مخصص IMultiValueConverter لإعطاء قيمة نهائية من قيم الروابط. على سبيل المثال، قد يكون اللون محسوب من قيم أحمر, أزرق و أخضر والتي يمكن أن تكون قيم من كائنات مصدر الربط نفسها أو أخرى مختلفة . راجع MultiBinding فئة صفحة لأمثلة و معلومات.

الربط إلى مجموعة

يشتمل هذا القسم على الأقسام الفرعية التالية.

  • كيفية تنفيذ المجموعات
  • طرق عرض المجموعة

كائن مصدر الربط يمكن معاملته ككائن واحد له خصائص تحتوي على البيانات أو كمجموعة بيانات من كائنات متعددة الأشكال التي غالباً ما يتم تجميعها معًا (مثل نتيجة استعلام من قاعدة بيانات). حتى الآن قمنا فقط بمناقشة الربط إلى كائنات واحدة, على الرغم من ذلك، الربط بمجموعة بيانات هو سيناريو شائع. على سبيل المثال، سيناريو شائع استخدام ItemsControl مثل ListBox ، ListView, أو TreeView لعرض مجموعة بيانات, مثل في التطبيق الموضح في مقطع ما المقصود بربط البيانات ؟ .

ولحسن الحظ، مازال تطبيق الرسم التخطيطي الأساسي الخاص بنا متاح. إذا كنت تقوم بربط ItemsControl إلى مجموعة, الرسم التخطيطي يبدو مثل:

الرسم التخطيطي ItemsControl لربط البيانات

كما هو موضح في الرسم التخطيطي, لربط ItemsControl إلى كائن مجموعة, خاصية ItemsSource هى الخاصية المستخدمة. يمكنك اعتبار خاصية ItemsSource أنها محتوى ItemsControl. لاحظ أن الربط OneWay لأن خاصية ItemsSource تدعم OneWay الربط بشكل افتراضي.

كيفية تنفيذ المجموعات

يمكن الإضافة إلى أي مجموعة تقوم بتنفيذ واجهة IEnumerable . ومع ذلك، لإعداد ارتباطات حيوية بحيث عمليات الإدراج أو الحذف في المجموعة تقوم بتحديث واجهة المستخدم تلقائياً, يجب أن تقوم المجموعة بتنفيذ واجهة INotifyCollectionChanged . هذه الواجهة تقوم بالكشف عن أحد الأحداث التي يجب أن يتم تشغيلها عند تغير المجموعة الأساسية.

WPF يوفر فئة ObservableCollection<T> و هو تطبيق مضمن لتجميع البيانات الذي يعرض الواجهةINotifyCollectionChanged . لاحظ أن لدعم نقل قيم البيانات بشكل كامل من كائنات المصدر إلى الأهداف, كل كائن في مجموعتك يدعم خصائص يمكن ربطها أن يقوم أيضاً بتنفيذ واجهة INotifyPropertyChanged . لمزيد من المعلومات، راجع نظرة عامة حول مصادر الربط.

قبل تطبيق المجموعة الخاصة بك، يمكنك استخدام ObservableCollection<T> أو أحد فئات المجموعة الموجودة مثل List<T> ، Collection<T> ، و BindingList<T> ، بين العديد من الآخرين. إذا كان لديك سيناريو متقدم وكنت تريد تنفيذ المجموعة الخاصة بك, خذ في الاعتبار استخدام IList ، والتي توفر مجموعة غير عامة من الكائنات التي يمكن الوصول لها بشكل فردي بواسطة الفهرس و بالتالي أفضل أداء.

طرق عرض المجموعة

ما إن ItemsControl منضم إلى تجميع البيانات, قد تحتاج إلى فرز أو تصفية أو تجميع البيانات. وللقيام بذلك، يمكنك استخدام طرق عرض المجموعة, وهي الفئات التي تقوم بتنفيذ الواجهة ICollectionView .

يشتمل هذا القسم على الأقسام الفرعية التالية.

  • ما هي طرق عرض المجموعة ؟
  • كيفية إنشاء طريقة عرض
  • الفرز
  • تصفية
  • التجميع
  • مؤشرات العنصر الحالي
  • رئيسي-تفصيلي سيناريو الربط

ما هي طرق عرض المجموعة ؟

طريقة عرض مجموعة هي طبقة من مجموعة مصدر الربط تسمح لك بالتنقل وعرض مصدر المجموعة بناءً على استعلامات الفرز, التصفية, و التجميع, دون الحاجة إلى تغيير مجموعة المصادر الأساسية نفسها. طريقة عرض المجموعة أيضاً تحتفظ بمؤشر إلى العنصر الحالي في المجموعة. إذا مجموعة المصدر قامت بتنفيذ INotifyCollectionChanged الواجهة, التغييرات قبل الحدث CollectionChanged يتم نشرها إلى طرق العرض.

لأن طرق العرض لا تقوم بتغيير مجموعات المصدر الأساسية ، يمكن لكل مجموعة مصدر أن يكون لديها طرق عرض متعددة مقترنة بها . على سبيل المثال، قد يكون لديك مجموعة كائنات المهام. مع استخدام طرق العرض, يمكنك عرض نفس البيانات بطرق مختلفة. على سبيل المثال، على الجانب الأيسر من الصفحة الخاصة بك قد تحتاج لإظهار المهام التي تم فرزها حسب الأولوية, و على الجانب الأيمن, مجمّعة حسب المنطقة.

كيفية إنشاء طريقة عرض

واحدة من طرق إنشاء و استخدام طريقة العرض هي إنشاء مثيل لكائن العرض مباشرة ومن ثم استخدامه كمصدر الربط. على سبيل المثال، ضع في الاعتبار ربط البيانات DemoData ربط العرض التوضيحي التطبيق موضح في مقطع ما المقصود بربط البيانات ؟ . يتم تنفيذ التطبيق بحيث ListBox بربطه إلى طريقة عرض لتجميع البيانات بدلاً من تجميع البيانات مباشرة. يتم استخراج المثال التالي من التطبيق العرض التوضيحي لربط البيانات. CollectionViewSource فئة Extensible Application Markup Language (XAML) الوكيل للفئة التي ترث من CollectionView. في هذا المثال, Source من طريقة العرض منضم إلى مجموعة AuctionItems (من نوع ObservableCollection<T>)من كائن التطبيق الحالي.

<Window.Resources>


...


<CollectionViewSource 
      Source="{Binding Source={x:Static Application.Current}, Path=AuctionItems}"   
      x:Key="listingDataView" />


...


</Window.Resources>

المورد listingDataView ثم تخدم كمصدر الربط لعناصر في التطبيق, مثل ListBox:

<ListBox Name="Master" Grid.Row="2" Grid.ColumnSpan="3" Margin="8"
    ItemsSource="{Binding Source={StaticResource listingDataView}}">


...


</ListBox>

لإنشاء طريقة عرض أخرى عن نفس المجموعة ، يمكنك إنشاء مثيل آخر CollectionViewSource و إعطاءها اسم مختلف x:Key .

يعرض الجدول التالي طرق عرض datatypes التي يتم إنشاؤها كطريقة عرض افتراضية للمجموعة أو عن طريق CollectionViewSource استناداً على نوع مجموعة المصدر.

نوع مجموعة المصدر

نوع طريقة عرض المجموعة

ملاحظات

IEnumerable

نوع داخلي يعتمد على CollectionView

لا يمكن تجميع العناصر.

IList

ListCollectionView

أسرع.

IBindingList

BindingListCollectionView

باستخدام طريقة عرض افتراضية

تحديد طريقة عرض المجموعة كمصدر ربط هو أحد الطرق لإنشاء واستخدام طريقة عرض المجموعة. WPF أيضاً يقوم بإنشاء طريقة عرض افتراضية للمجموعة لكل مجموعة يتم استخدامها كمصدر ربط. في حالة الربط مباشرة إلى مجموعة, WPF يقوم بالربط إلى طريقة العرض الافتراضية الخاصة به. لاحظ مشاركة هذا العرض الافتراضي بواسطة كل عمليات الربط إلى نفس المجموعة, حتى إجراء تغيير إلى طريقة عرض افتراضية بواسطة عنصر تحكم منضم أو تعليمات برمجية (مثل الفرز أو تغيير مؤشر العنصر الحالي, يتم مناقشته لاحقاً) تنعكس على كافة الارتباطات الأخرى إلى نفس المجموعة.

للحصول على طريقة العرض الافتراضية, استخدم أسلوب GetDefaultView. على سبيل المثال ، راجع كيفية القيام بما يلي: الحصول على طريقة العرض الافتراضية لتجميع البيانات.

طرق عرض المجموعة ب DataTables ADO.NET

لتحسين الأداء, طرق عرض المجموعة ل ADO.NET DataTable أو DataView تفوض الكائنات الفرز والتصفية إلى DataView. يؤدي ذلك إلى مشاركة الفرز والتصفية عبر كافة طرق عرض مجموعة مصدر البيانات. لتمكين كل طريقة عرض مجموعة الفرز و التصفية بشكل مستقل, يجب تهيئة كل طريقة عرض مجموعة بالكائن الخاص به DataView .

الفرز

كما ذكر من قبل، طرق العرض يمكنها تطبيق ترتيب فرز لمجموعة. كما هو موجود في المجموعة الأساسية, البيانات الخاصة بك قد أو قد لا تكون مضمّنة, لها ترتيب ذات صلة. تسمح لك طريقة عرض المجموعة أن تفرض له ترتيب أو تغير الترتيب الافتراضي, استناداً إلى معايير المقارنة التي توفرها. لأنها طريقة عرض للبيانات تستند إلى العميل، سيناريو شائع أن المستخدم قد يريد فرز أعمدة من جدولي البيانات لكل قيمة توافق مع العمود. باستخدام طرق العرض ، هذا الفرز حسب المستخدم يمكن تطبيقه ، مرة أخرى بدون إجراء أية تغييرات للمجموعة الأساسية أو حتى الحاجة لإعادة طلب محتوى مجموعة. على سبيل المثال ، راجع كيفية القيام بما يلي: فرز عمود GridView متى تم النقر على رأس العمود.

يظهر المثال التالي منطق الفرز "فرز حسب الفئة و التاريخ" CheckBox للتطبيق واجهة المستخدم في مقطع ما المقصود بربط البيانات؟ :

private void AddSorting(object sender, RoutedEventArgs args)
{
    // This sorts the items first by Category and within each Category,
    // by StartDate. Notice that because Category is an enumeration,
    // the order of the items is the same as in the enumeration declaration
    listingDataView.SortDescriptions.Add(
        new SortDescription("Category", ListSortDirection.Ascending));
    listingDataView.SortDescriptions.Add(
        new SortDescription("StartDate", ListSortDirection.Ascending));
}

تصفية

طرق العرض يمكنها أيضاً تطبيق عامل تصفية على مجموعة. وهذا يعني أنه على الرغم من وجود صنف في المجموعة، طريقة العرض المعينة هذه مقصود بها فقط إظهار فرعية معيّنة من المجموعة الكاملة. قد تقوم بالتصفية على شرط في البيانات. على سبيل المثال، كما تم بواسطة التطبيق في مقطع ما المقصود بربط البيانات ، "Show only bargains" CheckBox يحتوي على منطق لتصفية العناصر التي تكلف 25 ر.س أو أكثر. يتم تنفيذ التعليمات البرمجية التالية لضبط ShowOnlyBargainsFilter Filter معالج الأحداث عند تحديد CheckBox:

listingDataView.Filter += new FilterEventHandler(ShowOnlyBargainsFilter);

قام معالج الأحداث ShowOnlyBargainsFilter بتنفيذ التالي:

private void ShowOnlyBargainsFilter(object sender, FilterEventArgs e)
{
    AuctionItem product = e.Item as AuctionItem;
    if (product != null)
    {
        // Filter out products with price 25 or above
        if (product.CurrentPrice < 25)
        {
            e.Accepted = true;
        }
        else
        {
            e.Accepted = false;
        }
    }
}

إذا كنت تستخدم أحد CollectionView الفئات مباشرةً بدلاً من CollectionViewSource ، يمكنك استخدام خاصية Filter لتعيين رد الاتصال. على سبيل المثال ، راجع كيفية القيام بما يلي: تصفية البيانات في عرض.

التجميع

عدا الفئة الداخلية التي تعرض IEnumerable مجموعة, كافة طرق عرض المجموعات تدعم وظيفة التجميع التي تسمح للمستخدم تقسيم المجموعة في طريقة عرض المجموعة إلى مجموعات منطقية. يمكن أن المجموعات صريحة حيث يوفر للمستخدم قائمة المجموعات, أو بشكل ضمني، حيث يتم إنشاء المجموعات بشكل حيوي استناداً صواب.

يظهر المثال التالي المنطق "تجميع حسب الفئة" CheckBox:

// This groups the items in the view by the property "Category"
PropertyGroupDescription groupDescription = new PropertyGroupDescription();
groupDescription.PropertyName = "Category";
listingDataView.GroupDescriptions.Add(groupDescription);

لمثال تجميع آخر, راجع كيفية القيام بما يلي: مجموعة عناصرفى ListView التي تنفذ GridView.

مؤشرات العنصر الحالي

تدعم طرق العرض أيضاً الفكرة من عنصر حالي. يمكنك التنقل خلال الكائنات الموجودة في طريقة عرض المجموعة. عند الانتقال, تقوم بنقل مؤشر الصنف الذي يسمح لك باسترداد الكائن الموجود في ذلك الموقع المعين في المجموعة. على سبيل المثال ، راجع كيفية القيام بما يلي: النتقل عبر الكائنات في CollectionView الخاص بالبيانات.

لأن WPF تقوم بربط مجموعة فقط باستخدام طريقة عرض (إما طريقة العرض التي تحددها أو طريقة العرض الافتراضية للمجموعة) ، لكل عمليات الربط إلى مجموعات تحتوي على مؤشر الصنف الحالي. عند الربط إلى طريقة عرض "، حرف الخط المائل ("/") في القيمة Path تعين الصنف الحالي في طريقة العرض. في المثال التالي سياق البيانات هو طريقة عرض مجموعة. السطر الأول يربط بالمجموعة. يرتبط السطر الثاني بالصنف الحالي في المجموعة. السطر الثالث يرتبط بخاصية Description للصنف الحالي في المجموعة.

<Button Content="{Binding }" />
<Button Content="{Binding Path=/}" />
<Button Content="{Binding Path=/Description}" /> 

المائلة و خاصية بناء الجملة يمكن أن تكدس لاجتياز هيكلي المجموعات. يرتبط المثال التالي بالصنف الحالي في مجموعة باسم Offices ، وهي خاصية للصنف الحالي من مجموعة المصدر.

<Button Content="{Binding /Offices/}" />

مؤشر الصنف الحالي يمكن أن يتأثر بأي فرز أو تصفية يتم تطبيقه على المجموعة. يحتفظ الفرز بمؤشر الصنف الحالي على العنصر الأخير الذي تم تحديده, ولكن طريقة عرض المجموعة الآن يتم إعادة تحديدها حوله. (ربما الصنف المحدد كان في بداية القائمة من قبل, ولكن الآن الصنف المحدد قد يكون في مكان ما في الوسط.) التصفية تحتفظ بالعنصر المحدد إذا كان ذلك التحديد باقى في طريقة العرض بعد التصفية. وإلا، مؤشر الصنف الحالي يتم تعيينه إلى أول صنف في طريقة عرض المجموعة المصفاة.

رئيسي-تفصيلي سيناريو الربط

فكرة الصنف الحالي مفيدة ليس فقط من أجل التنقل بين الاصناف الموجودة في مجموعة ، ولكن أيضاً لسيناريو الربط رئيسي-تفصيلي. خذ بعين الاعتبار التطبيق واجهة المستخدم في مقطع ما المقصود بربط بيانات مرة أخرى. في هذا التطبيق, التحديد داخل ListBox تحدد المحتوى في ContentControl. لوضعه بطريقة أخرى، عند ListBox تحديد صنف ContentControl يظهر تفاصيل الصنف المحدد.

يمكنك تنفيذ سيناريو رئيسي-تفصيلي ببساطة عند وجود اثنين أو أكثر من عناصر التحكم المنضمة إلى نفس طريقة العرض. يظهر المثال التالي من العرض التوضيحي لربط البيانات العلامات ListBox و ContentControl راجع التطبيق واجهة المستخدم في مقطع ما هو ربط البيانات؟ :

<ListBox Name="Master" Grid.Row="2" Grid.ColumnSpan="3" Margin="8"
    ItemsSource="{Binding Source={StaticResource listingDataView}}">


...


</ListBox>


...


<ContentControl Name="Detail" Grid.Row="3" Grid.ColumnSpan="3" 
        Content="{Binding Source={StaticResource listingDataView}}" 
        ContentTemplate="{StaticResource detailsProductListingTemplate}" 
        Margin="9,0,0,0"/>

لاحظ أن كل من عناصر التحكم مرتبطة بنفس المصدر listingDataViewمورد ثابت (راجع تعريف هذا المورد في كيفية إنشاء مقطع طريقة عرض ). يعمل هذا لأن عند كائن نوع مفرد ( ContentControl في هذه الحالة) منضم إلى طريقة عرض، فإنه تلقائياً يربط ب CurrentItem من طريقة العرض. لاحظ أن CollectionViewSource كائنات تلقائياً تقوم بمزامنة العملة و التحديد. إذا كان عنصر تحكم القائمة غير مرتبط بالكائن CollectionViewSource كما في هذا المثال، ثم عليك تعيين IsSynchronizedWithCurrentItem خاصية true ليعمل.

للحصول على أمثلة آخري، راجع كيفية القيام بما يلي: ربط مجموعة و عرض معلومات اعتماداً على الاختيار و كيفية القيام بما يلي: استخدام نمط رئيسي تفصيلي مع البيانات ذات التسلسل الهرمي.

قد تكون لاحظت أن المثال أعلاه يستخدم قالب. في الحقيقة، البيانات قد لا يتم عرضها بالطريقة التي نتمناها بدون استخدام قوالب (التي استخدمتها بشكل صريح عن طريق ContentControl و الأخرى المستخدمة ضمنيًا من قبل ListBox). نقوم الآن بالأنتقال إلى قلب البيانات في المقطع التالي.

قلب البيانات

بدون استخدام قوالب البيانات, التطبيق الخاص بنا واجهة المستخدم في مقطع ما المقصود بربط البيانات سيبدو كالتالي:

شكل توضيحي لربط البيانات دون قوالب بيانات

كما هو موضح في المثال الموجود في مقطع السابق، كلا ListBoxعنصر التحكم و ContentControlالمرتبطة إلى الكائن مجموعة كاملة (أو عرض وبشكل أكثر تحديداً، فوق الكائن مجموعة) AuctionItem s. دون الحصول على إرشادات خاصة حول ل dهوplay جمع البيانات، ListBoxهو dهوplaying تمثيل سلسلة لكل كائن في المجموعة الأساسية و ContentControlهو dهوplaying تمثيل سلسلة الكائن هو مرتبطة ب.

إلى حل هذه المشكلة، قم بتعريف تطبيق DataTemplates. As shown in the example in the previous section, the ContentControl explicitly uses the detailsProductListingTemplate DataTemplate. ListBox يستخدم عنصر التحكم التالي ضمنيًا DataTemplate عند عرض AuctionItem الكائنات في المجموعة:

<DataTemplate DataType="{x:Type src:AuctionItem}">
    <Border BorderThickness="1" BorderBrush="Gray"
            Padding="7" Name="border" Margin="3" Width="500">
        <Grid>
          <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
          </Grid.RowDefinitions>
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="86"/>
            <ColumnDefinition Width="*"/>
          </Grid.ColumnDefinitions>

            <Polygon Grid.Row="0" Grid.Column="0" Grid.RowSpan="4"
                     Fill="Yellow" Stroke="Black" StrokeThickness="1"
                     StrokeLineJoin="Round" Width="20" Height="20"
                     Stretch="Fill"
                     Points="9,2 11,7 17,7 12,10 14,15 9,12 4,15 6,10 1,7 7,7"
                     Visibility="Hidden" Name="star"/>

            <TextBlock Grid.Row="0" Grid.Column="1" Margin="0,0,8,0"
                       Name="descriptionTitle"
                       Style="{StaticResource smallTitleStyle}">Description:</TextBlock>
            <TextBlock Name="DescriptionDTDataType" Grid.Row="0" Grid.Column="2" 
                Text="{Binding Path=Description}" 
                Style="{StaticResource textStyleTextBlock}"/>

            <TextBlock Grid.Row="1" Grid.Column="1" Margin="0,0,8,0"
                       Name="currentPriceTitle"
                       Style="{StaticResource smallTitleStyle}">Current Price:</TextBlock>
            <StackPanel Grid.Row="1" Grid.Column="2" Orientation="Horizontal">
                <TextBlock Text="$" Style="{StaticResource textStyleTextBlock}"/>
                <TextBlock Name="CurrentPriceDTDataType" 
                    Text="{Binding Path=CurrentPrice}" 
                    Style="{StaticResource textStyleTextBlock}"/>
            </StackPanel>
        </Grid>
    </Border>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Path=SpecialFeatures}">
            <DataTrigger.Value>
                <src:SpecialFeatures>Color</src:SpecialFeatures>
            </DataTrigger.Value>
          <DataTrigger.Setters>
            <Setter Property="BorderBrush" Value="DodgerBlue" TargetName="border" />
            <Setter Property="Foreground" Value="Navy" TargetName="descriptionTitle" />
            <Setter Property="Foreground" Value="Navy" TargetName="currentPriceTitle" />
            <Setter Property="BorderThickness" Value="3" TargetName="border" />
            <Setter Property="Padding" Value="5" TargetName="border" />
          </DataTrigger.Setters>
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=SpecialFeatures}">
            <DataTrigger.Value>
                <src:SpecialFeatures>Highlight</src:SpecialFeatures>
            </DataTrigger.Value>
            <Setter Property="BorderBrush" Value="Orange" TargetName="border" />
            <Setter Property="Foreground" Value="Navy" TargetName="descriptionTitle" />
            <Setter Property="Foreground" Value="Navy" TargetName="currentPriceTitle" />
            <Setter Property="Visibility" Value="Visible" TargetName="star" />
            <Setter Property="BorderThickness" Value="3" TargetName="border" />
            <Setter Property="Padding" Value="5" TargetName="border" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

مع استخدام تلك الاثنين DataTemplate s، UI الناتج هو الذي يظهر في مقطع ما المقصود بربط البيانات . كما يمكنك مشاهدة من ذلك اللقطة, بالإضافة إلى السماح لك بوضع البيانات في عناصر التحكم DataTemplate s تسمح لك بتعريف صور مقنعة للبيانات الخاصة بك. على سبيل المثال، DataTrigger s تُستخدم في أعلاه DataTemplate بحيث s AuctionItemمع SpecialFeatures قيمة تمييزسيتم عرضه بحد برتقالي و نجمة.

للحصول على مزيد من المعلومات حول قوالب البيانات ، راجع نظرة عامة حول قولبة البيانات.

التحقق من صحة البيانات

يشتمل هذا القسم على الأقسام الفرعية التالية.

  • اقتران قواعد التحقق من الصحة بالربط
  • توفير ملاحظات مرئية
  • عملية التحقق من الصحة

معظم التطبيقات التي تستغرق الحاجة لإدخال مدخلات من المستخدم, يحتاج أن يكون لديك منطق التحقق من صحة للتأكد من أن المستخدم ادخل المعلومات المتوقعة. التحقق من الصحة يمكن أن يستند إلى النوع ، النطاق أو التنسيق أو المتطلبات الأخرى الخاصة بالتطبيق. يتناول هذا المقطع كيفية عمل التحقق من صحة البيانات في WPF.

اقتران قواعد التحقق من الصحة بالربط

WPF يسمح نموذج ربط البيانات إقران ValidationRules بالكائن الخاص بك Binding . على سبيل المثال، يرتبط المثال التالي على TextBoxإلى خاصية مسماة StartPriceو إضافة ExceptionValidationRuleالكائن إلى Binding.ValidationRulesالخاصية.

<TextBox Name="StartPriceEntryForm" Grid.Row="2" Grid.Column="1"
    Style="{StaticResource textStyleTextBox}" Margin="8,5,0,5">
  <TextBox.Text>
    <Binding Path="StartPrice" UpdateSourceTrigger="PropertyChanged">
      <Binding.ValidationRules>
        <ExceptionValidationRule />
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>

ValidationRule الكائن يتحقق ما إذا كانت قيمة الخاصية صالحة. WPF يتضمن نوعين من الكائنات المضمنةValidationRule :

  • ExceptionValidationRule التحقق من الاستثناءات التي تطرح أثناء تحديث خاصية مصدر الربط. في المثال السابق، StartPriceهو من النوع الصحيح. عندما يقوم المستخدم بإدخال قيمة لا يمكن تحويلها إلى عددًا صحيحًا, يتم إلقاء استثناء ، يسبب ذلك وضع علامة على الربط على أنها غير صالحة. بناء الجملة البديل إلى إعداد ExceptionValidationRule بشكل صريح يتم تعيين ValidatesOnExceptions خاصية إلى true على الخاص بك Binding أو MultiBinding الكائن.

  • DataErrorValidationRule الكائن الذي يتحقق من الأخطاء التي تتم عند تشغيل الحدث قبل تنفيذ IDataErrorInfo الواجهة. لمزيد من المعلومات حول استخدام قاعدة التحقق من الصحة هذه، راجع DataErrorValidationRule. بناء الجملة البديل إلى إعداد DataErrorValidationRule بشكل صريح يتم تعيين ValidatesOnDataErrors خاصية إلى true على الخاص بك Binding أو MultiBinding الكائن.

يمكنك أيضاً إنشاء قاعدة التحقق من الصحة الخاصة بواسطة اشتقاق ValidationRuleمن الفئة وتنفيذ أسلوب Validate . يظهر المثال التالي القاعدة المستخدمة من قبل إدخال قائمة المنتجات "تاريخ البدء" TextBox من مقطع "ما هو ربط البيانات " ؟ :

class FutureDateRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        DateTime date;
        try
        {
            date = DateTime.Parse(value.ToString());
        }
        catch (FormatException)
        {
            return new ValidationResult(false, "Value is not a valid date.");
        }
        if (DateTime.Now.Date > date)
        {
            return new ValidationResult(false, "Please enter a date in the future.");
        }
        else
        {
            return ValidationResult.ValidResult;
        }
    }
}

StartDateEntryForm TextBox يستخدم هذا FutureDateRule ، كما هو موضح في المثال التالي:

<TextBox Name="StartDateEntryForm" Grid.Row="3" Grid.Column="1" 
    Validation.ErrorTemplate="{StaticResource validationTemplate}" 
    Style="{StaticResource textStyleTextBox}" Margin="8,5,0,5">
    <TextBox.Text>
        <Binding Path="StartDate" UpdateSourceTrigger="PropertyChanged" 
            Converter="{StaticResource dateConverter}" >
            <Binding.ValidationRules>
                <src:FutureDateRule />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

لاحظ أنه نظرًا لأن UpdateSourceTrigger قيمة PropertyChanged ، مشغّل الربط يقوم بتحديث القيمة عند كل ضغط مفاتيح, الذي يعني أنه أيضاً يقوم بالتدقيق في كل قاعدة في ValidationRules المجموعة على كل ضغط مفاتيح. نحن نقوم بمناقشة هذا بشكل أكبر في مقطع "عملية التحقق من صحة" .

توفير ملاحظات مرئية

إذا قام المستخدم بإدخال قيمة غير صالحة, فقد تحتاج إلى توفير بعض الملاحظات حول الخطأ في التطبيق واجهة المستخدم. طريقة واحدة لتوفير الملاحظات بأن يتم تعيين Validation.ErrorTemplate الخاصية المرفقة إلى مخصص ControlTemplate. كما هو موضح في القسم الفرعي السابق, في StartDateEntryForm TextBox يستخدم ErrorTemplate تسمى validationTemplate. يظهر المثال التالي تعريف validationTemplate :

<ControlTemplate x:Key="validationTemplate">
  <DockPanel>
    <TextBlock Foreground="Red" FontSize="20">!</TextBlock>
    <AdornedElementPlaceholder/>
  </DockPanel>
</ControlTemplate>

AdornedElementPlaceholder عنصر يقوم بتحديد أين يجب وضع عنصر التحكم المقلد.

بالإضافة إلى ذلك، يمكنك أيضاً استخدام ToolTip لعرض رسالة الخطأ. StartDateEntryForm و StartPriceEntryForm TextBoxيستخدما النمط textStyleTextBox, which creates a ToolTip‎الذي يعرض رسالة الخطأ. يظهر المثال التالي تعريف textStyleTextBox : The خاصية مرفقة Validation.HasError يتم trueعندما يكون واحد أو أكثر من الارتباطات في خصائص العنصر المنضم في خطأ.

<Style x:Key="textStyleTextBox" TargetType="TextBox">
  <Setter Property="Foreground" Value="#333333" />
  <Setter Property="MaxLength" Value="40" />
  <Setter Property="Width" Value="392" />
  <Style.Triggers>
    <Trigger Property="Validation.HasError" Value="true">
      <Setter Property="ToolTip"
        Value="{Binding RelativeSource={RelativeSource Self},
                        Path=(Validation.Errors)[0].ErrorContent}"/>
    </Trigger>
  </Style.Triggers>
</Style>

مع ErrorTemplate المخصصة و ToolTip، تظهر StartDateEntryForm TextBox مثل الشكل التالي عندما يوجد خطأ في التحقق من الصحة:

خطأ في التحقق من صحة ربط البيانات

إذا كان Binding الخاص بك يحتوي على قواعد التحقق من الصحة المقترنة ولكنك لم تقم بتحديد ErrorTemplate على التحكم المحدود، ErrorTemplate افتراضي, سيتم استخدامه لإعلام المستخدمين عندما يكون هناك خطأ في التحقق من الصحة. ErrorTemplate الافتراضي عبارة عن قالب عنصر التحكم الذي يعرف حد أحمر في طبقة التقليد. مع ErrorTemplate الافتراضي و ToolTip، تظهر واجهة المستخدم of the StartPriceEntryForm TextBoxمثل الشكل التالي عندما يوجد خطأ في التحقق من الصحة:

خطأ في التحقق من صحة ربط البيانات

للحصول على مثال حول توفير منطق التحقق من صحة لكافة عناصر التحكم في مربع حوار, راجع مقطع مربع حوار مخصص في نظرة عامة حول مربعات الحوار.

عملية التحقق من الصحة

التحقق من الصحة يحدث عادةً عند نقل قيمة الهدف إلى خاصية مصدر الربط. يحدث هذا على TwoWay و OneWayToSource روابط. ‏‫‏‫لنكرر القول، ما يؤدي إلى تحديث مصدر يعتمد على قيمة خاصية UpdateSourceTrigger ، كما هو موضح في مقطع ما مشغلات تحديثات المصدر .

يلي وصف عملية التحقق من الصحة . يجب ملاحظة إذا كان خطأ التحقق من الصحة أو نوع آخر من الاخطاء يحدث في أي وقت أثناء هذه العملية, يجب تعليق العملية.

  1. مشغّل الربط يتحقق إذا كان هناك أي ValidationRule مخصصة, الكائنات المعرفة ValidationStep يتم تعيينها إلى RawProposedValue ذلك Binding, وفي هذه الحالة يقوم باستدعاء Validate الأسلوب لكل ValidationRule حتى إحداهما يصطدم بخطأ أو حتى يمر كله.

  2. مشغّل الربط ثم يقوم باستدعاء المحول في حالة وجود واحدة.

  3. إذا نجح المحوّل, مشغّل الربط يقوم بالتحقق من إذا كان هناك أي ValidationRule مخصصة, الكائنات المعرفة ValidationStepتم تعيينها إلى ConvertedProposedValueذلك Binding, وفي هذه الحالة يقوم باستدعاء Validate method on each ValidationRule ValidationStep الأسلوب على كل ConvertedProposedValue تى إحداهما يتم تشغيله إلى خطأ أو حتى يمر كله.

  4. مشغّل الربط يقوم بتعيين خاصية المصدر.

  5. مشغّل الربط يتحقق إذا كان هناك أي ValidationRule مخصصة, الكائنات المعرفة ValidationStepيتم تعيينها إلى UpdatedValue ذلكt Binding‎, وفي هذه الحالة يقوم باستدعاء Validate الأسلوب لكل ValidationRule ValidationStep UpdatedValue حتى إحداهما يصطدم بخطأ أو حتى يمر كله. إذا DataErrorValidationRuleهو المقترنة بربط وبه ValidationStepهو تعيين إلى الإعدادات الافتراضية، UpdatedValue، DataErrorValidationRuleهو التحقق من القيم بالموضع هو نقطة. هذا هو أيضا النقطة عند الروابط التي تحتوي على ValidatesOnDataErrorsالتعيين إلى trueيتم محدد.

  6. مشغّل الربط يتحقق إذا كان هناك أي ValidationRule مخصصة, الكائنات المعرفة ValidationStepيتم تعيينها إلى CommittedValue ذلكt Binding‎, وفي هذه الحالة يقوم باستدعاء Validate الأسلوب لكل ValidationRule ValidationStep CommittedValue حتى إحداهما يصطدم بخطأ أو حتى يمر كله.

إذا ValidationRule لا يمرر في أي وقت خلال هذه العملية, مشغل الربط يقوم بإنشاء ValidationError الكائن وإضافته إلى Validation.Errors مجموعة العنصر المنضم. قبل مشغل الربط أن يقوم بتشغيل ValidationRule كائنات في أي مرحلة معطى, تزيل أي ValidationError التي تمت إضافتها إلى Validation.Errors  خاصية مرفقةمن العنصر المنضم أثناء تلك الخطوة. على سبيل المثال، إذا ValidationRule له ValidationStep يعين UpdatedValue فشل, في المرة التالية التي تحدث عملية التحقق من الصحة, مشغّل الربط يقوم بإزالة ValidationError مباشرة قبل استدعاء أي ValidationRule له ValidationStep يعين UpdatedValue.

عند Validation.Errors غير فارغة Validation.HasError عيين الخاصية المرفقة للعنصر إلى true. أيضاً، إذا NotifyOnValidationError خاصية من Bindingتعيين إلى true، ثم يرفع مشغّل الربط Validation.Error الحدث المرفق على العنصر.

لاحظ أيضاً أن نقل قيمة صحيحة في أي اتجاه (الهدف إلى المصدر أو المصدر إلى الهدف) يمسح Validation.Errorsالخاصية المرفقة.

إذا كان التوثيق أما ExceptionValidationRuleالمقترنة بها، أو كان ValidatesOnExceptionsخاصية هو تعيين إلى trueواستثناء هو طرح عند تعيين مشغل توثيق المصدر، يقوم مشغل ربط معرفة ما إذا كان هناك هو UpdateSourceExceptionFilter. يكون لك خيار استخدام UpdateSourceExceptionFilter رد الاتصال لتوفير معالج مخصص لمعالجة الاستثناءات. إذا كان UpdateSourceExceptionFilter لم يتم تحديده على Binding ، ينشئ مشغّل الربط ValidationError بالاستثناء وإضافته إلى Validation.Errors مجموعة العنصر المنضم.

آلية تصحيح الأخطاء

يمكنك تعيين الخاصية المرفقة PresentationTraceSources.TraceLevel على كائن ذات الصلة بالربط لتلقي معلومات حول حالة ربط معينة.

راجع أيضًا:

المهام

كيفية القيام بما يلي: الربط بنتائج استعلام LINQ

كيفية القيام بما يلي: الربط إلى مصدر بيانات ADO

المرجع

DataErrorValidationRule

المبادئ

الجديد في الإصدار 4 من WPF

أمثلية الأداء: ربط البيانات.

موارد أخرى

العرض التوضيحي لربط البيانات

المواضيع الإجرائية لربط البيانات