WPF桌面端开发2-ItemsControl、ListBox和ListView的用法

前言

ItemsControl和ListBox都可以用做列表,既然是列表,那么我们怎样获取列表点击的项呢。

ItemsControl、ListBox和ListView

结构的复杂程度从低到高依次为:

ItemsControl=>ListBox=>ListView

ListBox继承于ItemsControl,ListView继承于ListBox,所以后面的组件拥有前面组件的一切特性。

相同点:

  1. 这三个控件都是列表型控件,可以进行列表绑定(ItemsSource);
  2. 这三个控件均使用ItemsPresenter来展示列表信息;

不同点:

  1. ItemsControl是不包含水平和垂直方向的滚动条的。ListBox和ListView有水平和垂直方向滚动条。

  2. ListBox 继承于ItemsControl,增加了一个Selector对象,支持单选,ItemsControl中的Item是不支持选择的。

    而ListBox中Item是支持选择,并且可以单选,多选。

  3. ListView类似 Gridview ,支持多列。

    ListBox很简单, 就一列。

ListBox点击列表项后就不能再触发点击事件,而ItemsControl压根就没有选中项,那么怎样处理呢?

自定义ListBox

实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ZNotifyModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}

列表的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class ZListItemModel : ZNotifyModel
{
public int index { get; set; }
public string tag { get; set; }
private int _selected;

public string name { get; set; }

public int selected
{
get => _selected;
set
{
_selected = value;
OnPropertyChanged("selected");
}
}
}

页面的PageData对象

1
2
3
4
5
6
7
8
9
public class UserCenterPageData : ZNotifyModel
{
public UserCenterPageData()
{
typeList = new ObservableCollection<ZListItemModel>();
}

public ObservableCollection<ZListItemModel> typeList { get; set; }
}

页面中调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
internal UserCenterPageData pageData = new UserCenterPageData();
pageData.typeList.Add(
new ZListItemModel()
{
name = "全部",
tag = "0",
selected = 1
}
);
pageData.typeList.Add(
new ZListItemModel()
{
name = "Word",
tag = "1",
selected = 0
}
);
pageData.typeList.Add(
new ZListItemModel()
{
name = "PPT",
tag = "2",
selected = 0
}
);
DataContext = pageData;

全局样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="ListBoxItemContainerStyle1" TargetType="ListBoxItem">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border
Name="Border"
Padding="0,0,0,0"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="True">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Border" Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="Black" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="LightGray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

<ControlTemplate x:Key="ListBoxTemplate" TargetType="{x:Type ListBox}">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<WrapPanel
IsItemsHost="True"
Orientation="Horizontal"
ScrollViewer.CanContentScroll="True" />
</ScrollViewer>
</ControlTemplate>

<ControlTemplate x:Key="ListBoxTemplateH" TargetType="{x:Type ListBox}">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<StackPanel
IsItemsHost="True"
Orientation="Horizontal"
ScrollViewer.CanContentScroll="True" />
</ScrollViewer>
</ControlTemplate>
</ResourceDictionary>

样式转换器

背景颜色转换器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ColorBgConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
int v = int.Parse(value.ToString());
if (v == 0)
{
return "#ffffff";
}
else
{
return "#4597FF";
}
}

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}

文字颜色转换器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class ColorTextConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
int v = int.Parse(value.ToString());
if (v == -1)
{
return "#666666";
}
else if (v == 0)
{
return "#000000";
}
else
{
return "#ffffff";
}
}

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}

页面

