מדריך Windows Phone

מדריך Windows Phone – שימוש ב Data Binding: חיבור ל Collection

‏ • Sela

עד כה ראינו כיצד לחבר בין פקד אחד לפריט מידע אחד. בפרק זה נראה כיצד נוכל לחבר בין פקד שיודע להציג רשימות כמו ListBox לבין רשימה של אובייקטים.

התכונה ItemsSource

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

לדוגמא, נראה חיבור של ListBox לרשימה של אובייקטים.

ראשית נוסיף מחלקה חדשה בשם MyData שתייצג ישות מידע בודדת ברשימה:


namespace PhoneDemo
{
public class MyData
{
public string FirstName { get; set
; }
public string LastName { get; set
; }
public bool IsLecturer { get; set; }
}
}

כעת ניצור פקד שיודע להציג רשימות, ונחבר אותו לרשימה שניצור ב code-behind. בנוסף נוסיף כפתור שתפקידו יהיה להוסיף איבר חדש לרשימה:

<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"
  >:local="clr-namespace:PhoneDemo"
  mc:Ignorable="d"
  d:DesignWidth="480"
  d:DesignHeight="800"
  FontFamily="{StaticResource PhoneFontFamilyNormal}"
  FontSize="{StaticResource PhoneFontSizeNormal}"
  Foreground="{StaticResource PhoneForegroundBrush}"
  Orientation="Portrait"
  SupportedOrientations="Portrait">
  <StackPanel>
    <ListBox
     ItemsSource="{Binding}" />
    <Button
     Content="Add"
     Click="Button_Click" />
  </StackPanel
>
</
phone:PhoneApplicationPage
>

נשים לב לשימוש המיוחד ב Binding ללא פרמטרים. מאחר ואין מקור מפורש (ElementName, Source, RelativeSource) אזי ברירת המחדל תהיה לחפש את מקור הנתונים ב DataContext של האובייקט ListBox. בנוסף לא הוגדר Path לכן במקום להתחבר תכונה מסוימת של אובייקט המקור, החיבור יהיה לכל האובייקט.

ההצבה של אובייקט ל DataContext נעשית בקוד #C באופן הבא:

using System.Collections.Generic;
using System.Windows;
using
Microsoft.Phone.Controls;

namespace
PhoneDemo
{
 
public partial class MainPage : PhoneApplicationPage
  {
   
private List<MyData> _myCollection = new List<MyData
>();

   
// Constructor
    public
MainPage()
    {
      InitializeComponent();

      DataContext = _myCollection;
      _myCollection.Add(
       
new MyData
 
        {
          FirstName =
"Arik"
,
          LastName =
"Poznanski"
,
          IsLecturer =
true
 
        });
      _myCollection.Add(
       
new MyData
 
        {
          FirstName =
"John"
,
          LastName =
"Smith"
,
          IsLecturer =
false
 
        });
    }

   
private int
counter = 0;
   
private void Button_Click(object sender, RoutedEventArgs
e)
    {
      ++counter;
      _myCollection.Add(
       
new MyData
()
        {
          FirstName =
"item "
+ counter,
          LastName =
"item " + counter,
          IsLecturer = counter % 3 == 0
        });
    }
  }
}

הרצה של תוכנית זו תציג את הפלט הבא:

מדריך Windows Phone – שימוש ב Data Binding: חיבור ל Collection

הבעיה הראשונה שעולה מקוד זה היא שהאלמנטים מטיפוס MyData לא מוצגים בצורה טובה. מאחר והמחלקה MyData איננה אלמנט גרפי, מנגנון הציור של Silverlight קורא לפונקציה ToString של האובייקט ומציג את התוצאה בתוך TextBlock. נראה בהמשך המדריך כיצד לשפר משמעותית את ההצגה הגרפית של אובייקטים מטיפוס MyData. בינתיים נסתפר בהעמסה של האופרטור ToString של MyData:

public override string ToString()
{
return string.Format("First name: {0}, Last name: {1}, Is lecturer: {2}",
FirstName, LastName, IsLecturer);
}

כעת התוצאה נראית כך:

מדריך Windows Phone – שימוש ב Data Binding: חיבור ל Collection

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

הבעיה דומה לבעיה שכבר נתקלנו בה בפרק קודם. ה ListBox אינו יודע שה Collection שאליו אנו מחוברים השתנה ולכן אינו יודע ליצור אלמנט חדש עבור האיבר החדש שהצטרך לרשימה. הפתרון לבעיה זו הוא שה Collection שאיתו אנו עובדים יממש ממשק בשם INotifyCollectionChange. שימו לב, זהו לא אותו ממשק כמו שהיה מקודם INotifyPropertyChanged. המטרה פה היא לדווח על שינויים ב Collection ולא בתכונה כזו או אחרת.

שינוי Collection בצורה דינמית

כדי לגרום לכך ששינויים ב Collection שאליו אנו מחוברים יגיעו לפקד הרשימה יש לדאוג שה Collection יממש את הממשק INotifyCollectionChange. למזלנו, לא צריך לממש מחלקות של רשימות משלנו. מיקרוסופט מספקת לנו מימוש כזה בצורת המחלקה הגנרית: ObservableCollection. מחלקה זו מממשת כבר את הממשק הנ"ל ומדווחת על שינויים. כל שנותר לעשות הוא להשתמש במחלקה הזו במקום השימוש שלנו במחלקה הגנרית List.

להלן הקוד המתוקן:

using System.Collections.ObjectModel;
using System.Windows;
using
Microsoft.Phone.Controls;

namespace
PhoneDemo
{
 
public partial class MainPage : PhoneApplicationPage
  {
   
private ObservableCollection<MyData> _myCollection = new ObservableCollection<MyData
>();

   
// Constructor
    public
MainPage()
    {
      InitializeComponent();

      DataContext = _myCollection;
      _myCollection.Add(
       
new MyData
 
        {
          FirstName =
"Arik"
,
          LastName =
"Poznanski"
,
          IsLecturer =
true
 
        });
      _myCollection.Add(
       
new MyData
 
        {
          FirstName =
"John"
,
          LastName =
"Smith"
,
          IsLecturer =
false
 
        });
    }

   
private int
counter = 0;
   
private void Button_Click(object sender, RoutedEventArgs
e)
    {
      ++counter;
      _myCollection.Add(
       
new MyData
()
        {
          FirstName =
"item "
+ counter,
          LastName =
"item " + counter,
          IsLecturer = counter % 3 == 0
        });
    }
  }
}

כעת לחיצה על כפתור Add עובדת והתוצאה לאחר מספר לחיצות היא:

מדריך Windows Phone – שימוש ב Data Binding: חיבור ל Collection

תגיות: , , , ,

arikp

אריק פוזננסקי הוא יועץ בכיר ומרצה בסלע. הוא השלים שני תארי B.Sc. במתמטיקה ומדעי המחשב בהצטיינות יתרה בטכניון. לאריק ידע נרחב בטכנולוגיות מיקרוסופט, כולל .NET עם C#, WPF, Silverlight, WinForms, Interop, COM/ATL, C++ Win32 ו reverse engineering.

תגובות בפייסבוק