先示範一般單純指定 ItemTemplate 的情況,這種情況同一個 ListBox 中每個 Item 都是一樣的 View 故變化性低。
DataItem.cs
public class DataItem
{
public Int32 Index;
private Brush icon;
public Brush Icon
{
get
{
return icon;
}
set
{
icon = value;
}
}
private String title;
public String Title
{
get
{
return title;
}
set
{
title = value;
}
}
private String description;
public String Description
{
get
{
return description;
}
set
{
description = value;
}
}
}
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Icon}" Width="40" Height="40"/>
<StackPanel Orientation="Vertical" Margin="10,0,0,0">
<TextBlock Text="{Binding Title}"/>
<TextBlock Text="{Binding Description}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
items = new List<DataItem>();
items.Add(new DataItem { Index = 0,
Icon = new SolidColorBrush(Colors.Red),
Title = "Title A",
Description = "Description A" });
items.Add(new DataItem { Index = 1,
Icon = new SolidColorBrush(Colors.Blue),
Title = "Title B",
Description = "Description B" });
items.Add(new DataItem { Index = 2,
Icon = new SolidColorBrush(Colors.Gray),
Title = "Title C",
Description = "Description C" });
items.Add(new DataItem { Index = 3,
Icon = new SolidColorBrush(Colors.Green),
Title = "Title D",
Description = "Description D" });
items.Add(new DataItem { Index = 4,
Icon = new SolidColorBrush(Colors.Yellow),
Title = "Title E",
Description = "Description E" });
items.Add(new DataItem { Index = 5,
Icon = new SolidColorBrush(Colors.Pink),
Title = "Title F",
Description = "Description F" });
DataContext = this;
}
private List<DataItem> items;
public List<DataItem> Items
{
get
{
return items;
}
set
{
items = value;
}
}
}
這樣子的配置下執行效果如下。
如果我們想要讓單數行的 Icon 向左,偶數行的 Icon 向右,代表我們必須有兩個 ItemTemplate 讓 List Item 被畫在螢幕上之前可以選擇該畫成什麼 View 的樣式,而 DataTemplateSelector 就是用來實作這種不限於一個 Template 的方法,以下示範讓 ListBox 的每個 Item 可以自行選擇 Template 的方式。
首先建立一個繼承 DataTemplateSelector 的類別,並在類別中定義你期望可以使用的數個 DataTemplate Property 並在 SelectTemplate Method 中根據適當的條件回傳需使用的樣版。
MyDataTemplateSelector.cs
public class MyDataTemplateSelector : DataTemplateSelector
{
public DataTemplate OddTemplate
{
get;
set;
}
public DataTemplate EvenTemplate
{
get;
set;
}
public override DataTemplate SelectTemplate(Object item, DependencyObject container)
{
DataTemplate template = EvenTemplate;
DataItem obj = (DataItem)item;
if (obj.Index % 2 > 0)
{
template = OddTemplate;
}
return template;
}
}
接著,可以利用 C# 撰寫 View 的方式,或者在 XAML 中定義 StaticResource 的方式將這些樣版的實際外觀定義出來,我個人習慣寫在需要使用的 Page 同頁的 XAML 檔案中,如果是整個 Application 有許多頁面共同都需要用到的樣版,我習慣寫在 App.xaml 裡面,定義完後,將 ListBox 的 ItemTemplate 拿掉,改成設定 ItemTemplateSelector = {StaticResource MainSelector} 即可
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:MyDataTemplateSelector x:Key="MainSelector">
<local:MyDataTemplateSelector.OddTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Icon}" Width="40" Height="40"/>
<StackPanel Orientation="Vertical" Margin="10,0,0,0">
<TextBlock Text="{Binding Title}"/>
<TextBlock Text="{Binding Description}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</local:MyDataTemplateSelector.OddTemplate>
<local:MyDataTemplateSelector.EvenTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Title}"/>
<TextBlock Text="{Binding Description}"/>
</StackPanel>
<Rectangle Fill="{Binding Icon}" Margin="10,0,0,0" Width="40" Height="40"/>
</StackPanel>
</DataTemplate>
</local:MyDataTemplateSelector.EvenTemplate>
</local:MyDataTemplateSelector>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Items}"
ItemTemplateSelector="{StaticResource MainSelector}"/>
</Grid>
</Window>
如此執行起來即可以讓一個 ListBox 中的各個 Item 使用不同的樣版,效果如下。
沒有留言:
張貼留言