列表项(建议写在页面中,除非是通用的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<Window.Resources>
<cv:ColorBgConverter x:Key="colorBgConvert" />
<cv:ColorTextConverter x:Key="colorTextConvert" />
<DataTemplate x:Key="typeItemDT">
<Border
Height="36"
Margin="0,0,10,0"
Background="{Binding selected, Converter={StaticResource colorBgConvert}}"
CornerRadius="4"
Cursor="Hand">
<Grid>
<TextBlock
Padding="8"
VerticalAlignment="Center"
FontSize="14"
Foreground="{Binding selected, Converter={StaticResource colorTextConvert}}"
Text="{Binding name}" />
</Grid>
</Border>
</DataTemplate>
</Window.Resources>

ListBox

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<Grid Background="#f3f3f3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
Margin="10,0,0,0"
VerticalAlignment="Center"
FontSize="16"
Text="类型:" />

<ListBox
x:Name="type_list_lb"
Grid.Column="1"
Background="#f3f3f3"
BorderThickness="0"
ItemContainerStyle="{StaticResource ListBoxItemContainerStyle1}"
ItemTemplate="{StaticResource typeItemDT}"
ItemsSource="{Binding typeList}"
Template="{StaticResource ListBoxTemplateH}"
SelectionChanged="type_list_lb_SelectionChanged"/>
</Grid>

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private async void type_list_lb_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (!(sender is ListBox listBox))
{
return;
}
if (listBox.SelectedItem is ZListItemModel item)
{
ObservableCollection<ZListItemModel> typeList = pageData.typeList;
for (int i = 0; i < typeList.Count; i++)
{
ZListItemModel item_temp = typeList[i];
if (item_temp == item)
{
item_temp.selected = 1;
}
else
{
item_temp.selected = 0;
}
}
}
}

如果想让选中的项能够再次点击

设置选中索引即可

1
type_list_lb.SelectedIndex = -1;

获取点击项

使用SelectionChanged回调(推荐)

重置选中索引

1
2
3
4
5
6
7
8
9
10
11
12
<ListBox
Grid.Row="2"
Margin="10,0,10,0"
Background="#f3f3f3"
BorderThickness="0"
ItemContainerStyle="{StaticResource StyleUserListBoxItem}"
ItemTemplate="{StaticResource UserAnsTpl}"
ItemsSource="{Binding userList}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
SelectionChanged="UserAnsSelectionChanged"
Template="{StaticResource ListBoxTemplate}" />

代码中

1
2
3
4
5
6
7
8
9
10
11
12
private void UserAnsSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (!(sender is ListBox listBox))
{
return;
}
if (listBox.SelectedItem is TiwenTongjiJiandaItem item)
{

}
listBox.SelectedIndex = -1;
}

自定义ListBox

ListBox点击会选中,但是选中的项目不能再次点击,所以这里

自定义ListBox,当item选中后再重置为未选中

自定义ListBox

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Z.Views
{
public class ZListBox : ListBox
{
protected override DependencyObject GetContainerForItemOverride()
{
return new ZListBoxItem();
}
}

public class ZListBoxItem : ListBoxItem
{
protected override void OnSelected(System.Windows.RoutedEventArgs e)
{
DependencyObject dep = (DependencyObject)e.OriginalSource;
while ((dep != null) && !(dep is ListBoxItem))
{
dep = VisualTreeHelper.GetParent(dep);
}

if (dep == null) { return; }

ListBoxItem item = (ListBoxItem)dep;
if (item.IsSelected)
{
item.IsSelected = !item.IsSelected;
}
base.OnSelected(e);
}
}
}

使用

1
2
3
4
5
6
7
8
9
<views:ZListBox 
ItemsSource="{Binding menuList}"
ItemTemplate="{StaticResource ToolbarMenu}"
SelectionChanged="UserAnsSelectionChanged"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Background="#f3f3f3"
BorderThickness="0">
</views:ZListBox>

对应的

1
2
3
4
5
6
7
8
9
10
11
private void UserAnsSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (!(sender is ListBox listBox))
{
return;
}
if (listBox.SelectedItem is TiwenTongjiJiandaItem item)
{

}
}

也可以简写为

1
2
3
4
5
6
7
8
private void UserAnsSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (!(sender is ListBox { SelectedItem : TiwenTongjiJiandaItem item }))
{
return;
}
//处理逻辑
}

使用Tag传值(推荐)

还有一种方式是绑定Tag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<DataTemplate x:Key="LeftMenu">
<Button
x:Name="toolbar_item"
Height="60"
Margin="6,25,0,0"
Background="Transparent"
BorderThickness="0"
Click="leftbar_item_Click"
Cursor="Hand"
Tag="{Binding}">
<Button.Content>
<Grid>
<TextBlock
Margin="64,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="18"
Foreground="White"
Text="{Binding Name}" />
</Grid>
</Button.Content>
</Button>
</DataTemplate>

代码中

1
2
3
4
5
6
7
8
9
private void leftbar_item_Click(object sender, RoutedEventArgs e)
{
if (!(sender is Button { Tag: TiwenTongjiSelectItem tongjiItem }))
{
return;
}
QuesSelectDetail win = new QuesSelectDetail($"选择{tongjiItem.OptionName}的学生", tongjiItem.UserNameList);
win.ShowDialog();
}

注意:

这种方式获取到的是对应的值,可以通过值获取在列表中的索引。

ItemsControl、ListBox和ListView均支持该方式。

ItemsControl选中项索引(不推荐)

你可以在ItemsControlMouseLeftButtonDown事件中获取点击的索引。

以下是一个示例:

XAML:

1
2
3
4
5
6
7
<ItemsControl ItemsSource="{Binding Items}" MouseLeftButtonDown="ItemsControl_MouseLeftButtonDown">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

代码:

1
2
3
4
5
6
7
8
9
private void ItemsControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// 获取点击的ItemsControl项
var clickedItem = ((FrameworkElement)e.OriginalSource).DataContext;

// 获取点击项的索引
int clickedIndex = ((ItemsControl)sender).Items.IndexOf(clickedItem);
Console.WriteLine($@"选中的项索引{clickedIndex}");
}

在这个示例中,MouseLeftButtonDown事件会在用户点击ItemsControl中的任何一个项时触发。通过获取事件参数中的OriginalSource属性,可以确定实际点击的元素。

在这个示例中,我们将OriginalSource强制转换为FrameworkElement,以便我们可以访问其DataContext(即ItemsControl中的项)。

一旦我们得到了点击的项,我们可以使用IndexOf方法获取其索引。

这种方式要注意:

选中项的模版中不能是Button,这样点击事件就被消费掉了。

查找控件方式(不推荐)

Item中添加Button,对Button添加事件,获取Button所在Item的Index

工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;

namespace ZJClassTool.Utils
{
class VTHelper
{
public static T FindChild<T>(DependencyObject parent, string childName)
where T : DependencyObject
{
if (parent == null) return null;

T foundChild = null;

int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
// 如果子控件不是需查找的控件类型
T childType = child as T;
if (childType == null)
{
// 在下一级控件中递归查找
foundChild = FindChild<T>(child, childName);

// 找到控件就可以中断递归操作
if (foundChild != null) break;
}
else if (!string.IsNullOrEmpty(childName))
{
var frameworkElement = child as FrameworkElement;
// 如果控件名称符合参数条件
if (frameworkElement != null && frameworkElement.Name == childName)
{
foundChild = (T)child;
break;
}
}
else
{
// 查找到了控件
foundChild = (T)child;
break;
}
}

return foundChild;
}

public static List<T> FindChilds<T>(DependencyObject parent, string childName)
where T : DependencyObject
{
var list = new List<T>();
if (parent == null) return list;

int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
// 如果子控件不是需查找的控件类型
T childType = child as T;
if (childType == null)
{
// 在下一级控件中递归查找
var findChildList = FindChilds<T>(child, childName);
for (int j = 0; j < findChildList.Count; j++)
{

}
list.AddRange(FindChilds<T>(child, childName));

}
else if (!string.IsNullOrEmpty(childName))
{
var frameworkElement = child as FrameworkElement;
// 如果控件名称符合参数条件
if (frameworkElement != null && frameworkElement.Name == childName)
{
list.Add((T)child);
}
}
else
{
// 查找到了控件
list.Add((T)child);
}
}

return list;
}

/// <summary>
/// 查找父元素
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <param name="name"></param>
/// <returns></returns>
public static T FindParent<T>(DependencyObject i_dp) where T : DependencyObject
{
DependencyObject dobj = VisualTreeHelper.GetParent(i_dp);
if (dobj != null)
{
if (dobj is T)
{
return (T)dobj;
}
else
{
dobj = FindParent<T>(dobj);
if (dobj != null && dobj is T)
{
return (T)dobj;
}
}
}
return null;
}
}
}

xaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<Window.Resources>
<DataTemplate x:Key="ToolbarMenu">
<Button x:Name="toolbar_item" Background="Transparent" BorderThickness="0" Cursor="Hand" Height="60" Click="toolbar_item_Click">
<Button.Content>
<StackPanel Width="Auto" Background="Transparent">
<Image HorizontalAlignment="Center" Width="44" Source="{Binding Pic}"/>
<TextBlock HorizontalAlignment="Center" Text="{Binding Name}" Foreground="#3C525B"/>
</StackPanel>
</Button.Content>
</Button>
</DataTemplate>
</Window.Resources>
<ItemsControl
x:Name="toolbar_list"
ItemsSource="{Binding menuList}"
ItemTemplate="{StaticResource ToolbarMenu}"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Grid.Row="1" Background="#f3f3f3" BorderThickness="0">
</ItemsControl>

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
private void toolbar_item_Click(object sender, RoutedEventArgs e)
{
var clickindex = 0;
var buttons = VTHelper.FindChilds<Button>(toolbar_list, "toolbar_item");
for (var i = 0; i < buttons.Count; i++)
{
if (buttons[i] == sender)
{
clickindex = i;
break;
}
}
}

ListBox配置项

1
2
3
4
5
6
7
8
9
<ListBox
Background="#f3f3f3"
BorderThickness="0"
ItemsSource="{Binding menuList}"
ItemContainerStyle="{StaticResource ListBoxItemContainerStyle1}"
ItemTemplate="{StaticResource recordDT}"
Template="{StaticResource ListBoxTemplate}"
ScrollViewer.VerticalScrollBarVisibility="Visible"
/>

其中

  • ItemsSource是数据源

  • 跟每个Item有关的是ItemContainerStyleItemTemplate

    • ItemContainerStyle:每一项的外部样式 比如设置选中的状态的边框

    • ItemTemplate:每一项的内部模板

  • Template是所有项的外部容器

项容器

ItemContainerStyle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<Style x:Key="ListBoxItemContainerStyle1" TargetType="ListBoxItem">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border
Name="Border"
Padding="0,0,0,0"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="True">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Border" Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="Black" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="LightGray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

项模板

ItemTemplate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<DataTemplate x:Key="recordDT">
<Grid
Width="260"
Height="180"
Margin="0,0,0,10">
<Grid Margin="10" Background="Aquamarine">

<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Image />

<Grid Grid.Row="1" Height="30">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" />
</Grid>

<Grid Grid.Row="2" Height="30">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" />
</Grid>
</Grid>
</Grid>
</DataTemplate>

列表外部容器

Template是所有项的外部容器

比如能换行的

1
2
3
4
5
6
7
8
<ControlTemplate x:Key="ListBoxTemplate" TargetType="{x:Type ListBox}">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<WrapPanel
IsItemsHost="True"
Orientation="Horizontal"
ScrollViewer.CanContentScroll="True" />
</ScrollViewer>
</ControlTemplate>

不能换行的

1
2
3
4
5
6
7
8
<ControlTemplate x:Key="ListBoxTemplateH" TargetType="{x:Type ListBox}">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<StackPanel
IsItemsHost="True"
Orientation="Horizontal"
ScrollViewer.CanContentScroll="True" />
</ScrollViewer>
</ControlTemplate>

注意

作为外部容器要添加IsItemsHost="True"属性。

柱状图示例

其中ZGenericTypeConverter参见 https://www.psvmc.cn/article/2019-12-30-wpf-start-03-mvvm.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<ListBox
Grid.Row="1"
Margin="20,20,20,0"
ItemsSource="{Binding TiwenItemList}"
ScrollViewer.CanContentScroll="False">
<ListBox.Template>
<ControlTemplate TargetType="{x:Type ListBox}">
<UniformGrid IsItemsHost="True" Rows="1" />
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Border
Grid.Row="0"
Width="70"
HorizontalAlignment="Center"
Background="#F8F8F8"
CornerRadius="4 4 0 0"
RenderTransformOrigin="0.5,1" />
<StackPanel Grid.Row="0" VerticalAlignment="Bottom">
<TextBlock
Height="30"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="18"
Foreground="#666666"
Text="{Binding OptionNum}" />
<Border
Width="70"
Height="{Binding OptionHeight}"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
Background="{Binding Path=OptionType, Converter={StaticResource ZGenericTypeConverter}, ConverterParameter='1:#3CB371|2:#DC143C|3:#A9A9A9|other:#EEEEEE'}"
CornerRadius="4 4 0 0"
RenderTransformOrigin="0.5,1" />

</StackPanel>

<Rectangle
Grid.Row="1"
Height="1"
VerticalAlignment="Top"
Stroke="#f0f0f0" />
<TextBlock
Grid.Row="1"
Margin="0,10,0,0"
HorizontalAlignment="Center"
FontSize="18"
FontWeight="Bold"
Foreground="#333333"
Text="{Binding OptionName}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>