בפוסט הקודם ראינו איך אפשר להוסיף TriggerActions (או פשוט Actions, פעולות) ע”י בלנד. בפוסט הנוכחי נראה איך אפשר לכתוב Actions מאפס בעצמנו.
כמובן על מנת להתחיל נרשום את מרחב השמות של Behaviors (שימו לב כי Behaviors הוא שם כללי לשני הסוגים, גם ל Behaviors וגם ל Actions):
בשביל להוסיף Action, נשים על החלון מלבן, ונכין את הקרקע להוספת Action:
<Grid>
<Rectangle Fill="#FFF4F4F5" Margin="119,87,166,103" Stroke="Black">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseUp">
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
</Grid>
במקום i:Interacgtion.Behaviors רשמנו i:Interaction.Triggers כששם אפשר להוסיף את ה Actions שלנו.
כל Action מכיל פעולה בלבד, ללא ה”מתי”. במקרה שלנו הוספנו EventTrigger שמקשיב לאירוע MouseUp. באותה מידה היינו יכולים להרשם לכל אירוע אחר של המלבן.
עד כאן הכנת השטח – נעבור ליצירת ה Action שלנו בקוד. בשביל ליצור Action צריך לרשת מ TriggerAction<T> :
public class ChangeColorTriggerAction : TriggerAction<Rectangle>
{}
ה Action שאנו הולכים ליצור הולך “לשבת” על מלבן, ולפיכך ירשנו מ TriggerAction של Rectangle. ה Action ישנה את הצבע של המלבן (כש*מתי* זה קורה יקבע ע”י הEventTrigger שלעיל).
בשביל לממש TriggerAction כל מה שצריך זה לממש מתודה אחת – Invoke:
public class ChangeColorTriggerAction : TriggerAction<Rectangle>
{ protected override void Invoke(object parameter)
{ throw new NotImplementedException();
}
}
לצורך הדוגמא, נרשום בתוך invoke את הקוד הבא, שפשוט משנה את צבע המילוי של ה Rectangle לאדום.
public class ChangeColorTriggerAction : TriggerAction<Rectangle>
{ protected override void Invoke(object parameter)
{ this.AssociatedObject.Fill = Brushes.Red;
}
}
כעת נוכל להשתמש ב Action שלנו:
<Grid>
<Rectangle Fill="#FFF4F4F5" Margin="119,87,166,103" Stroke="Black">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseUp">
<my:ChangeColorTriggerAction />
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
</Grid>
וכך תראה התוכנה בזמן ריצה לאחר שלחצנו על המלבן:

עבודה עם בלנד
במידה ונעבור לבלנד, נראה כי הAction שיצרנו נמצא שם. בלנד יודע אוטומאטית לסרוק את כל הפרוייקטים/ DLLים באפליקציה להוציא מהם את ה Behaviors וה Actions. (מאוד שימושי כשעובדים עם מעצבים גראפים) :

את הAction הזה נוכל לגרור למשטח העבודה, כשבלנד מספיק חכם לאפשר גרירה אך ורק לאלמנטים מתאימים – במקרה שלנו אך ורק לRectangleים היות וכך הגדרנו את הAction. אם נוסיף עוד כמה אלנטים, נוכל לראות של מלבנים אפשר לגרור (כפי שמציין הריבוע הכחול מסביב):

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

התמיכה של בלנד ב Actions היא מלאה לחלוטין, וזה עוד אחת מהסיבות שזה פיצ’ר כזה חזק. אם נסתכל בעץ האלמנטים נראה שה Actions אכן נמצאים שם.

ואם נבחר אחד מהם נראה שאפשר לשנות פרמטרים בחלון המאפיינים. :

