يمكن أن تضمن القيمة الافتراضية للسمة صلاحية السمة.
يمكن استخدام صلاحية التحقق من السمة للتحقق من سمات الإدخال وعمليات الاسترجاعات الإلزامية للسمات، أي أنه يجب إرسال الإشعارات بغض النظر عما إذا كانت السمات قد تغيرت أم لا.
إشعار تغيير السمة، عندما تتغير إحدى السمات، يمكن إخطار البرنامج بتنفيذ سلسلة من العمليات.
لا يوجد شيء خاطئ في WPF هنا، دعونا نرى كيف تحل خصائص التبعية المشاكل المذكورة أعلاه.
يحدد ملخص المحتوى أول وأبسط قيمة سمة التبعية لقيمة سمة التبعية الأساسية للبيانات الوصفية لسمة مجمّع السمة (PropertyMetadata)
السلوك الأساسي للبيانات التعريفية
على الرغم من أن الكلمات الأصلية لـ MSDN صريحة، إلا أنه ليس هناك شك في دقتها بمجرد فهمها، سيكون لديك تجربة مختلفة عندما تنظر إليها.
1. حدد سمة التبعية الأولى والأبسط
كلمات MSDN الأصلية: توفر Windows Presentation Foundation (WPF) مجموعة من الخدمات التي يمكن استخدامها لتوسيع وظائف خصائص وقت تشغيل اللغة العامة (CLR). غالبًا ما يُشار إلى هذه الخدمات بشكل جماعي باسم نظام الملكية WPF. تسمى الخصائص التي يدعمها نظام خاصية WPF خصائص التبعية.
دعونا نحدد سمة تبعية العمر، كما يلي:
الطبقة العامة DPCustomPeople
{
DependencyProperty العامة الثابتة للقراءة فقط AgeProperty =
DependencyProperty.Register("Age", typeof(int), typeof(DPCustomPeople));
الفراغ العام DisplayAgeProperty ()
{
Console.WriteLine("DPName:" + DPCustomPeople.AgeProperty.Name);
Console.WriteLine("DPPropertyType:" + DPCustomPeople.AgeProperty.PropertyType);
Console.WriteLine("DPOWnerType:" + DPCustomPeople.AgeProperty.OwnerType);
}
}
ثم اتصل بنتيجة الإخراج
برنامج الصف
{
الفراغ الثابت الرئيسي (سلسلة [] الحجج)
{
DPCustomPeople people = new DPCustomPeople();
People.DisplayAgeProperty();
}
}
قد لا تكون على دراية بفئة DependencyProperty. توفر فئة DependencyProperty بعض الخصائص الأساسية لخصائص التبعية.
طريقة تسجيل خاصية التبعية هي استدعاء طريقة التسجيل الثابتة لـ DependencyProperty، والتي توفر طرقًا متعددة مثقلة، ولكن الخطوات الثلاث التالية ضرورية بمجرد اكتمال التسجيل، فهي خاصية ثابتة
تقديم الاسم المسجل (الاسم) "العمر"
تسجيل نوع الخاصية (PropertyType) typeof (int)
تسجيل نوع المالك لنوع سمة التبعية (OwnerType) (DPCustomPeople)
ملاحظة: لا يمكن تغيير اسم السمة ونوع السمة ونوع مالك السمة بمجرد التسجيل.
وفيما يلي نتيجة الإخراج
2. العمليات الأساسية لقيم السمات التابعة (اكتساب القيمة وتعيينها)
بعد تحديد خاصية تبعية العمر، يجب أن نكون قادرين على تنفيذ عمليات اكتساب القيمة وتعيينها على الخاصية. لا توفر DependencyProperty نفسها هذه العمليات، ولكن يتم التعامل معها بواسطة DependencyObject.
يمثل DependencyObject كائنًا يشارك في نظام خاصية التبعية.
لذلك، من الضروري أن ترث الفئة المحددة من DependencyObject، ثم إعادة كتابة DPCustomPeople
الفئة العامة DPCustomPeople:System.Windows.DependencyObject
{
}
عمليات تعيين القيمة الأساسية وطرق GetValue وSetValue
الفراغ العام DPPropertyBasicOperator ()
{
Console.WriteLine("Age:" + this.GetValue(DPCustomPeople.AgeProperty));
this.SetValue(DPCustomPeople.AgeProperty, 24);
Console.WriteLine("ChangedAge:" + this.GetValue(DPCustomPeople.AgeProperty));
}
نتائج الإخراج
3. يستخدم مجمّع السمة طريقتي GetValue وSetValue للعمل على القيم، حتى نتمكن من تغليفها وتحديد سمة العمر.
العمر العام
{
الحصول على { return (int)GetValue(AgeProperty });
set { SetValue(AgeProperty, value });
}
ملاحظة: اصطلاح التسمية لتعبئة الخاصية التابعة هو إزالة الخاصية التالية
الفراغ العام DPPropertyBasicOperatorUsingProperty ()
{
Console.WriteLine("العمر:" + this.Age);
this.Age=24;
Console.WriteLine("ChangedAge:" + this.Age);
}
هل يبدو الكود أعلاه أكثر إيجازًا؟
4. البيانات الوصفية للملكية (PropertyMetadata)
MSDN الأصلي: يتضمن نظام خاصية Windows Presentation Foundation (WPF) نظامًا لإعداد تقارير بيانات التعريف لا يقتصر على ما يمكن الإبلاغ عنه حول خاصية من خلال الانعكاس أو ميزات وقت تشغيل اللغة العامة العادية (CLR).
عند الحديث عن البيانات الوصفية للسمات، أول ما يتبادر إلى الذهن هو سمة .net
شخص من الطبقة العامة
{
[DefaultValue(200),Category("Layout")]
العرض العام {احصل عليه}
}
تحتاج السمة إلى استخدام قوة Visual Studio لتقديم الدعم السهل لـ IDE للسمة، أو الاعتماد على الانعكاس لتعيين القيم.
ولكن بدون هذه التقنيات، يقوم الجديد بإنشاء مثيل جديد من خلال القنوات العادية، ولن يكون لإضافة السمات أي تأثير. لا يمكننا الاعتماد على هذه السمات لضمان بعض الخصائص الأساسية للسمات (مثل القيم الافتراضية). السمات تختلف عن البيانات الوصفية الموضحة أعلاه.
بيانات التعريف لخصائص التبعية
يمكن تحديدها بشكل فريد من خلال الفئة التي تم تعريف خاصية التبعية فيها يمكن تغييرها عند إضافة خاصية التبعية إلى فئة أخرى يمكن تجاوزها بشكل صريح من قبل جميع الفئات المشتقة التي ترث خاصية التبعية من الفئة الأساسية المحددة اللغة المذكورة أعلاه صريحة، لكنه يوضح القصد ولكن لا يمكننا دائمًا فهم أفكار المصمم في المرة الأولى.
5. السلوك الأساسي لبيانات تعريف السمة يوفر السلوك الأساسي لبيانات تعريف السمة ثلاث وظائف للسمات التابعة. وهذه أيضًا هي المشكلة التي تم طرحها للتو في هذه المقالة.
رد الاتصال الإلزامي لخاصية إشعار الخاصية الافتراضية دعنا نلقي نظرة أولاً على مُنشئ PropertyMetadata الكامل إذا لم يتم تعيين PropertyMetadata الافتراضي للخاصية التابعة، فسيتم إنشاء كائن PropertyMetadata تلقائيًا داخليًا للخاصية التابعة.
خصائص البيانات العامة (object defaultValue، PropertyChangedCallback propertyChangedCallback، CoerceValueCallback coerceValueCallback)
تستعير السمات التابعة مفهوم بيانات تعريف السمة لإكمال القيم الافتراضية للسمة وإشعارات السمات وعمليات الاسترجاعات القسرية والسلوكيات الأخرى
1.القيمة الافتراضية للسمة
DependencyProperty NameProperty العامة الثابتة للقراءة فقط =
DependencyProperty.Register("Name"، typeof(string)، typeof(DPCustomPeople)،
new PropertyMetadata(string.Empty));
سيكون لدى معظم الأشخاص سؤال عندما يرون ذلك، لماذا تستخدم PropertyMetadata لتعيين قيمة افتراضية؟ لماذا لا تسجلها مباشرة في طريقة التسجيل؟
DependencyProperty NameProperty العامة الثابتة للقراءة فقط =
DependencyProperty.Register("Name"، typeof(string)، typeof(DPCustomPeople)،
string.Empty);
بالطبع هذا السؤال يرافقني منذ فترة طويلة، وليس هناك ما يمكنني فعله إذا لم أتمكن من حله، لذا سأتركه الآن.
ملاحظة: عند تعيين قيمة افتراضية لخاصية في PropertyMetadata، لا يمكن اكتشاف صحة النوع.
مثل هذا التعريف، نظرًا لأن القيمة الافتراضية لمقطع كود dp في vs هي 0، فهذا شيء جدير بالملاحظة
DependencyProperty NameProperty العامة الثابتة للقراءة فقط =
DependencyProperty.Register("Name"، typeof(string)، typeof(DPCustomPeople)،
new UIPropertyMetadata(0));
2. عملية استعادة القيمة الافتراضية للسمة
بعد تعيين قيمة للخاصية، يمكنك استعادة القيمة الافتراضية من خلال طريقة ClearValue الخاصة بـ DependencyObject، كما هو موضح في الكود التالي
اسم السلسلة العامة
{
الحصول على { return (string)GetValue(NameProperty });
set { SetValue(NameProperty, value });
}
DependencyProperty NameProperty العامة الثابتة للقراءة فقط =
DependencyProperty.Register("Name"، typeof(string)، typeof(DPCustomPeople)،
new UIPropertyMetadata(string.Empty));
الفراغ العام DPPropertyClearOperator ()
{
Console.WriteLine("الاسم:" + this.Name);
this.Name="تيري";
Console.WriteLine("ChangedName:" + this.Name);
this.ClearValue(NameProperty);
Console.WriteLine("الاسم:" + this.Name);
}
نتائج الإخراج
ملاحظة: ميز بين التعيين الافتراضي والقيمة الافتراضية
عادةً ما يتم التعيين الافتراضي في المُنشئ، ولكن هذه ليست القيمة الافتراضية (كان هذا صحيحًا قبل ظهور خصائص التبعية)، خاصة عندما تتجاوز الفئات المشتقة الخصائص.
طالب الطبقة العامة: DPCustomPeople
{
طالب عام ()
{
this.Name = "Sky";
}
الفراغ العام TestSubDefaultDpValue()
{
Console.WriteLine("مسح قبل:"+this.Name);
this.ClearValue(Student.NameProperty);
Console.WriteLine("مسح بعد:" + this.Name);
}
}
نتائج الإخراج
3. الإخطار بتغييرات الملكية
هذه الوظيفة هي الأكثر استخدامًا عندما تتغير قيمة الخاصية، يتم تشغيل رد الاتصال PropertyChangedCallback.
المجمع العام IsBoy
{
الحصول على { return (bool)GetValue(IsBoyProperty });
set { SetValue(IsBoyProperty, value });
}
DependencyProperty العامة الثابتة للقراءة فقط IsBoyProperty =
DependencyProperty.Register("IsBoy", typeof(bool), typeof(Student),
new UIPropertyMetadata(false,new PropertyChangedCallback(IsBoyPropertyChangedCallback)));
الفراغ العام الثابت IsBoyPropertyChangedCallback (DependencyObject d، DependencyPropertyChangedEventArgs e)
{
الطالب ش = د كطالب؛
إذا (st.IsBoy)
{
Console.WriteLine("مرحبا يا فتى");
}
آخر
{
Console.WriteLine("مرحبا يا فتاة");
}
}
الفراغ العام TestPropertyChangedCallback()
{
this.IsBoy = false;
this.IsBoy = true; this.IsBoy = true;
}
يمكنك عرض القيمة القديمة ونتائج إخراج القيمة الجديدة من خلال DependencyPropertyChangedEventArgs
ملحوظة:
(1) من خلال نتائج المخرجات المذكورة أعلاه، هل رأيت أن القيمة الافتراضية للخصائص التابعة لن تؤدي إلى تشغيل إشعارات تغيير الخاصية؟
(2) قم بتشغيل إشعارات تغيير السمات يدويًا
إذا كنت تريد أن تؤدي القيمة الافتراضية إلى تغيير الخاصية (في الواقع، يكون ذلك ضروريًا في بعض الأحيان)، فلا يتعين عليك الانتظار وتشغيلها يدويًا.
الفراغ الخاص RaiseIsBoyPropertyChangedCallback()
{
IsBoyPropertyChangedCallback(this،DependencyPropertyChangedEventArgs الجديدة
(Student.IsBoyProperty، Student.IsBoyProperty.DefaultMetadata.DefaultValue، null));
}
(3). عندما يكون هناك إشعار بتغيير السمة، تأكد من صحة نوع القيمة الافتراضية للسمة.
نحن نعلم أن أنواع القيم لها قيم افتراضية، ولكن الأنواع المرجعية لا تحتوي عليها (أي أنه يمكن تعيينها إلى قيم خالية) ويمكن التحقق مما إذا كان النوع يحتوي على نوع افتراضي باستخدام الكلمة الأساسية الافتراضية
نعيد كتابة القيمة الافتراضية لخاصية التبعية المحددة أعلاه إلى null، ويمكن أن تعمل بشكل جيد عندما لا يكون هناك PropertyChangedCallback، ولكن عندما يكون هناك إشعار بتغيير الخاصية، تحدث كارثة، وسيطرح البرنامج استثناءً، قائلًا إن النوع لا يحدث. مباراة.
DependencyProperty العامة الثابتة للقراءة فقط IsBoyProperty =
DependencyProperty.Register("IsBoy", typeof(bool), typeof(Student),
new UIPropertyMetadata(null,new PropertyChangedCallback(IsBoyPropertyChangedCallback)));
دعونا نلقي نظرة على نوع المرجع مرة أخرى إذا كانت القيمة الافتراضية فارغة، فسيكون كل شيء على ما يرام.
Ilist LovedGirl العامة
{
الحصول على { return (IList)GetValue(LovedGirlProperty });
set { SetValue(LovedGirlProperty, value });
}
DependencyProperty العامة الثابتة للقراءة فقط LovedGirlProperty =
DependencyProperty.Register("LovedGirl", typeof(IList), typeof(Student),
new UIPropertyMetadata(null, new PropertyChangedCallback(LovedGirlChangedCallback)));
الفراغ العام الثابت LovedGirlChangedCallback (DependencyObject d، DependencyPropertyChangedEventArgs e)
{
الطالب ش = د كطالب؛
foreach (عنصر var في e.NewValue كـ Ilist)
{
Console.WriteLine(item);
}
}
الفراغ العام TestReferenceDpType ()
{
List<string> list = new List<string>();
list.Add("فتاة 1");
list.Add("فتاة 2");
this.LovedGirl = list;
}
4. رد الاتصال القسري للسمة
أولاً، لا تزال القيمة الافتراضية لا تؤدي إلى تشغيل طريقة رد الاتصال.
تعني طريقة رد الاتصال القسري أنه سيتم إدخال طريقة رد الاتصال بغض النظر عما إذا كانت قيمة السمة قد تغيرت أم لا.
نقاط كثافة العمليات العامة
{
الحصول على { return (int)GetValue(ScoreProperty });
set {SetValue(ScoreProperty, value });
}
DependencyProperty ScoreProperty العامة الثابتة للقراءة فقط =
DependencyProperty.Register("Score"، typeof(int)، typeof(Student)،
new UIPropertyMetadata(0,null,new CoerceValueCallback(ScoreCoerceValueCallback)));
كائن ثابت عام ScoreCoerceValueCallback (DependencyObject d، object baseValue)
{
Console.WriteLine(baseValue);
إرجاع القيمة الأساسية؛
}
الفراغ العام TestCoerceValueCallback()
{
this.Score = 0;
this.Score = 0;
this.Score = 0;
}