Data Templates - czyli szablon prezentacji danych określa w jaki sposób użytkownik zobaczy dane prezentowane np. w
ListBox-ie.
Do tej pory wykorzystywaliśmy dla
ListBoxa właściwość
DisplayMemberPath. Teraz możemy napisać szablon:
Code:
<ListBox ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}"></TextBlock>
<TextBlock Text=" - "></TextBlock>
<TextBlock Text="{Binding Author}"></TextBlock>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Efekt:
W zależności od tego czy mamy do czynienia z kontrolką typu
Item (np.
ListBox) czy też
Content (
Label) przypisujemy nasz szablon do odpowiedniej właściwości:
- Items control - ItemTemplate
- Content control - ContentTemplate
Większość szablonów definiujemy jako zasoby, które następnie przypisujemy do odpowiedniej kontrolki:
Code:
<Window x:Class="Binding_DataTemplates.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate x:Key="BookTemplate">
<Grid>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}"></TextBlock>
<TextBlock Text=" - "></TextBlock>
<TextBlock Text="{Binding Author}"></TextBlock>
</StackPanel>
</Grid>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding}" ItemTemplate="{StaticResource BookTemplate}">
<!--
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}"></TextBlock>
<TextBlock Text=" - "></TextBlock>
<TextBlock Text="{Binding Author}"></TextBlock>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
-->
</ListBox>
</Grid>
</Window>
Konwertery
Konwertery świetnie nadają się do warunkowego formatowania danych, np. zmiana koloru tekstu w
TextBlock jeżeli cena książki jest wyższa od 10 złotych:
Code:
[ValueConversion(typeof(decimal), typeof(Brush))]
public class PriceForegroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var price = (decimal) value;
if (price > 10)
{
return Brushes.Red;
}
return Brushes.Black;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Code:
<Window.Resources>
<local:PriceForegroundConverter x:Key="ForegroudPriceConverter" />
<DataTemplate x:Key="BookTemplate">
<Grid>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" Foreground="{Binding Price, Converter={StaticResource ForegroudPriceConverter}}"></TextBlock>
<TextBlock Text=" - "></TextBlock>
<TextBlock Text="{Binding Author}"></TextBlock>
</StackPanel>
</Grid>
</DataTemplate>
</Window.Resources>
DataTemplateSelector
Pozwala przypisać szablon wyświetlania danych w zależności od bindowanych danych. Dla przykładu możemy zrealizować poniższy scenariusz:
Jeżeli cena książki jest wyższa od 5 zł, chcemy wyświetlić jej tytuł na czerwono, oraz po autorze dodać informację o cenie - także wyświetloną na czerwono. W tym celu najpierw tworzymy dwa szablony wyświetlania danych:
Code:
<Window.Resources>
<local:PriceForegroundConverter x:Key="ForegroudPriceConverter" />
<local:PriceDataTemplateSelector x:Key="PriceDataTemplateSelector" />
<DataTemplate x:Key="BookTemplate">
<Grid>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" />
<TextBlock Text=" - " />
<TextBlock Text="{Binding Author}" />
</StackPanel>
</Grid>
</DataTemplate>
<DataTemplate x:Key="BookTemplateAlternative">
<Grid>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" Foreground="Red" />
<TextBlock Text=" - " />
<TextBlock Text="{Binding Author}" />
<TextBlock Text=" - "></TextBlock>
<TextBlock Text="{Binding Price}" Foreground="Red" />
</StackPanel>
</Grid>
</DataTemplate>
</Window.Resources>
Następnym krokiem jest implementacja klasy
PriceDataTemplateSelector, która będzie dziedziczyć po klasie
DataTemplateSelector. Klasa
DataTemplateSelector zawiera jedną metodę, która możemy nadpisać -
SelectTemplate. Metoda ta ma na celu zwrócić odpowiedni szablon. Przyjmuje ona dwa parametry:
- item - czyli bindowany obiekt
- container - kontener, do którego jest bindowany obiekt
Przykładowa implementacja:
Code:
public class PriceDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var element = container as FrameworkElement;
var book = item as Book;
if (element != null && item != null && book != null)
{
if (book.Price > 5)
{
return (DataTemplate)element.FindResource("BookTemplateAlternative");
}
else
{
return (DataTemplate)element.FindResource("BookTemplate");
}
}
return null;
}
}
Ostatnim elementem do wykonania jest przypisanie do kontrolki naszego selektora:
Tworzymy zasób związany z selektorem:
Code:
<local:PriceDataTemplateSelector x:Key="PriceDataTemplateSelector" />
oraz przypisujemy go do kontrolki:
Code:
<ListBox ItemsSource="{Binding}" ItemTemplateSelector="{StaticResource PriceDataTemplateSelector}">
Efekt:
Źródła przykładów realizowanych w tym poście (wraz z przykładowymi danymi) - do pobrania z linku:
http://sdrv.ms/12js6rd
Brak komentarzy:
Prześlij komentarz