先示範一般單純指定 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 使用不同的樣版,效果如下。


 
沒有留言:
張貼留言