التنبيهات التالية ظهرت :
Warning [2] count(): Parameter must be an array or an object that implements Countable - Line: 864 - File: showthread.php PHP 7.4.33 (Linux)
File Line Function
/showthread.php 864 errorHandler->error



تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
WPF الأساسيات : ربط البيانات DataBinding في WPF
#1
توضح هذه المقالة خطوة بخطوة كيف يمكنك ربط مصادر البيانات Data Sources مع أدوات تحكم WPF Controls - WPF وصفيًا من خلال لغة XAML., أو يدويًا (إجرائيًا) من خلال الكود, هذه المقالة تركّز بشكل أكبر على إيضاح مبادئ ربط البيانات في WPF بشكل عام. ولا تُناقش كيفية استخدام مصادر البيانات بشكل خاص, محتويات المقالة كالتالي:
  • مقدمّة
  • نظام التبعيّة Dependency System في WPF, ومفاهيم ربط البيانات الأساسية
  • ربط البيانات من خلال XAML
  • ربط البيانات إجرائيًا
  • أوضاع الربط والتحديث Data Binding/Updating Modes
  • خيارات الربط Data Binding Options
[SIZE="3"]مقدمة[/SIZE]

ربط البيانات Data Binding هو آلية تسمح بتكوين ارتباط بين مصادر البيانات مع واجهة الاستخدام المرئية Graphical User Interface, مصادر البيانات قد تختلف حسب طبيعة التطبيق, عادةً مصادر البيانات تقيم في إحدى طبقات التطبيق والتي تسمّى Business Logic Layer, هذا الارتباط يُمكن أن يكون أُحادي الاتجاه أو ثنائي الاتجاه, في الوضع الأول يمكن فقط لأحد الطرفين (مصدر البيانات أو عنصر تحكم واجهة الاستخدام) التأثير على الطرف الآخر, وفي الوضع الثاني يكون التأثير بينهما متبادلاُ.

