نظرة عامة حول الكائنات المجمدة
يصف هذا الموضوع كيفية استخدام وإنشاء كائنات Freezable بفاعلية ، مما يوفر ميزات خاصة يمكن أن تحسن أداء التطبيق. أمثلة للكائنات المجمدة فرشاة و الأقلام و التحويلات و الهندسات و الحركات.
يشمل هذا الموضوع على الأقسام التالية.
ما هي المحتويات المجمدة ؟
إن Freezable هو نوع خاص من الكائنات يحتوي على حالتين: غير مجمد و مجمد. عند عدم التجميد ، يظهر Freezable ليسلك مثل أي كائن آخر . عند التجميد ، فإن Freezable لا يمكن تعديله بعد الآن.
إن Freezable يوفر الحدث Changed لإعلام الملاحظين بأية تعديلات على الكائن. تجميد Freezable يمكنه تحسين الأداء الخاص به لأنه لم يعد يحتاج إلى صرف الموارد في إعلامات التغيير. إن Freezable المجمد يمكن مشاركته أيضاً عبر مؤشرات ترابط في حين لا يستطيع Freezable الغير مجمد.
على الرغم من إن فئة Freezable تحتوي على العديد من التطبيقات ، فإن أكثر كائنات Freezable في Windows Presentation Foundation (WPF) متعلقة صواب بالرسومات الخاصة بالنظام الفرعي .
إن فئة Freezable تسهّل استخدام كائنات نظام رسومات معين كما يساعد على تحسين أداء التطبيق. الأمثلة على الأنواع التي ترث من Freezable تتضمن فئات Brush ، Transform ، و Geometry . لأنها تحتوي على موارد غير مدارة ، يجب على النظام مراقبة هذه الكائنات للتعديلات، ثم تحديث مواردها الغير مدارة المطابقة عندما يتم التغيير على الكائن الأصلي. حتى في حالة عدم تعديلك لرسومات كائن النظام فعلياً، فلابد أن يظل النظام يستهلك بعض الموارد الخاصة به لمراقبة الكائن، في حالة تغييره.
على سبيل المثال، افترض أنك تقوم بإنشاء فرشاة SolidColorBrush واستخدامها لرسم خلفية الزر.
Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)
myButton.Background = myBrush
Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
myButton.Background = myBrush;
عند تقديم زر ، فإن النظام الفرعي الخاص بالرسومات WPF يستخدم المعلومات التي وفرتها لرسم مجموعة من وحدات البكسل لإنشاء مظهر الزر. على الرغم من استخدامك فرشاة لون خالص لوصف كيف يجب أن يتم تلوين الزر ، فإن فرشاة اللون الخالص الخاص بك لا تقوم فعلياً بالرسم . ينشئ نظام الرسومات كائنات سريعة ، ذات مستوى منخفض للزر الفرشاة وهذة هي الكائنات لكنها لا تظهر على الشاشة.
إذا كنت تريد تعديل الفرشاة ، فإن تلك الكائنات ذات المستوى المنخفض يجب أن يتم اعادة انشائها . الفئة المجمدة هي ما يعطي الفرشاة القدرة على العثور على الكائنات ذات المستوى المنخفض ، المنشأة المقابلة الخاصة به لتحديثها عندما تتغير. عند تمكين هذه القدرة فإن الفرشاة تقال لها "غير مجمدة".
أسلوب Freeze الخاص بالمجمد يتيح لك تعطيل هذه القدرة "التطوير الذاتي ". يمكنك استخدام هذا الأسلوب لجعل الفرشاة تصبح "مجمد" أو غير قابلة للتعديل.
ملاحظة |
---|
ليس كل كائن قابل للتجميد يمكن تجميده.لتجنب القاء InvalidOperationException ، تحقق من قيمة خاصية CanFreeze الخاصة بالكائن القابل للتجميد لتحديد ما إذا كان يمكن تجميده قبل محاولة تجميده. |
If myBrush.CanFreeze Then
' Makes the brush unmodifiable.
myBrush.Freeze()
End If
if (myBrush.CanFreeze)
{
// Makes the brush unmodifiable.
myBrush.Freeze();
}
عند عدم احتياجك لتعديل الكائن القابل للتجميد ، تجميده فإنه يوفر مزايا الأداء. إذا كنت تريد تجميد الفرشاة في هذا المثال ، فإن نظام الرسومات لا يعود بحاجة إلى مراقبته للتغييرات. نظام الرسومات يمكنه ايضاً القيام بتحسينات أخرى بسبب أنه يعرف إن الفرشاة لن تتغير .
ملاحظة |
---|
تسهيلاً ، فإن الكائنات القابلة للتجميد تبقى غير مجمدة حتى تقوم بتجميدها بشكل صريح . |
استخدام الكائنات القابلة للتجميد
استخدام كائنات قابلة للتجميد غير مجمدة يشبه أن تستخدم أي نوع آخر من الكائن. في المثال التالي ، لون SolidColorBrush يتم تغييره من الأصفر إلى اللون الأحمر بعد استخدامه لرسم خلفية الزر. يعمل نظام الرسومات في الخلفية لتغيير الزر تلقائياً من الأصفر إلى اللون الأحمر في المرة التالية التي يتم فيها تحديث الشاشة.
Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)
myButton.Background = myBrush
' Changes the button's background to red.
myBrush.Color = Colors.Red
Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
myButton.Background = myBrush;
// Changes the button's background to red.
myBrush.Color = Colors.Red;
تجميد الكائنات القابلة للتجميد
لجعل Freezableغير قابلة للتعديل ، تقوم بالاتصال بالاسلوب Freeze الخاص به. عند تجميد الكائن الذي يحتوي على كائنات قابلة للتجميد ، تلك الكائنات يتم تجميدها أيضاً. على سبيل المثال، إذا قمت بتجميد PathGeometry ، فإن الصور و جمل التي تحتوي عليها يمكن تجميدها أيضاً.
لا يمكن تجميد كائن قابل للتجميد إذا تحققت أي من الإجراءات التالية:
تحتوي على رسومات متحركة أو بيانات مرتبطة بالخصائص.
يحتوي على الخصائص التي تم تعيينها بواسطة المورد الحيوي. (راجع نظرة عامة حول الموارد للحصول على مزيد من المعلومات حول الموارد الحيوية.)
يحتوي على كائنات فرعية لــ Freezableيتعذر تجميدها .
إذا كانت هذه الشروط غير متحققة و أنت لا تنوي تعديل Freezable ، لذا فيجب عليك تجميدها للحصول على مزايا الأداء الذي تم وصفه سابقاً.
بمجرد استدعاء اسلوب Freeze الخاص بالكائن القابل للتجميد, لا يمكن تعديله بعد هذا . محاولة لتعديل كائن مجمد يتسبب في طرح InvalidOperationException . تطرح التعليمة البرمجية التالية استثناء ، لمحاولتنا تعديل الفرشاة بعد تجميدها .
Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)
If myBrush.CanFreeze Then
' Makes the brush unmodifiable.
myBrush.Freeze()
End If
myButton.Background = myBrush
Try
' Throws an InvalidOperationException, because the brush is frozen.
myBrush.Color = Colors.Red
Catch ex As InvalidOperationException
MessageBox.Show("Invalid operation: " & ex.ToString())
End Try
Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
if (myBrush.CanFreeze)
{
// Makes the brush unmodifiable.
myBrush.Freeze();
}
myButton.Background = myBrush;
try {
// Throws an InvalidOperationException, because the brush is frozen.
myBrush.Color = Colors.Red;
}catch(InvalidOperationException ex)
{
MessageBox.Show("Invalid operation: " + ex.ToString());
}
لتجنب طرح هذا الاستثناء ، يمكنك استخدام أسلوب IsFrozen لتحديد ما إذا كان Freezable قد تم تجميده.
Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)
If myBrush.CanFreeze Then
' Makes the brush unmodifiable.
myBrush.Freeze()
End If
myButton.Background = myBrush
If myBrush.IsFrozen Then ' Evaluates to true.
' If the brush is frozen, create a clone and
' modify the clone.
Dim myBrushClone As SolidColorBrush = myBrush.Clone()
myBrushClone.Color = Colors.Red
myButton.Background = myBrushClone
Else
' If the brush is not frozen,
' it can be modified directly.
myBrush.Color = Colors.Red
End If
Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
if (myBrush.CanFreeze)
{
// Makes the brush unmodifiable.
myBrush.Freeze();
}
myButton.Background = myBrush;
if (myBrush.IsFrozen) // Evaluates to true.
{
// If the brush is frozen, create a clone and
// modify the clone.
SolidColorBrush myBrushClone = myBrush.Clone();
myBrushClone.Color = Colors.Red;
myButton.Background = myBrushClone;
}
else
{
// If the brush is not frozen,
// it can be modified directly.
myBrush.Color = Colors.Red;
}
في المثال السابق للتعليمات البرمجية، يتم انشاء نسخة قابلة للتعديل من كائن مجمد باستخدام اسلوب Clone . القطاع التالي يناقش الاستنساخ بمزيد من التفاصيل.
ملاحظة لأن الكائنات القابلة للتجميد المجمدة لا يمكن تحريكها ، سيقوم نظام الحركة تلقائيًا بإنشاء نسخ قابلة للتعديل من كائنات Freezable مجمدة عند محاولتك تحريكها بــ Storyboard. للتخلص من حمولة الأداء الذي سببه استنساخ, اترك كائن غير مجمد إذا كنت تريد تحريكه. للحصول على مزيد من المعلومات حول التحريك بلوحة العمل ، راجع نظرة عامة حول لوحات العمل.
تجميد علامات النموذج
لتجميد كائن Freezable تم تعريفه في العلامات ، يمكنك استخدام سمة PresentationOptions:Freeze . في المثال التالي SolidColorBrush تم تعريفه كمورد صفحة و مجمد. ثم تُستخدم لتعيين زر الخلفية .
<Page
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOptions="https://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions">
<Page.Resources>
<!-- This resource is frozen. -->
<SolidColorBrush
x:Key="MyBrush"
PresentationOptions:Freeze="True"
Color="Red" />
</Page.Resources>
<StackPanel>
<Button Content="A Button"
Background="{StaticResource MyBrush}">
</Button>
</StackPanel>
</Page>
لاستخدام سمة Freeze , يجب عليك التعيين إلى مساحة اسم خيارات العرض التقديمي: https://schemas.microsoft.com/winfx/2006/xaml/presentation/options. PresentationOptionsهو البادئة الموصى بها لتعيين مساحة الاسم هذه:
xmlns:PresentationOptions="https://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
لأن ليس كل قراء XAML يتعرفون على هذه السمة, فمن المستحسن استخدام mc: سمة مهملة صواب لوضع علامة على سمة Presentation:Freeze كـمتجاهلة:
xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions"
لمزيد من المعلومات، راجع صفحة mc: سمة مهملة.
عدم تجميد الكائنات القابلة للتجميد
متى تم التجميد ، Freezable لا يمكن تعديله أبداً أو عدم تجميده ومع ذلك، يمكنك إنشاء نسخة غير مجمدة باستخدام أسلوبClone أو CloneCurrentValue .
في المثال التالي، يتم تعيين خلفية الزر بالفرشاة ثم يتم تجميد الفرشاة . يتم انشاء نسخة غير مجمدة من الفرشاة باستخدام اسلوب Clone . تم تعديل النسخة و استخدامها لتغيير خلفية الزر من الأصفر إلى اللون الأحمر.
Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)
' Freezing a Freezable before it provides
' performance improvements if you don't
' intend on modifying it.
If myBrush.CanFreeze Then
' Makes the brush unmodifiable.
myBrush.Freeze()
End If
myButton.Background = myBrush
' If you need to modify a frozen brush,
' the Clone method can be used to
' create a modifiable copy.
Dim myBrushClone As SolidColorBrush = myBrush.Clone()
' Changing myBrushClone does not change
' the color of myButton, because its
' background is still set by myBrush.
myBrushClone.Color = Colors.Red
' Replacing myBrush with myBrushClone
' makes the button change to red.
myButton.Background = myBrushClone
Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
// Freezing a Freezable before it provides
// performance improvements if you don't
// intend on modifying it.
if (myBrush.CanFreeze)
{
// Makes the brush unmodifiable.
myBrush.Freeze();
}
myButton.Background = myBrush;
// If you need to modify a frozen brush,
// the Clone method can be used to
// create a modifiable copy.
SolidColorBrush myBrushClone = myBrush.Clone();
// Changing myBrushClone does not change
// the color of myButton, because its
// background is still set by myBrush.
myBrushClone.Color = Colors.Red;
// Replacing myBrush with myBrushClone
// makes the button change to red.
myButton.Background = myBrushClone;
ملاحظة |
---|
بغض النظر عن أي أسلوب مستنسخ تستخدمه فإن الحركات لا يتم أبداً نسخها إلى Freezable.الجديد |
أساليب Clone و CloneCurrentValue تقوم بإنتاج نسخ عميقة من الكائن القابل للتجميد. إذا كان القابل للتجميد يحتوي على كائنات قابلة للتجميد مجمدة أخرى ، هي أيضاً مستنسخة و منشأة قابلة للتعديل . على سبيل المثال، إذا قمت باستنساخ PathGeometry مجمد لجعله قابل للتعديل,فإن الصور و الجمل التي يحتوي عليها يتم نسخها و منشأة قابلة للتعديل .
إنشاء فئة القابل للتجميد الخاص بك
الفئة المشتقة من Freezable تكسب الميزات التالية.
حالات خاصة: في وضع القراءة فقط (المجمدة) وحالة قابل للكتابة.
أمان مؤشر الترابط إن Freezable المجمد يمكن مشاركته عبر مؤشرات الترابط.
إعلام تغيير مفصل: بعكس DependencyObject الأخرى ، فإن الكائنات القابلة للتجميد توفر إعلامات التغيير عند تغيير قيم الخاصية الفرعية .
استنساخ سهل: إن الفئة القابلة للتجميد تحتوي بالفعل على تنفيذ العديد من الطرق التي تُنتج نسخ عميقة .
إن Freezable هو نوع من DependencyObject ، ويستخدم والتالي نظام خاصية التبعية . لا يلزم أن تكون لدى خصائص فئتك خصائص التبعية ولكن استخدام خصائص التبعية ستؤدي إلى تقليل مقدار التعليمات البرمجية لديك للكتابة، لأن فئة Freezable تم تصميمها بخصائص التبعية في الاعتبار. للحصول على مزيد من المعلومات حول نظام خاصية التبعية ، راجع نظرة عامة حول خصائص التبعية.
كل فئةFreezableفرعية يجب أن تتجاوز الأسلوب CreateInstanceCore . إذا كانت الفئة الخاصة بك تستخدم خصائص التبعية لكافة بياناتها ، هكذا انتهيت.
إذا كانت الفئة تحتوي على بيانات خصائص غير التبعية ، يجب عليك أيضاً تجاوز الطرق التالية:
يجب أيضًا ملاحظة القواعد التالية للحصول على الوصول إلى البيانات والكتابة على أعضاء الفريق و التي هي غير خصائص التبعية:
في بداية أي API الذي يقرأ اعضاء بيانات خصائص غير التبعية ،قم باستدعاء اسلوب ReadPreamble .
في بداية أي API يكتب على اعضاء بيانات خاصية غير تبعية ، قم باستدعاء اسلوب WritePreamble . (بمجرد قمت باستدعاء WritePreamble في API ، لا تحتاج إلى إجراء استدعاء إضافية إلى ReadPreamble إذا أيضاً تقوم بقراءة اعضاء بيانات خصائص غير التبعية .)
قم بااستدعاء الأسلوب WritePostscript قبل إنهاء أساليب الكتابة إلى اعضاء بيانات خصائص غير التبعية .
إذا كانت الفئة الخاصة بك تحتوي على أعضاء البيانات الخاصة بخاصية غير التبعية مما يعني كائنات DependencyObject ، يجب أيضاً استدعاء أسلةب OnFreezablePropertyChanged في كل مرة تقوم فيها بتغيير على القيم الخاصة بهم حتى في حالة تعيين العضو إلى null.
ملاحظة |
---|
من المهم جداً تبدأ كل أسلوب Freezable تجاوزته باستدعاء إلى تطبيق القاعدة. |
للحصول على مثال فئة Freezable المخصصة, راجع نموذج حركة مخصصة.