מדריך WPF

מדריך WPF – שימוש ב Data Templates

‏ • Sela

מה זה Data Templates?

Data Template הוא מנגנון המאפשר ליצור בזמן ריצה רכיבי UI מתוך Data. לדוגמא, בפרק הקודם ראינו כיצד ניתן לחבר פקד ListBox ל Collection של איברים מטיפוס MyData. נחזור על הקוד של הדוגמא:

המחלקה MyData הוגדרה באופן הבא:

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

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

קוד הXAML הוגדר להיות:

<Window x:Class="CollectionDemo.MainWindow"
       >="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       >:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="MainWindow"
       Height="350"
       Width="525">
  <StackPanel>
    <ListBox ItemsSource="{Binding}" />
    <Button Content="Add"
           Click="Button_Click" />
  </StackPanel
>
</
Window
>

הקוד מאחור ב#C:

using System.Collections.ObjectModel;
using
System.Windows;

namespace
CollectionDemo
{
 
/// <summary>
  /// Interaction logic for MainWindow.xaml
  /// </summary>
  public partial class MainWindow : Window
  {
   
private ObservableCollection<MyData
> _myCollection =
     
new ObservableCollection<MyData
>();

   
public
MainWindow()
    {
      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
          });
    }
  }
}

 

תוצאת הרצת התוכנית הזו הייתה:

מדריך WPF – שימוש ב Data Templates

 

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

Data Template זוהי טכניקה המאפשרת לנו להגדיר כיצד אובייקט נתונים (לדוגמא, מטיפוס MyData) יראה בצורה גרפית.

כיצד נגדיר Data Template?

כדי להגדיר כיצד יש להציג אלמנטים מטיפוס MyData יש צורך להגדיר Data Template עבורו. להלן דוגמא:

<Window x:Class="DataTemplates.MainWindow"
       >="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       >:x="http://schemas.microsoft.com/winfx/2006/xaml"
       >:local="clr-namespace:DataTemplates"
       Title="MainWindow"
       Height="350"
       Width="525">
  <Window.Resources>
    <DataTemplate x:Key="MyDataTemplate"
                 DataType="local:MyData">
      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="*" />
          <ColumnDefinition Width="*" />
          <ColumnDefinition Width="*" />
          <ColumnDefinition Width="*" />
          <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <TextBlock Grid.Column="0"
                  Text="First Name: " />
        <TextBlock Grid.Column="1"
                  Text="{Binding Path=FirstName}" />
        <TextBlock Grid.Column="2"
                  Text="Last Name: " />
        <TextBlock Grid.Column="3"
                  Text="{Binding Path=LastName}" />
        <CheckBox Grid.Column="4"
                 Content="Is Lecturer?"
                 IsEnabled="False"
                 IsChecked="{Binding Path=IsLecturer}" />
      </Grid>
    </DataTemplate>
  </Window.Resources>
  <StackPanel>
    <ListBox ItemsSource="{Binding}"
            ItemTemplate="{StaticResource MyDataTemplate}"
            HorizontalContentAlignment="Stretch" />
    <Button Content="Add"
           Click="Button_Click" />
  </StackPanel
>
</
Window
>

בדוגמא זו אנו מגדירים שכל אלמנט מסוג MyData יוצג ע"י Grid שבתוכו מספר פקדים (מסוג TextBlock ו CheckBox) שיציגו בצורה גרפית את התכונות החשובות של האלמנט.

בנוסף נשים לב לשימוש בתכונה ItemTemplate בפקד ListBox. תכונה זו מציינת באיזה Data Template יש להשתמש בשביל לצייר את האלמנטים ברשימה. בזמן ריצה עבור כל אלמנט שברשימה ייוצר עותק מהתוכן הגרפי של ה Data Template לצורך הצגת האלמנט. בנוסף, האלמנט עצמו (מסוג MyData) יקבע באופן אוטומטי להיות ה DataContext של הפקדים הגרפיים שב Data Template. באופן זה כאשר משתמשים ב Binding בהגדרת ה Data Template, האובייקט מקור יהיה באופן אוטומטי האלמנט שגרם ליצירת הפקדים הנ"ל.

תוצאת הרצת התוכנית באמצעות הקוד הנ"ל נראית כך:

מדריך WPF – שימוש ב Data Templates

 

שימוש ב Implicit Data Templates

בדוגמא הקודמת הראינו כיצד להגדיר Data Template עבור אובייקט מטיפוס MyData ולתת לו מפתח מזהה, ואז להשתמש במפתח כדי להגדיר את סוג האובייקט בעזרת ItemTemplate.

ישנה אפשרות נוספת לעשות זאת, והיא באמצעות שימוש ב Implicit Data Templates.

ב Implicit Data Templates הכוונה היא יצירת Data Template ללא מפתח מפורש (כלומר, ללא הגדרת x:Key), במקרה כזה ה Data Template יופעל בכל פעם שנרצה להציג למסך אובייקט מטיפוס MyData, גם ללא שימוש בתכונה ItemTemplate.

להלן הקוד של הדוגמא הקודמת תוך שימוש ב Implicit Data Template:

<Window x:Class="DataTemplates.MainWindow"
       >="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       >:x="http://schemas.microsoft.com/winfx/2006/xaml"
       >:local="clr-namespace:DataTemplates"
       Title="MainWindow"
       Height="350"
       Width="525">
  <Window.Resources>
    <DataTemplate DataType="local:MyData">
      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="*" />
          <ColumnDefinition Width="*" />
          <ColumnDefinition Width="*" />
          <ColumnDefinition Width="*" />
          <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <TextBlock Grid.Column="0"
                  Text="First Name: " />
        <TextBlock Grid.Column="1"
                  Text="{Binding Path=FirstName}" />
        <TextBlock Grid.Column="2"
                  Text="Last Name: " />
        <TextBlock Grid.Column="3"
                  Text="{Binding Path=LastName}" />
        <CheckBox Grid.Column="4"
                 Content="Is Lecturer?"
                 IsEnabled="False"
                 IsChecked="{Binding Path=IsLecturer}" />
      </Grid>
    </DataTemplate>
  </Window.Resources>
  <StackPanel>
    <ListBox ItemsSource="{Binding}"
            HorizontalContentAlignment="Stretch" />
    <Button Content="Add"
           Click="Button_Click" />
  </StackPanel
>
</
Window
>

תגיות: , , , ,

arikp

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

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