התנהגויות ב-WPF

הכרות עם התנהגויות

התנהגות, או Behavior בלעז, הוא קונספט חדש יחסית ב-Silverlight ו-WPF, אך מאוד מוצלח. הרעיון הוא לממש יכולות מסויימות (התנהגות) באובייקט נפרד בצורה שיכולה להתלבש על אובייקטים קיימים ולהוסיף להם את ההתנהגות שמימשנו. לדוגמה, כדי לאפשר למשתמש לגרור (Drag) אלמנט באפליקציה, ניתן לממש יכולת זו כהתנהגות, ואז נוכל להוסיף התנהגות זו לכל אלמנט שנרצה שיהיה בר-גרירה. מימוש ההתנהגות עצמה נעשה על-ידי מפתח התוכנה (Developer) בעזרת קוד C#. לאחר שאובייקט ההתנהגות מומש, מעצב התוכנה (Designer) יכול להשתמש בו על כל אלמנט על-ידי גרירה של ההתנהגות הרצויה אל האלמנט בעזרת כלי עיצוב כמו Microsoft Blend.

למה זה טוב?
התנהגויות מאפשרות להוסיף יכולות חדשות לאלמנטים קיימים של WPF, בצורה שמאוד מותאמת לסגנון העבודה בWPF, מפתח מול מעצב. המפתח מממש את היכולת החדשה בשיטה של Behavior ואילו המעצב משתמש ביכולת שפותחה ע"י גרירת ההתנהגות אל האלמנט המבוקש. בנוסף, שימוש בהתנהגויות נותן לנו כמפתחים שיטה חדשה לשימוש חוזר בקוד שאינה מבוססת על ירושה (Inheritance).
שימוש בהתנהגויות בעזרת Blend
ראשית, נציג כיצד להשתמש בהתנהגויות תוך שימוש בכלי Microsoft Expression Blend 4. יש לציין כי כלי זה הינו כלי עזר לעבודה בעיצוב אפליקציות WPF ו-Silverlight, וכי ניתן להוריד גרסת התנסות ל-60 יום בקישור הבא. בדוגמה הבאה ניצור פרויקט WPF חדש בעזרת Blend, נוסיף לו אלמנט מטיפוס אליפסה ונוסיף לאליפסה התנהגות של גרירה. בעזרת התנהגות זו נוכל בזמן ריצה לתפוס את האליפסה עם העכבר ולהזיז אותה לכל מקום באפליקציה שלנו:
נפתח Blend על-ידי בחירתו מרשימת התוכניות וניצור פרויקט WPF חדש על-ידי לחיצה על New Project.
כעת נבחר את הקטגוריה WPF, נבחר את סוג האפליקציה WPF Application, ונעניק לה שם: BehaviorsDemo, לבסוף נאשר את היצירה על-ידי לחיצה על הכפתור OK.
נבחר אוביקט מטיפוס אליפסה ע"י לחיצה על Assets, לאחר מכן נבחר Shapes, ומתוך הצורות האפשריות נבחר Ellipse.
כעת נלך למשטח העבודה ונצייר את האליפסה. ניתן לשנות את צבעה על-ידי בחירה מתוך פקד הצבעים שמופיע מימין למשטח העבודה.
כעת נרצה להוסיף לאליפסה שלנו התנהגות של גרירה, כלומר נרצה לאפשר למשתמש לגרור את האליפסה בתוך האפליקציה. לצורך כך נבחר בקטגוריה Behaviors ומתוכה נבחר בהתנהגות MouseDragElementBehavior.
כעת נלחץ (בלי לעזוב) על MouseDragElementBehavior ונגרור את העכבר אל הצורה שעבורה אנו רוצים להוסיף את ההתנהגות, במקרה שלנו אל האליפסה, ונשחרר את העכבר.
סיימנו! כל מה שנדרש בשביל להוסיף את התנהגות הגרירה לאליפסה היה לגרור את אובייקט ההתנהגות מעל האליפסה. כעת נריץ את התוכנית על-ידי לחיצה על תפריט Project ובחירה Run Project, או לחילופין לחיצה על מקש F5.
כעת נסו בעצמכם לגרור את האליפסה בתוך האפליקציה.
ניתן להוריד את הקוד המלא בכתובת הבאה: BehaviorsDemo.zip. הערה: ניתן להריץ את התוכנית בקלות על-ידי הפעלת הקובץ BehaviorsDemo.exe בספריה bin/Debug.
התנהגויות ב-Visual Studio
כעת נראה כיצד להשתמש בהתנהגויות תוך שימוש בכלי Microsoft Visual Studio 2010 ונממש את אותה הדוגמא כמו מקודם, אבל הפעם ללא שימוש בכלי העיצוב (Designers): ראשית, נפתח פרויקט חדש מסוג WPF Application, ונקרא לו BehaviorsDemoVS.
כעת נוסיף את ה-References הדרושים לצורך הכרה של מנגנון ההתנהגויות. נלך ל- Solution Explorer, נלחץ עם הכפתור הימני בעכבר על References ונבחר ב-Add Reference.
כעת נלחץ על Browse, נעבור לספריה:
C:\Program Files\Microsoft SDKs\Expression\Blend\.NETFramework\v4.0\Libraries
נבחר את הקבצים: System.Windows.Interactivity.dll, Microsoft.Expression.Interactions.dll ונלחץ על OK לצורך הוספתם לפרויקט. ראוי לציין כי קבצים אלו מגיעים כחלק מהתקנת Blend 4. לחילופין, ניתן להתקין אותם על-ידי הורדה של Microsoft Expression Blend 4 SDK בכתובת הבאה.
נכתוב את הקוד הבא ב MainPage.xaml לצורך הוספת האליפסה והתנהגות הגרירה:
שימו לב, כל מה שנדרש לצורך הוספת התנהגות הגרירה לאליפסה הוא הוספת 3 שורות ב-XAML. בפרט, אין צורך בכתיבת קוד C#. כעת לחצו על F5 להרצת התוכנית ונסו לגרור את האליפסה.
היכן ניתן למצוא התנהגויות?
מלבד ההתנהגויות שקיימות ב-Microsoft Blend ניתן למצוא התנהגויות שפותחו על-ידי הקהילה באתר Microsoft Expression Gallery:
סיכום ביניים
בחלק זה של המדריך למדנו מהן התנהגויות, מה היתרונות בשימוש בהן וכיצד משתמשים בהן בעזרת הכלים Microsoft Blend ו-Microsoft Visual Studio. בחלק הבא נלמד מהו תהליך הפיתוח של התנהגות חדשה וכן נראה דוגמה מלאה למימוש של התנהגות.
בחלק זה נלמד כיצד ליצור התנהגות חדשה בעזרת Visual Studio 2010, ולכן מיועד למפתחים בעל ניסיון בפיתוח בטכנולוגיית WPF.
מתכון ליצירת התנהגות
ראשית, ניצור מחלקה חדשה שיורשת מ Behavior>T>. לאחר מכן נדרוס (Override) את הפונקציה OnAttached. פונקציה זו נקראת פעם אחת כאשר ההתנהגות משוייכת לאלמנט, ובה נבצע את השינויים הדרושים על האלמנט שאליו ההתנהגות משוייכת (AssociatedObject). בדרך כלל, נשנה את התכונות של האלמנט עליו אנו פועלים וכן נרשם לאירועים שמעניינים אותנו. לאחר מכן נדרוס את הפונקציה OnDetaching, אשר נקראת פעם אחת כאשר ההתנהגות מוסרת מאלמנט. בפונקציה זו נבטל את השינויים שעשינו בפונקציה OnAttached. אם אנו בטוחים שלא יסירו את ההתנהגות במהלך ריצת התוכנית, ניתן לוותר על מימוש פונקציה זו.
דוגמא למימוש התנהגות
בדוגמא זו נממש אפקט של שיקוף-מראה לאלמנטים ב-WPF. נכתוב את האפקט בתור התנהגות כך שנוכל אחר כך להשתמש בה על כל אלמנט על-ידי גרירה של ההתנהגות ב-Blend אל האלמנט הרצוי.
נפתח פרויקט חדש מסוג WPF Application, ונקרא לו WpfReflectionBehaviorDemo.
כעת נוסיף את ה-Reference הדרוש לצורך הכרת המחלקה Behavior>T>. כעת נלך ל-Solution Explorer, נלחץ עם כפתור ימני בעכבר על References ונבחר Add Reference.
כעת נלחץ על Browse, נעבור לספריה:
C:\Program Files\Microsoft SDKs\Expression\Blend\.NETFramework\v4.0\Libraries
נבחר את הקובץ: System.Windows.Interactivity.dll ונלחץ על OK לצורך הוספתו לפרויקט. יש לציין כי קובץ זה מגיע כחלק מהתקנת Blend 4. לחילופין, ניתן להתקין אותו על-ידי הורדה של Microsoft Expression Blend 4 SDK בכתובת הבאה.
על מנת להוסיף מחלקה חדשה נלחץ עם כפתור ימני בעכבר על שם הפרויקט (WpfReflectionBehaviorDemo) בחלון Solution Explorer, נבחר באפשרות Add ואז Class.
ניתן למחלקה החדשה את השם ReflectionBehavior ונאשר על-ידי לחיצה על כפתור OK.
נשנה את המחלקה כך שתהיה נגישה מכל מקום (Public) וכן תבצע ירושה מהמחלקה <Behavior<FrameworkElement. משמעות הפרמטר FrameworkElement היא שניתן להצמיד את ההתנהגות שאנו מגדירים רק על אלמנטים שיורשים מ-FrameworkElement:
public class ReflectionBehavior : Behavior<FrameworkElement>
{
}
יש להוסיף בשלב זה לראש הקובץ את השורות הבאות:
;using System.Windows
;using System.Windows.Controls
;using System.Windows.Data
;using System.Windows.Interactivity
;using System.Windows.Media
מימוש OnAttached

