Behaviors חלק 7 – איך מממשים Drag and Drop ב WPF ע"י Code Behind

14 באוגוסט 2012

תגיות: , , ,
אין תגובות

בפוסט הקודם ראינו איך פותרים את בעיית ה Commands ב MVVM ע”י שימוש ב Behaviors. בפוסטים הבאים נתחיל לחקור הרבה בעיות ש Behaviors מפשטים, כשנתחיל עם Drag and Drop.

אחת הפעולות הסטנדרטיות שמממשים לעיתים קרובות היא Drag and Drop. לממש Drag and Drop ב WPF יחסית קל היות ויש תמיכה טובה מאוד של התשתית עבור זה, אבל יחד עם זאת הפתרון הבסיסי עדיין רחוק מלהיות אלגנטי.

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

image

פעולת ה Drag and Drop תתחיל כשנמקם את סמן העכבר מעל למלבן, נלחץ על הכפתור השמאלי ונתחיל לגרור. בשביל זה צריך להרשם לאירוע MouseLeftButtonDown על המלבן:

 

   1: <Window x:Class="DragDropBehaviorsDemo.NoMvvmWindow"

   2:         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   3:         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   4:         Title="NoMvvmWindow" Height="313" Width="542">

   5:     <Grid>

   6:         <Button Content="Button" Height="73" HorizontalAlignment="Left"

   7:                 Margin="31,37,0,0" Name="button1" VerticalAlignment="Top" Width="125" />

   8:         

   9:         <Rectangle Height="159" HorizontalAlignment="Left" Margin="194,88,0,0" MouseLeftButtonDown="rectangle1_MouseLeftButtonDown"

  10:                    Name="rectangle1" Stroke="Black" VerticalAlignment="Top" Width="287" Fill="#FF004CFF" />

  11:         

  12:     </Grid>

  13: </Window>

בשביל לאתחל פעולת Drag and Drop נשתמש במתודה הסטאטית DoDragDrop של במחלקת העזר DragDrop. המתודה מקבלת שלושה פרמטרים – הפרמטר הראשון הוא קונטרול המקור שפעולת הגרירה התחילה ממנו, והפרמטר השני הוא המידע אותו אנחנו רוצים להעביר לקונטרול המטרה (שבמקרה שלנו יהיה הכפתור).
הפרמטר השלישי קובע את האפקט שנראה על סמן העכבר בשעת הגרירה (אפקט העברה, אפקט העתקה וכו’) בדוגמה שלהלן אנו קובעים את המקור להיות המלבן, את המידע להיות המחרוזת “SomeData”, ואת האפקט להיות אפקט העברה (Move): image

   1: private void rectangle1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)

   2: {

   3:     DataObject data = new DataObject("SomeData");

   4:  

   5:     var effects = DragDrop.DoDragDrop(sender as DependencyObject, data, DragDropEffects.Move);

   6: }

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

image

בשביל שנוכל להגיב לפעולת הגרירה, צריך לקבוע את הערך AllowDrop להיות true על כל אלמנט שעליו ניתן “להפיל” את הגרירה. במקרה שלנו זה יהיה הכפתור.
בנוסף, בשביל לטפל באירוע ה”הפלה” צריך להרשם לאירוע DragDrop.Drop:

 

   1: <Button AllowDrop="True" DragDrop.Drop="button1_Drop" Content="Button" Height="73" HorizontalAlignment="Left"

   2:         Margin="31,37,0,0" Name="button1" VerticalAlignment="Top" Width="125" />

 

האירוע חושף לנו DragEventArgs שממנו אפשר להוציא את השולח ואת המידע שהוא שלח:

   1: private void button1_Drop(object sender, DragEventArgs e)

   2: {

   3:     var data = e.Data.GetData(typeof(string)).ToString();

   4:  

   5:     MessageBox.Show(data);

   6: }

image

image_thumb[2]

וזה כל מה שצריך לעשות על מנת לממש Drag and Drop בצורה נאיבית.

ישנן שתי בעיות בשיטה הנ”ל:
1. Reuse של קוד – במידה ורוצים לממש Drag and Drop בעוד קונטרולים/חלונות, צריך להרשם לכל האירועים הרלוונטים ולכתוב את הקוד הזה פעם נוספת. רחוק מלהיות אלגנטי.

2. איך מממשים את זה ב MVVM? המחלקה DragDrop היא מחלקת UI – זו מחלקה שאסור לגשת אליה מה ViewModel. גם אם היינו ניגשים אליה מהViewModel – זו לא פעולה שה ViewModel אמור בכלל לדעת עליה היות וזו אחריות של ה View בלבד.

בפוסט הבא נראה איך ע”י שימוש ב


Behaviors אפשר להגיע לפתרון הרבה יותר אלגנטי וריוזאבילי (reuseable), שמאוד נוח לשימוש ב MVVM.

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *