استدعاء خاصية التبعية و التحقق من صحتها
يصف هذا الموضوع كيفية إنشاء خصائص تبعية باستخدام تطبيقات مخصصة بديلة للسمات المتعلقة بالخاصية مثل تحديد التحقق من الصحة ، وعمليات الاسترجاع التي يتم بها الاستدعاء عند تغيير القيمة الفعالة لخاصية وتجاوز التأثيرات الخارجية المحتملة على تحديد القيمة. يناقش هذا الموضوع أيضاً وحدات سيناريو حيث التوسع على السلوكيات الافتراضية لنظام الخاصية باستخدام هذه التقنيات مناسب.
يشتمل هذا الموضوع على الأقسام التالية.
- المتطلبات الأساسية
- التحقق من صحة عمليات الاسترجاعات
- فرض قيمة عمليات الاسترجاع وتغيير الأحداث للخاصية
- الفرض المتقدم وسيناريوهات الاستدعاء
- موضوعات ذات صلة
المتطلبات الأساسية
يفترض هذا الموضوع أنك على دراية بالسيناريوهات الأساسية لتطبيق خاصية تبعية، وكيفية تطبيق بيانات التعريف الى خاصية تبعية مخصصة. راجع خصائص التبعية المخصصة و الخاصية التبعية بيانات التعريف للسياق.
التحقق من صحة عمليات الاسترجاعات
يمكن تعيين عمليات الاسترجاع إلى خاصية تبعية عندما تقوم أولاً بتسجيلها. استدعاء التحقق من الصحة ليس جزءاً من بيانات التعريف انما هو إدخال مباشر للأسلوب Register. لذلك، بمجرد إنشاء استدعاء التحقق من الصحة لخاصية تبعية ، لا يمكن أن يتم تجاوزه من قبل تطبيق جديد.
Public Shared ReadOnly CurrentReadingProperty As DependencyProperty = DependencyProperty.Register("CurrentReading", GetType(Double), GetType(Gauge), New FrameworkPropertyMetadata(Double.NaN, FrameworkPropertyMetadataOptions.AffectsMeasure, New PropertyChangedCallback(AddressOf OnCurrentReadingChanged), New CoerceValueCallback(AddressOf CoerceCurrentReading)), New ValidateValueCallback(AddressOf IsValidReading))
Public Property CurrentReading() As Double
Get
Return CDbl(GetValue(CurrentReadingProperty))
End Get
Set(ByVal value As Double)
SetValue(CurrentReadingProperty, value)
End Set
End Property
public static readonly DependencyProperty CurrentReadingProperty = DependencyProperty.Register(
"CurrentReading",
typeof(double),
typeof(Gauge),
new FrameworkPropertyMetadata(
Double.NaN,
FrameworkPropertyMetadataOptions.AffectsMeasure,
new PropertyChangedCallback(OnCurrentReadingChanged),
new CoerceValueCallback(CoerceCurrentReading)
),
new ValidateValueCallback(IsValidReading)
);
public double CurrentReading
{
get { return (double)GetValue(CurrentReadingProperty); }
set { SetValue(CurrentReadingProperty, value); }
}
يتم تنفيذ عمليات الاسترجاع بحيث يتم توفير قيمة كائن. فإنها ترجع true إذا كانت القيمة المتوفرة صالحة للخاصية; وإلا، فإنها ترجع false. يتم افتراض أن الخاصية من النوع الصحيح لكل نوع مسجل مع نظام الخاصية بحيث لا يتم اجراء نوع التحقق ضمن عمليات الاسترجاع عادةً. عمليات الاسترجاع تُستخدم من قبل النظام في عمليات أخرى متنوعة. يتضمن هذا التهيئة الأولية للنوع بواسطة القيمة الافتراضية ، وتغيير برمجي بواسطة استدعاء SetValue، أو يحاول تجاوز بيانات التعريف بالقيمة الافتراضية الجديدة التي تم توفيرها. إذا تم استدعاء استدعاء التحقق من الصحة بواسطة أي من هذه العمليات وتم إرجاع false ، يمكن اجراء استثناء. يجب أن يتحضر كتّاب التطبيق لمعالجة هذه الاستثناءات. أحد الاستخدامات العامة لاستدعاءات التحقق من الصحة هو التحقق من صحة قيم التعداد أو وضع حدود على قيم أعداد صحيحة عندما تقوم الخاصية بتعيين القياسات التي يجب أن تكون صفر أو أكبر.
استدعاءات التحقق من الصحة بشكل خاص مخصصة لعمليات التحقق من صحة الفئة وليس التحقق من صحة المثيل. لا ترسل معلمات الاستدعاء DependencyObject معينة التى بناء عليها يتم تعيين الخصائص المطلوب التحقق من صحتها. ولذلك عمليات الاسترجاع للتحقق من الصحة غير مفيدة من أجل فرض تبعيات محتملة التي قد تؤثر على قيمة الخاصية ، حيث القيمة الخاصة لمثيل الخاصية يعتمد على عوامل مثل القيم الخاصة للمثيل للخصائص الأخرى أو حالة وقت التشغيل.
التالي هو مثال للتعليمات البرمجية لسيناريو رد اتصال التحقق من صحة بسيط جداً: التحقق من صحة أن الخاصية يتم كتابتها كالمجموعة الأساسية Double ليست PositiveInfinity أو NegativeInfinity.
Public Shared Function IsValidReading(ByVal value As Object) As Boolean
Dim v As Double = CType(value, Double)
Return ((Not v.Equals(Double.NegativeInfinity)) AndAlso (Not v.Equals(Double.PositiveInfinity)))
End Function
public static bool IsValidReading(object value)
{
Double v = (Double)value;
return (!v.Equals(Double.NegativeInfinity) && !v.Equals(Double.PositiveInfinity));
}
فرض قيمة عمليات الاسترجاع وتغيير الأحداث للخاصية
فرض قيمة عمليات الاسترجاع يقوم بتمرير مثيل DependencyObject معين للخصائص كما تفعل تطبيقات PropertyChangedCallback التى يتم استدعاؤها بواسطة النظام كلما تغيرت قيمة خاصية تبعية. باستخدام عمليات الاسترجاع هذه ، يمكنك إنشاء سلسلة من الخصائص على عناصر حيث التغييرات في أحد الخصائص سيقوم بفرض تغييرات على خاصية أخرى.
سيناريو نموذجي لاستخدام ربط الخصائص التبعية عندما يكون لديك خاصية تدار من قبل واجهة مستخدم حيث يحتوي العنصر على قيمة خاصية واحدة لكل من الحد الأدنى والأقصى و خاصية وثالثة للقيمة الفعلية أو الحالية. هنا إذا تم ضبط الحد الأقصى بطريقة تتجاوز فيها القيمة الحالية الحد الأقصى الجديد ، قد ترغب في فرض القيمة الحالية لتكون أصغر من الحد الأقصى الجديد وعلاقة مشابهة للحد الأدنى بالحالى.
التالي تعليمات المثال البرمجية مختصرة جداً لأحد الخصائص التبعية الثلاثة التي توضح هذه العلاقة. يوضح المثال كيف أن الخاصية CurrentReading للمجموعة أدنى/أقصى/الحالى * قراءة خصائص يتم تسجيلها. تستخدم التحقق من الصحة كما هو موضح في المقطع السابق.
Public Shared ReadOnly CurrentReadingProperty As DependencyProperty = DependencyProperty.Register("CurrentReading", GetType(Double), GetType(Gauge), New FrameworkPropertyMetadata(Double.NaN, FrameworkPropertyMetadataOptions.AffectsMeasure, New PropertyChangedCallback(AddressOf OnCurrentReadingChanged), New CoerceValueCallback(AddressOf CoerceCurrentReading)), New ValidateValueCallback(AddressOf IsValidReading))
Public Property CurrentReading() As Double
Get
Return CDbl(GetValue(CurrentReadingProperty))
End Get
Set(ByVal value As Double)
SetValue(CurrentReadingProperty, value)
End Set
End Property
public static readonly DependencyProperty CurrentReadingProperty = DependencyProperty.Register(
"CurrentReading",
typeof(double),
typeof(Gauge),
new FrameworkPropertyMetadata(
Double.NaN,
FrameworkPropertyMetadataOptions.AffectsMeasure,
new PropertyChangedCallback(OnCurrentReadingChanged),
new CoerceValueCallback(CoerceCurrentReading)
),
new ValidateValueCallback(IsValidReading)
);
public double CurrentReading
{
get { return (double)GetValue(CurrentReadingProperty); }
set { SetValue(CurrentReadingProperty, value); }
}
تغيير الخاصية رد الاتصال للحالى يتم استخدامها لإعادة توجيه التغيير إلى خصائص أخرى تعتمد بشكل صريح على استدعاء عمليات الاسترجاعات لقيمةالتي تم تسجيلها لهذه الخصائص:
Private Shared Sub OnCurrentReadingChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
d.CoerceValue(MinReadingProperty)
d.CoerceValue(MaxReadingProperty)
End Sub
private static void OnCurrentReadingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
d.CoerceValue(MinReadingProperty);
d.CoerceValue(MaxReadingProperty);
}
قيمة رد الاتصال تقوم بالتحقق من قيم الخصائص التي تعتمد عليها الخاصية الحالية ثم تحويل القيمة الحالية إذا لزم الأمر:
Private Shared Function CoerceCurrentReading(ByVal d As DependencyObject, ByVal value As Object) As Object
Dim g As Gauge = CType(d, Gauge)
Dim current As Double = CDbl(value)
If current < g.MinReading Then
current = g.MinReading
End If
If current > g.MaxReading Then
current = g.MaxReading
End If
Return current
End Function
private static object CoerceCurrentReading(DependencyObject d, object value)
{
Gauge g = (Gauge)d;
double current = (double)value;
if (current < g.MinReading) current = g.MinReading;
if (current > g.MaxReading) current = g.MaxReading;
return current;
}
ملاحظة |
---|
القيم الافتراضية للخصائص لا يمكن أن يتم فرضهاقد يحدث أن تكون قيمة خاصية تساوي القيمة الافتراضية إذا كانت القيمة الافتراضية للخاصية لا تزال تحتفظ بالقيمة الأولي الخاصة بها أو من خلال إلغاء القيم الأخرى مع ClearValue. |
قيمة المفروضة وعمليات الاسترجاع للخاصية المتغيرة هى جزء من بيانات التعريف. لذلك، يمكنك تغيير عمليات الاسترجاع لخاصية تبعية معينة لأنها تتواجد على نوع تقوم باشتقاقه من النوع الذي يملك الخاصية التبعية ، بواسطة تجاوز بيانات التعريف لتلك الخاصية على النوع الخاص بك.
الفرض المتقدم وسيناريوهات الاستدعاء
القيود والقيم المطلوبة
سوف يتم استخدام استدعاءات CoerceValueCallback بواسطة النظام لفرض قيمة تبعاً للمنطق الذي تقوم بتعريفه ولكن القيمة المفروضة لخاصية يتم تعيينها محلياً لا يزال سيحتفظ "بالقيمة المطلوبة" داخلياً. إذا كانت القيود تستند على بعض القيم الأخرى للخاصية التي قد تتغير بشكل حيوي أثناء مدة عمر التطبيق ، تتغير القيود القسرية بشكل حيوي أيضاً وتقوم الخاصية المقيدة بتغيير القيمة الخاصة بها لتقترب من القيمة المرغوبة قدر المستطاع مع وجود القيود الجديدة. ستصبح القيمة هى القيمة المطلوبة إذا تم رفع كافة القيود. يمكنك تقديم بعض وحدات السيناريو التبعية المعقدة اذا كان لديك عدة خصائص التي تعتمد على بعضها البعض بطريقة دائرية. على سبيل المثال، في سيناريو الأدنى/الأقصى /الحالى ، تكون قد اخترت أن الحد الأدنى والحد الأقصى تكون قابلة للتعيين من قبل المستخدم. اذا كانت كذلك قد تحتاج لفرض أن الأقصى دائماً أكبر من الأدنى والعكس ولكن إذا كان هذا التصحيح نشطاً ويتم تحويل الأقصى إلى الأدنى يتم ترك الحالى في حالة غير معينة لأنه يعتمد على كل من الأدنى والأقصى ومقيد بالنطاق بين القيم والذى هو الصفر. ثم إذا تم ضبط الحد الأقصى أو الأدنى صواب سوف يبدو الحالى كما لو كان "يتتبع" إحدى القيم، لأن القيمة المطلوبة للحالى لا تزال مخزنة وتقوم بمحاولة الوصول إلى القيمة المطلوبة كلما تم تجاهل القيود.
لا يوجد شيء غير صحيح تقنيًا للتبعيات المعقدة إلا أنها يمكن أن تكون محددة للأداء بشكل بسيط إذا كانت تتطلب أعداد كبيرة من عمليات اعادة التعيين ويمكن أن يكون مربكاً للمستخدمين إذا كان تأثيرها على واجهة المستخدم مباشر. كن حذراً مع تغيير الخاصية وفرض قيم عمليات الاسترجاع وتأكد من أن محاولات القسر يمكن معاملتها بشكل واضح كما لا تقوم بزيادة القيود.
استخدام CoerceValue لإلغاء تغييرات القيمة
سيعامل النظام أي CoerceValueCallback التي ترجع القيمة UnsetValue كحالة خاصة. هذه الحالة الخاصة تعني أن تغير الخاصية الذي نتج عنه استدعاء CoerceValueCallback يجب أن يتم رفضه من قبل النظام وأن النظام ينبغي عليه أن يرسل تقرير بغض النظر عن القيمة السابقة للخاصية. يمكن أن تكون هذه الآلية مفيدة للتحقق من تغييرات الخاصية التي تمت تهيئتها بشكل غير متزامن لا تزال صالحة من أجل حالة الكائن الحالية ومنع التغييرات إذا لم يكن هذا متحققاً. سيناريو آخر محتمل أنه يمكنك بشكل انتقائي منع قيمة استناداً إلى أي مكون يقوم بتحديد قيمة الخاصية مسؤول عن القيمة التى يتم الإبلاغ عنها. للقيام بذلك، يمكنك استخدام DependencyProperty التى يتم تمريرها فى الاستدعاء ومعرف الخاصية كإدخال لعناصر GetValueSource ، ثم معالجة ValueSource.