נחזור לויז’ואל סטודיו ונראה את הקוד שבלנד הוסיף – בדיוק הקוד שאנו היינו צריכים להוסיף על מנת להשתמש ב Action:
<Grid>
<Rectangle Fill="#FFF4F4F5" Margin="119,87,166,103" Stroke="Black">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseUp">
<my:ChangeColorTriggerAction />
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
<Rectangle Fill="#FFF4F4F5" HorizontalAlignment="Right" Height="88" Margin="0,39,55,0" Stroke="Black" VerticalAlignment="Top" Width="165">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<my:ChangeColorTriggerAction/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
<Ellipse Fill="#FFF4F4F5" HorizontalAlignment="Right" Height="106" Margin="0,0,45,30" Stroke="Black" VerticalAlignment="Bottom" Width="175"/>
</Grid>
עקרונית, אפשר כבר להבין בשלב הזה שאין סיבה אמיתית שב Action שלנו נוכל להשתמש רק על Rectangleים – אנו נרצה שנוכל להשתמש בהם איפה שרק אפשר. איפה שרק אפשר במקרה שלנו == על כל אלמנט שיש לו מאפיין בשם Fill – או במילים אחרות, על כל מי שיורש מהמחלקה Shape (וכך נוכל לשים אותו גם על האליפסה).
נשנה את ה Action כך שיתאים לכל Shape:
public class ChangeColorTriggerAction : TriggerAction<Shape>
{ protected override void Invoke(object parameter)
{ this.AssociatedObject.Fill = Brushes.Red;
}
}
ועכשיו נוכל לשים אותו גם על האליפסה:
<Ellipse Fill="#FFF4F4F5" HorizontalAlignment="Right" Height="106" Margin="0,0,45,30" Stroke="Black" VerticalAlignment="Bottom" Width="175">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<my:ChangeColorTriggerAction/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Ellipse>

הוספת DependencyProperties ל Action
אין שום סיבה שנשתמש תמיד בצבע אדום – ולכן נשנה את הקוד שלנו כך שיהיה יותר גנרי.
עקרונית, כל מה שאנו צריכים לעשות זה להוסיף מאפיין (פרופרטי) ל Action שלנו מסוג Brush על מנת שנוכל לקבוע מ”בחוץ” את הצבע אליו צריך לשנות. הפרופרטי הזה יכול להיות פרופרטי רגיל, אבל בשביל שהוא יוכל לתמוך ב DataBinding בהמשך, עדיף בהרבה שהוא יהיה פרופרטי מסוג DependencyProperty.
נוסיף DependencyProperty מסוג Brush, ונשנה אליו כאשר ה Action מופעל:
public class ChangeColorTriggerAction : TriggerAction<Shape>
{ public Brush Color
{ get { return (Brush)GetValue(ColorProperty); } set { SetValue(ColorProperty, value); } }
// Using a DependencyProperty as the backing store for Color. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ColorProperty =
DependencyProperty.Register("Color", typeof(Brush), typeof(ChangeColorTriggerAction), new UIPropertyMetadata(Brushes.Black));
protected override void Invoke(object parameter)
{ this.AssociatedObject.Fill = Color;
}
}
מה שיאפשר לנו לרשום את הקוד הבא, והלהשתמש כל פעם בצבע אחר:
<Grid>
<Rectangle Fill="#FFF4F4F5" Margin="119,87,166,103" Stroke="Black">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseUp">
<my:ChangeColorTriggerAction Color="Blue" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
<Rectangle Fill="#FFF4F4F5" HorizontalAlignment="Right" Height="88" Margin="0,39,55,0" Stroke="Black" VerticalAlignment="Top" Width="165">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<my:ChangeColorTriggerAction Color="Green"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
<Ellipse Fill="#FFF4F4F5" HorizontalAlignment="Right" Height="106" Margin="0,0,45,30" Stroke="Black" VerticalAlignment="Bottom" Width="175">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<my:ChangeColorTriggerAction Color="Yellow"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Ellipse>
</Grid>
וזו התוצאה הסופית שנקבל

בפוסט הבא נכתוב את ה Action הראשון הבאמת שימושי – Action שאי אפשר לעבוד בלעדיו כשעובדים ב MVVM.