מדריך WPF – שימוש ב Data Templates
מה זה 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
});
}
}
}
תוצאת הרצת התוכנית הזו הייתה:
כעת נחזור לבעיה המקורית של התצוגה של אלמנט מטיפוס 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, האובייקט מקור יהיה באופן אוטומטי האלמנט שגרם ליצירת הפקדים הנ"ל.
תוצאת הרצת התוכנית באמצעות הקוד הנ"ל נראית כך:
שימוש ב 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>
תגובות בפייסבוק