ראשית נוסיף דריסה (Override) של הפונקציה OnAttached:

הגדרת הפונקציות ReplaceControlWithProxyGrid ו-AddReflectionEffect תגיע מיד בצירוף הסבר. רשאית, כדי לממש אפקט שיקוף-מראה יש צורך להוסיף אלמנט נוסף לעץ הלוגי שיציג את תמונת השיקוף. לכן, בשלב ראשון אנו נחליף את האלמנט הקיים באלמנט מסוג Grid שיכיל את האלמנט המקורי וכן אלמנט נוסף שיציג את תמונת השיקוף.
בשביל להחליף את האלמנט המקורי באלמנט Grid יש צורך להסיר אותו מה-Container שמכיל אותו ולצרף במקומו את אלמנט ה-Grid. יש לטפל בשני מקרים שונים לפי סוג ה-Container שמכיל את האלמנט המקורי: מקרה שבו ה-Container של האלמנט המקורי יורש מ-Panel ומ-ContentControl. קטע הקוד הבא מבצע את הטיפול בשני המקרים:
כעת נרצה להוסיף את אפקט השיקוף-מראה לאלמנט החדש שהוספנו. כדי ליצור את האפקט נשתמש ביכולות הבאות:
  • VisualBrush לצורך ציור האלמנט המקורי
  • ScaleTransform לצורך היפוך הציור של האלמנט המקורי
  • TranlateTransform לצורך הזזת הציור של האפקט אל מתחת לאלמנט המקורי
  • OpacityMask לצורך יצירת ציור שהולך ונהיה שקוף
 קטע הקוד הבא משתמש ביכולות אלו ליצירת האפקט:
בכך סיימנו לממש את ההתנהגות. ראוי לציין שהמימוש אינו מושלם ואם נרצה להשתמש בו באפליקציה אמיתית יש לטפל במקרי קצה נוספים וכן לממש גם את הפונקציה OnDetaching כך שתסיר את השינויים שעשינו. יחד עם זאת, לצורך הדגמת הנושא המימוש הנ"ל מספיק טוב.
שימוש בהתנהגות החדשה
בשביל להדגים את השימוש בהתנהגות החדשה שיצרנו נוסיף לאפליקציה שלנו כפתור ותמונה, ונוסיף לכל אחד מהם ההתנהגות החדשה. קטע הקוד הבא מראה כיצד להגדיר זאת:
ניתן להוריד את הקוד המלא בכתובת הבאה: WpfReflectionBehaviorDemo.zip. הערה: ניתן להריץ את התוכנית בקלות על-ידי הפעלת הקובץ WpfReflectionBehaviorDemo.exe בספריה bin/Debug.
סיכום

בחלק זה למדנו מהו תהליך הפיתוח של התנהגות חדשה וכן ראינו דוגמה מלאה למימושה. כל הנותר לנו לעשות כעת הוא לאחל לכם בהצלחה, ובמידה ונתקלתם בבעיות אל תהססו להיעזר בפורומי התכנות שלנו!

אריק הוא יועץ בכיר בקבוצת סלע, ומפעיל בלוג ברשת בנושא פיתוח: http://blogs.microsoft.co.il/blogs/arik