מדריך Windows Phone – שימוש ב Routed Events
הקדמה
בפרק שעבר למדנו שבWPF ו Silverlight החליטו לשפר את מערכת הProperties ולהוסיף Properties בעלי יתרונות חדשים שנקראים Dependency Properties. באותו אופן, גם Events (אירועים) היו זקוקים למקצה שיפורים, ולEvents מהסוג החדש קוראים Routed Events. אלו אירועים בעלי יתרונות ביחד לאירועים הרגילים בשפת #C. גם פרק זה יהיה בעיקר תיאורטי.
יתרונות Routed Events
הרעיון המרכזי ב Routed Events הוא שכאשר אירוע מופעל, הוא מופעל מספר פעמים, על פקדים נוספים בעץ הפקדים באפליקציה שלנו. לדוגמא, אם יש לנו את מבנה האפליקציה הבא:
<phone:PhoneApplicationPage
x:Class="PhoneDemo.MainPage"
>="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
>:x="http://schemas.microsoft.com/winfx/2006/xaml"
>:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
>:d="http://schemas.microsoft.com/expression/blend/2008"
>:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignWidth="480"
d:DesignHeight="800"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
Orientation="Portrait"
SupportedOrientations="Portrait">
<StackPanel>
<Button>
<StackPanel
Orientation="Horizontal">
<Image
Source="/PhoneDemo;component/Images/Koala.jpg"
Width="100" />
<TextBlock
Text="text next to image"
VerticalAlignment="Center"
Margin="10" />
</StackPanel>
</Button>
</StackPanel>
</phone:PhoneApplicationPage>
באפליקציה זו יש לנו חלון שבתוכו StackPanel ובתוכו כפתור, והכפתור מכיל תמונה וטקסט.
נניח שאירועים היו מתנהגים כרגיל, ולא כמו שRouted Events עובדים. ונניח שנרצה להגיב לאירוע לחיצה ארוכה על הכפתור שלנו, אזי נצטרך להירשם לאירוע Hold. אבל מה היה קורה אם היינו מבצעים את הלחיצה על התמונה שנמצאת בתוך הכפתור? מי שיקבל את הלחיצה ויפעיל את האירוע הוא אותה תמונה ולא הכפתור! כלומר אם נרצה שיופעל הקוד שלנו בעת לחיצה ימנית על הכפתור (בתוך התמונה ומחוצה לה!), יש להירשם לאירוע גם של הכפתור, גם של התמונה, גם של הפקד TextBlock וגם של ה StackPanel! כמובן שמצב כזה הוא מאוד מסורבל ולא נוח. הקוד הדרוש לרישום לכל האירועים הללו יראה כך:
<phone:PhoneApplicationPage
x:Class="PhoneDemo.MainPage"
>="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
>:x="http://schemas.microsoft.com/winfx/2006/xaml"
>:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
>:d="http://schemas.microsoft.com/expression/blend/2008"
>:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignWidth="480"
d:DesignHeight="800"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
Orientation="Portrait"
SupportedOrientations="Portrait">
<StackPanel>
<Button
Hold="Button_Hold">
<StackPanel
Orientation="Horizontal"
Hold="Button_Hold">
<Image
Source="/PhoneDemo;component/Images/Koala.jpg"
Width="100"
Hold="Button_Hold" />
<TextBlock
Text="text next to image"
VerticalAlignment="Center"
Margin="10"
Hold="Button_Hold" />
</StackPanel>
</Button>
</StackPanel>
</phone:PhoneApplicationPage>
התוספת המרכזית בRouted Events היא שלאחר שהאירוע שלנו מופעל על התמונה, האירוע "מטפס" במעלה עץ הפקדים, מגיע ל StackPanel ומופעל גם עליו, ואז ממשיך במעלה עץ הפקדים, ומופעל על ה Button, ואז תקרא הפונקציה שרשמנו אותה. באופן זה המקום היחיד שנצטרך להירשם אליו הוא הכפתור עצמו, כלומר הקוד הופך להיות קצר והגיוני:
<phone:PhoneApplicationPage
x:Class="PhoneDemo.MainPage"
>="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
>:x="http://schemas.microsoft.com/winfx/2006/xaml"
>:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
>:d="http://schemas.microsoft.com/expression/blend/2008"
>:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignWidth="480"
d:DesignHeight="800"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
Orientation="Portrait"
SupportedOrientations="Portrait">
<StackPanel>
<Button
Hold="Button_Hold">
<StackPanel
Orientation="Horizontal">
<Image
Source="/PhoneDemo;component/Images/Koala.jpg"
Width="100" />
<TextBlock
Text="text next to image"
VerticalAlignment="Center"
Margin="10" />
</StackPanel>
</Button>
</StackPanel>
</phone:PhoneApplicationPage>
אם נזכור את העובדה שבWPF ו Silverlight קל מאוד לשים פקדים בתוך פקדים, מאחר והתכונה Content יכולה להכיל אוסף פקדים אחרים, נבין שיתרון של Routed Events ביחס לאירועים רגילים הוא ממש הכרחי. מסיבה זו רוב האירועים הם מסוג Routed Events.
סוגים שונים של Routed Events
ב Silverlight לעומת WPF קיים רק סוג אחד של Routed Events.
- אירוע מסוג Bubbling – אירוע מסוג זה מתרחש קודם על הפקד שיצר אותו ואז מטפס במעלה עץ הפקדים ופועל שוב ושוב עד שהוא מגיע לשורש העץ, החלון הראשי. בדוגמא הקודמת האירוע MouseRightButtonDown הוא מסוג Bubbling.
תגובות בפייסבוק