في WPF عادةً ما يُشير المُصطلح Data Source إلى كائن في بيئة الدوت نت( .NET object ) هذا الكائن قد يكون مجموعة Collection مثل Lists أو Arrays , ملف XML, أو كائن خدمة ويب Web service object, أو كائن يشير إلى جدول في قاعدة بيانات Data table, أو كائن POCO بسيط ((Plain Old CLR Object, أو حتى عنصر تحكّم من عناصر WPF مثل Button .

[SIZE="3"]نظام التبعيّة Dependency System في WPF, ومفاهيم ربط البيانات الأساسية[/SIZE]

أضاف WPF نوعًا جديدًا من الخصائص, وهي خصائص التبعيّة Dependency Properties, والتي تم إدخالها لتبسيط المهام التي من أجلها تم تصميم WPF, مثل تنسيق المظهر Styling, ربط البيانات التلقائي Automatic Data Binding, التحريك Animation, والمزيد, قد تبدو هذه الإضافة غامضةُ بعض الشيء بالنسبة لك, لأنها ستُعقّد نوعًا ما الانطباع الذي أخذته عن كائنات Microsoft.NET الكلاسيكيّة: مجرّد حقول Fields, وإجرءات Methods وخصائص Properties بسيطة, لكن بمُجرّد أن تفهم المشاكل التي يحُلها نظام التبعيّة , ستُرحب كثيرًا بهذه الإضافة.

خصائص التبعيًة Dependency Properties تعتمد في الحصول على القيم الخاصة بها على مًوفّر القيمة Value Provider, وقد تعتمد على أكثر من مُوفّر واحد, وقد يكون هذا المُوفّر إما تحريكًا Animation يقوم تلقائيًا بتغيير قيمة تلك الخاصيّة, أو عنصر أبوي Parent Element ينشر قيم خصائصه نحو العناصر الأبناء Child Elements, وهكذا. من أهم ميزات خصائص التبعيّة هو اعتمادها على النظام المبني على التنبيه عند حدوث تغيّر في القيم التي تحملها Change Notifications.

الدافع وراء هذه الإضافة هو تمكين الميزات الغنيّة التي يُقدّمها WPF مباشرةً من خلال لغة تمييز التطبيقات القابلة للامتداد XAML, وما يجعل WPF يعتمد بشكل كبير على استخدام لغة التمييز هذه هو مبالغة نظام WPF في استخدام الخصائص, على سبيل المثال, عنصر التحكّم Button يحتوي على 111 خاصيّة (منها 98 موروثة من النوع Control وفئاته القاعدية), يُمكن تعيين قيم الخصائص لعناصر WPF بسهولة من خلال XAML (بطريقة مباشرة أو باستخدام أدوات التصميم مثل مُصمّم WPF المُضمن مع Visual Studio) , ولكن من دون اللجوء لكتابة بعض الكود الإضافي لن يكون من المُمكن الحصول على النتيجة المُنتظرة فقط بمجرد إسناد بعض القيم من خلال XAML, فلا تتوّقع أنك ستحصل على ميزات خصائص التبعيّة مثل الربط التلقائي باستخدام الخصائص العادية CLR Properties فقط.

كيفية تعريف خصائص التبعيّة

في الواقع كمطوّر WPF لست مُجبرًا على الإلمام بجميع التفاصيل الدقيقة لكيفية تعريف وكتابة خصائص التبعيّة, إلا إذا كنت تخطّط لكتابة أدوات تحكّم خاصة بك Custom Controls, وبشكل عام فإنك تحتاج فقط لفهم كيفية عملها, ومع مرور الوقت ستتمنّى لو كانت جميع الخصائص هي خصائص تبعيّة!

لغات عائلة Microsoft.NET في الواقع لا تتفهّم خصائص التبعيّة, لهذا فإن واجهة برمجة WPF - WPF APIs هي المسؤولة عن إدارة تلك الخصائص, ولهذا السبب عمليًا ستحتاج لاستخدام بعض الفئات الأساسيّة Base Classes الموجودة في WPF APIs من أجل كتابة خصائص التبعيّة, المثال التالي هو أبسط شكل لما يُمكن أن تكون عليه خاصية التبعيّة, وهو عبارة عن تعريف للخاصية Content الموجودة في عنصر التحكّم Button والعناصر الأخرى الموروثة من النوع ContentControl.
PHP كود :
public class ContentControl ControlIAddChild
    
{
        public static 
readonly DependencyProperty ContentProperty =
                    
DependencyProperty.Register("Content"typeof(object),
                    
typeof(ContentControl), new FrameworkPropertyMetadata(null,
                    new 
PropertyChangedCallback(ContentControl.OnContentChanged)));
        public 
object Content
        
{
            
get
            
{
                return 
base.GetValue(ContentProperty);
            }
            
set
            
{
                
base.SetValue(ContentPropertyvalue);
            }
        }
        private static 
void OnContentChanged(DependencyObject dDependencyPropertyChangedEventArgs e)
        {
        ...
        }
     ...
    } 
PHP كود :
Public Class ContentControl
    Inherits Control
    
Implements IAddChild
    
Public Shared ReadOnly ContentProperty As DependencyProperty DependencyProperty.Register("Content"GetType(Object), GetType(ContentControl), New FrameworkPropertyMetadata(Nothing, New PropertyChangedCallback(ContentControl.OnContentChanged)))
    Public 
Property Content() As Object
        Get
            
Return MyBase.GetValue(ContentProperty)
        
End Get
        Set
            MyBase
.SetValue(ContentPropertyvalue)
        
End Set
    End Property
    
Private Shared Sub OnContentChanged(As DependencyObjectAs DependencyPropertyChangedEventArgs)

    
End Sub
     
...
End Class 


الحقل المُشترك ContentProperty هو الذي يُمثّل خاصية التبعيّة, وهو من النوع System.Windows.DependencyProperty, وبالإجماع, جميع الحقول التي تُمثّل خصائص التبعيّة, تكون عامة public, ومُشتركة static, تنتهي تسميتها بالكلمة Property, منصّة WPF الأساسيّة تتطلب اتباع هذا الأسلوب في التعريف للعديد من الأغراض مثل أدوات الترجمة Localization, وأثناء القيام بتحميل ومُعالجة XAM, فإن WPF يخضع في معالجته لهذا الأسلوب.

وفي العادة يتم إنشاء خصائص التبعيّة باستدعاء الإجراء DependencyProperty.Register والذي يتطلب المُدخلات التالية: اسم الخاصًية متبوعًا بالكلمة Propertyكما في المثال السابق(ContentProperty), نوع الخاصيّة (object), ونوع الفئة الحاوية على الخاصيًة (ContentControl), يُمكن اختياريًا باستخدام أحد ال Overloads للإجراء Register السابق تحديد كيفية مُعالجة WPF لتلك الخاصيّة, وكذلك الإجراءات CallBacks التي سيتم استدعاءؤُها عند تغيّر قيمة الخاصيّة, وكذا بعض المعلومات الأخرى. في التعريف السابق تم استدعاء الإجراء Register لإسناد القيمة null للخاصية Content, وتمرير مُفوّض Delegate يشير إلى الإجراء OnContentChanged من أجل التنبيه عند تغيّر قيمة الخاصية Content.

ثم بعد ذلك تأتي الخاصيّة Content والتي يتم من خلال إجرائيها get و set استدعاء الإجرائين GetValue و SetValue على التوالي, والموروثة من النوع System.Windows.DependencyObject, الفئة المنخفضة المستوى, والتي ترث منها جميع الفئات التي تحتوي على خصائص التبعيّة, الإجراء GetValue يقوم باسترداد القيمة التي تمّ تخزينها باستخدام الإجراء SetValue, وفي حال لم يتم استدعاء هذا الإجراء (SetValue) مُسبقًا, سيتم استرداد القيمة الافتراضية والتي تمّ تمريرها للإجراء DependencyProperty.Register. وفي الواقع لست بحاجة لتعريف الخاصية Content, لأنه من المُمكن استدعاء الإجرائين GetValue و SetValue فهما إجراءان عامّان, ولكن استخدام الخصائص يجعل استهلاك خصائص التبعيّة مألوفًا لدى مستخدم هذه الخصائص, ومن جهة أخرى فهي تُمكّن من إسناد الفيم لها من خلال XAML. وقد تستغرب لما لا يستخدم الإجراءان Get/SetValue ال Generics, والسبب مبدئيًا هو ظهور مفاهيم خصائص التبعيّة قبل ظهور Generics.

من جهة أخرى قد تستغرب لما يتم تعريف حقول خصائص التبعيّة على أنها مشتركة static, وحتى تفهم ذلك تخيّل العكس, ماذا لو تم تعريفها على أنها Instance Fields عندها ستحتاج من أجل كل عنصر أو مثيل Instance من Button حوالي 111 حقلاً أي 111 قيمة, ومن كل مثيل من Label حوالي 104 حقلاً أي 104 قيمة, وهكذا... عندها سيزيد استهلاك الذاكرة بشكل مريع! لكن خصائص التبعيّة جاءت لتحل هذه المشكلة, حيث أن الإجرائين Get/SetValue يستخدمان أسلوب فعّال واقتصادي لمنع هذا الاستهلاك الفضيع للذاكرة, حيث هناك من 89 خاصية تبعيّة من بين 111 خاصيّة للنوع Button, و 82 من بين 104 للنوع Label وهذا سيُحسّن بشكل كبير كميّة استهلاك الذاكرة, لا تسن أن الحقول المشتركة Static Fields يتم حفظ قيمها على مستوى النوع وليس على مستوى مثيل ذلك النوع Per-type values .

فوائد خصائص التبعيّة تتجاوز تحسين استهلاك موارد النظام من الذاكرة, وتتعدّى ذلك إلى عزل المطوّر عن الكثير من الأعمال الشاقّة مثل التحقّق من وصول المسارات Threads Access, أو مطالبة العنصر الأبوي Parent Element الذي يحتوي على عنصر تحكّم ما بإعادة رسم نفسه, على سبيل المثال, تغيير قيمة الخاصيًة Background للعنصر Button, يحتاج لمطالبة هذا الأخير بإعادة رسم نفسه, وهذا مًمكن من خلال تمرير القيمة FrameworkPropertyMetaDataOptions.AffectRender للإجراء DependencyProperty.Register, بالإضافة إلى كل ذلك, هناك الفوائد الثلاثة الأخرى التي سيرد ذكرها فيما يلي.

1 - التنبيه بالتغيّرات Change Notification

عندما يحدث تغيّر في قيمة خاصية التبعيّة, يقوم WPF بتشغيل مجموعة من الإجراءات, بناءًا على كيفية تعريف تلك الخاصية, قد يكون هذا الإجراء إعادة رسم عنصر معيّن في واجهة الاستخدام, أو إحداث تغيّر في تصميم واجهة الاستخدام, تحديث ربط البيانات, والمزيد. وإن من أهم ما يُميّز نظام التنبيه بالتغيّرات هذا هو مُشغّلات الخصائص Property Triggers, والتي تسمح لك بتشغيل إجرائك الخاص عند حدوث التغيّر دون الحاجة لكتابة كود إجرائي, على سبيل المثال, قد تريد تغيير لون خلفية عنصر تحكّم Button عند مرور مؤشر الماوس فوقه, واسترداد القيمة السابقة عند مغادرة المؤشر, مبدئيًا ستحتاج للقيام بذلك إلى إرفاق إجرائين للحدثين MouseEnter و MouseLeave,
PHP كود :
<Button MouseEnter="Button_MouseEnter" MouseLeave="Button_MouseLeave" /> 
أما باستخدام مُشغّلات الخصائص, فيُمكنك الحصول على نفس النتيجة دون الاستعانة بالكود الإجرائي, بل يُمكنك الاكتفاء فقط باستخدام XAML, كما يُوضّح المثال التالي:
PHP كود :
<Button>
            <
Button.Style>
                <
Style TargetType="Button">
                    <
Style.Triggers>
                        <
Trigger Property="IsMouseOver" Value="true">
                            <
Setter Property="Background" Value="Blue"/>
                        </
Trigger>
                    </
Style.Triggers>
                </
Style>
            </
Button.Style>
        </
Button
هذا المُشغّل يمكنه العمل بحسب قيمة الخاصية IsMouseOver التي تُصبح True في نفس الوقت الذي يتم فيه إطلاق الحدث MouseEnter, وتُصبح False في نفس الوقت الذي يتم فيه إطلاق الحدث MouseLeave, لاحظ أنك لست مُطالبًا بإعادة القيمة Background إلى قيمتها الابتدائيّة, سيقوم WPF بذلك تلقائيًا من أجلك!
,كما لاحظت فإنه ليس بوُسعك إسناد مُشغّل بشكل مُباشر إلى عناصر WPF, بل ستحتاج لتعريف مظهر Style جديد وتعريف هذا المُشغّل بداخله ومن ثم تعيين هذا المظهر إلى العنصر الهدف كما في المثال السابق.

2 - وراثة الخصائص Property Inheritance

وراثة الخصائص أو "وراثة قيم الخصائص" غير مُرتبطة مطلقًا بمفاهيم الوراثة في البرمجة المُوجهّة بالكائنات OOP, بل تعني انتقال قيمة خاصيّة معينّة من عنصر إلى آخر في شجرة العناصر Elements Tree, على سبيل المثال عندما تقوم بتحديد قيمة خاصيّة التبعيّة FontSize للإطار Window فإن هذه القيمة يتم توريثها لجميع العناصر الموجودة ضمن هذا الإطار مثل عناصر تحكّم Button, Label, إلى غير ذلك, جرّب لمثال التالي:
PHP كود :
<Window x:Class="WPFDependencyOverview.MainWindow"
        
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        
Title="MainWindow"
        
Height="350"
        
Width="525"
        
FontSize="18"
        
SizeToContent="WidthAndHeight"
        
Background="SkyBlue">
    <
StackPanel>
        <
TextBlock FontSize="36"
                   
Text="Property Value Inheritance"
                   
HorizontalAlignment="Center" />
        <
TextBox HorizontalAlignment="Center"
                 
Width="200"
                 
Text="Test"
                 
TextAlignment="Center" />
        <
Button Content="Click me!"
                
HorizontalAlignment="Center" />
    </
StackPanel>
</
Window


لكن هذه ليست قاعدة في كل الحالات, فهناك بعض الحالات التي لا يمكن فيها لعنصر أبوي أن يُورّث قيم أحد خصائصه لأحد عناصره الأبناء, في هذه الحالة إما أن العنصر الإبن يأخذ قيمته من مُوفّر القيمة ذي الأولوية الأكبر من العنصر الأبوي, كما في المثال السابق حيث أن عنصر TextBlock لم يتأثر بحجم الخط الذي تمّ تعيينه للإطار لأنه قد تم تعيين قيمته المحليّة Local Value إلى 36 بكسل والتي لها أولوية أعلى من العنصر الأبوي (Window), بينما تأثر كلّ من Button و TextBox بالقيمة الأبوية 18 بكسل, وإما أن الخاصيّة نفسها لم يتم تكوينها بالشكل الذي يجعلها قادرةُ على توريث قيمتها. في العادة يُمكن الحصول على هذا السلوك (توريث القيمة) من خلال تمرير القيمة FrameworkPropertyMetaDataOptions.Inherits إلى الإجراء DependencyProperty.Register .

3 - إمكانيّة تعدّد مُوفّري القيمة Multiple Value Providers Support

تمّ تسمية خصائص التبعيّة Dependency Properties بهذا الإسم لانها تعتمد في الحصول على قيمهتا على مجموعة من موفّري القيمة Value Providers يعتمد WPF على آلية مُعقّدة بعض الشيء , وتتمّ هذه الآلية وفق ترتيب معيّن وفي مراحل. يمُّر WPF حاليًا على 5 مراحل من أجل تحديد تلك القيمة النهائيّة التي ستحملها الخاصيّة, يُمكن تلخيص تلك المراحل فيما يلي:

المرحلة الأولى: تحديد القيمة الابتدائية Base Value:
يشترك أغلب مُوفّري القيمة في عملية احتساب القيمة الابتدائية لخاصيّة مُحدّدة وفق ترتيب مُعيّن يخضع فيه هذا الترتيب لمبدأ الأسبقية (ما يُسمّى بـ Property Precedence), حيث أن مُوفّر القيمة ذي أعلى أسبقية هو الأحق بأن يُعطي قيمته لتلك للخاصية, يُمكن اختصار هذا الترتيب في القائمة التالية للقيم الناتجة من المُوفّر ذو الأسبقية العُليا إلى المُوفّر ذي الأسبقية السُفلى.
  • القيمة المحليّة Local Value لخاصيًة العنصر نفسه.
  • القيمة التي تمّ تحديدها في مُشفّل خاصيًة في Template العنصر الأبوي (Parent Tempate Trigger).
  • القيمة التي تمّ تحديدها في Template العنصر الأبوي (Parent Template).
  • القيمة التي تمّ تحديدها في مُشغل خاصية في Style العنصر نفسه (Style Trigger), كما يظهر ذلك في المثال الثاني في هذا المقال والخاص بخلفية Button .
  • القيمة التي تمّ تحديدها في مُشغّل خاصيّة في Template العنصر نفسه (Template Trigger).
  • القيمة التي تمّ تحديدها في Style العنصر نفسه بواسطة Style Setter.
  • القيمة التي تمّ تحديدها في مُشغّل خاصيّة في الـ Theme الحالي (Theme Style Trigger)
  • القيمة التي تمّ تحديدها في Style خاص بالـ Theme الحالي بواسطة Style Setter أي (Theme Style Setter)
  • القيمة التي تمّت وراثتها بواسطة ميزة Property Value Inheritance كما ورد في الفقرة السابقة "وراثة الخصائص".
  • القيمة الافتراضية Default Value لخاصيًة العنصر نفسه (التي تم استخدامها عند تعريف خاصيّة التبعيّة من خلال الإجراء DependencyProperty.Register).
- بالنسبة لـ Triggers و Templates و Themes سيتم الحديث عنها لاحقًا بالتفصيل في موضوع مستقل.

إذا لم يكن بوسعك معرفة مُوفّر القيمة الحالي لخاصيًة مُحدّدة, يمكنك استخدام الإجراء المُشترك DependencyPropertyHelper.GetValueSource, كوسيلة مُساعدة لذلك, هذا الإجراء يُعيد بعض البيانت المفيدة, من بينها قيمة من النوع BaseValueSource Enum والتي تُحدد مصدر القيمة الفعلي, يُمكنك مراجعة MSDN Library لمعرفة المزيد حول هذا الإجراء.

المرحلة الثانية: اختبار القيمة Value Evaluating
إذا كانت القيمة العائدة من المرحلة السابقة هي عبارة عن تعبير Expression (كائن مُشتق من النوع System.Windows.Expression) , سيقوم WPF باختبار ذلك التعبير للحصول على قيمة حقيقية, ال Expressions تستخدم في الغالب من أجل ربط البيانات Data Binding وهو ما سنتحدّث عنه في تكملة هذا المقال.

المرحلة الثالثة: تطبيق التحريكات Apply Animations
إذا كان هناك تحريك Animation يتم تطبيقه حاليًا على العنصر, فإن لهذا التحريك القدرة على تغيير قيمة الخاصيّة لهذا العنصر, لهذا من المُمكن للتحريك أن يُلغي مفعول كافة مُوفرّي القيمة السابقين في الخطوة الأولى ويُلغي كذلك القيمة الناتجة عن الخطوة الثانية.

المرحلة الرابعة: تطبيق القيمة الاضطراريّة Apply Corece Value
بعد الحصول على آخر قيمة "من المرحلة السابقة", يقوم WPF بتمرير تلك القيمة إلى المُفوّض CoerceValueCallback (إن تمّ تسجيله عند تعريف خاصيّة التبعيّة من خلال الإجراء DependencyPropery.Register), هذا المُفوّض مسؤول عن إرجاع قيمة جديدة قد تكون مُغايرة كليًا للقيمة الأخيرة بناءًا على منطق Logic مُحدّد, على سبيل المثال أداة ProgressBar تستخدم هذا المُفوّض لتقييد قيمة التقدّم Progress Value إلى أدنى قيمة لها Minimum إذا كانت الفيمة الأخيرة أقل من Minimum, أو إلى أعلى قيمة Maximum إذا كانت القيمة الأخيرة أكبر من Maximum (يُمكن تشبيه هذه الخطوة بـ Validation).

المرحلة الخامسة: التحقّق من صلاحية القيمة Validation
يقوم WPF بتمرير آخر قيمة تمّ تحصيلها من المرحلة السابقة إلى المُفوّض ValueValidateCallback (إن تمّ تسجيله عند تعريف خاصيّة التبعيّة من خلال الإجراء DependencyPropery.Register), هذا المُفوّض يجب أن يُعيد true إن كانت القيمة صالحة, أو يُعيد false إن لم تكن كذلك, الأمر الذي سيُسبّب إطلاق استثناء Exception.

تعابير الربط Binding Expressions

يستخدم WPF لتحقيق ربط البيانات الفئة System.Windows.Data.Binding والتي تعمل على وصل خاصيّتين مع بعضهما البعض ويبقي هذا الاتصال مغتوحًا بينهما, يُمكنك إنشاء هذا الاتصال مرّة واحدة وسيتولّى WPF إبقاهء على مدار عمر التطبيق, ويحتاج WPF لإنشاء الربط إلى أربع مُكونات أساسية:
  • الكائن الهدف Target Object: الكائن الذي يتمّ ربط مصدر البيانات به وإسناد القيمة المطلوبة إلى أحد خصائصه (عادة مايكون هذا الكائن هو أحد عناصر واجهة الاستخدام (DataGrid- ListBox ...)
  • الخاصيّة الهدف Target Property: الحاصيّة الموجودة في الكائن الهدف والتي ستحمل القيمة المطلوبة من خلال هذا الربط.
  • الكائن المَصدر Data Source: الكائن الذي يمتلك القيمة التي سيُقدّمها للكائن الهدف.
  • المسار Path: الذي يُحدّد موضع القيمة في الكائن المَصدر (قد يكون هذا المسار اسم خاصية Property Name, أو مُفهرِس Indexer).
ملاحظة: يجب أن تكون الخاصيّة الهدف عبارة عن Dependency Property, ولحسن الحظ فإن معظم الخصائص في عناصر WPF هي كذلك.

لنفترض على سبيل المثال أنك تريد ربط الخاصية Content لعنصر Label ليقوم بعرض النص الذي يتم إدخاله داخل عنصر TextBox, ولنفترض أن اسم عنصر Label هو lblResult, وأن اسم عنصر TextBox هو txtBox, وعليه ستكون مُكونات الربط الأساسيّة وفق ما سبق كما يلي:
  • الكائن (العنصر) الهدف: هو lblResult, وهو الكائن الذي تريد ربط مصدر البيانات به وعرض القيمة المطلوبة فيه.
  • الخاصيّة الهدف: هي الخاصيًة Content للكائن lblResult, لأنك تريد عرض القيمة المطلوبة من خلال الخاصيّة Content.
  • الكائن المَصدر: وهو txtBox (الكائن الذي يُوفّر القيمة).
  • المسار: وهو اسم الخاصيًة Text في الكائن المَصدر txtBox, لأنك تريد عرض القيمة التي تحملها الخاصيًة Text.

يُتبع ...
الرد }}}
تم الشكر بواسطة: الشموخ , T.ALKATHIRI , T.ALKATHIRI


الردود في هذا الموضوع
WPF الأساسيات : ربط البيانات DataBinding في WPF - بواسطة Islam Ibrahim - 17-09-12, 12:44 PM


التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم