高亮 WPF ListView 中的项目






4.87/5 (36投票s)
逐步回顾如何有条件地高亮 ListViewItems。

引言
本文介绍如何根据项的值或与项相关的值来更改 ListView
中项的颜色。这里使用的技术是将 ListView
绑定到一个 ADO.NET DataTable
,并利用自定义值转换器来确定每个 ListViewItem
应为何种颜色。
背景
这是一个常见场景:您有一个 DataTable
需要显示在 ListView
中,并且包含某个范围内(例如,小于零)值的任何行都应以特殊颜色“高亮显示”。也许决定 ListViewItem
颜色的值甚至没有在 ListView
中显示,而仅存在于 DataRow
中。如何在 WPF 中实现此功能?
此任务涉及四个步骤
- 填充
DataTable
并将其绑定到ListView
。 - 指定
ListView
如何显示DataTable
(即,指定项的来源、配置列等)。 - 编写一个高亮显示
ListViewItem
的Style
。 - 创建一个有助于确定
ListViewItem
颜色的类。
本文的演示应用程序创建了一个简单的 DataTable
,其中包含客户 ID、姓名和余额。如果客户有欠款(即,她的余额为负数),则该客户的项将以红色高亮显示。如果客户欠款,则该项将为绿色。
第一步 - 填充 DataTable 并将其绑定到 ListView
假设我们的 Window
子类中包含一个名为 'listView
' 的 ListView
。首先,我们必须创建 DataTable
并将其设置为 ListView
的 DataContext
。
public Window1()
{
InitializeComponent();
this.listView.DataContext = CreateDataTable();
}
// In a real app the DataTable would be populated from a database
// but in this simple demo the dummy data is created locally.
DataTable CreateDataTable()
{
DataTable tbl = new DataTable( "Customers" );
tbl.Columns.Add( "ID", typeof( int ) );
tbl.Columns.Add( "Name", typeof( string ) );
tbl.Columns.Add( "Balance", typeof( decimal ) );
tbl.Rows.Add( 1, "John Doe", 100m );
tbl.Rows.Add( 2, "Jane Dorkenheimer", -209m );
tbl.Rows.Add( 3, "Fred Porkroomio", 0m );
tbl.Rows.Add( 4, "Mike Spike", 550m );
tbl.Rows.Add( 5, "Doris Yakovakovich", 0m );
tbl.Rows.Add( 6, "Boris Zinkwolf", -25m );
return tbl;
}
第二步 - 指定 ListView 如何显示 DataTable
既然 DataTable
已经准备好并可供显示,让我们看看如何在 ListView
中显示它。
<ListView
Name="listView"
ItemContainerStyle="{StaticResource ItemContStyle}"
ItemsSource="{Binding}"
>
<ListView.View>
<GridView>
<GridViewColumn Header="ID" DisplayMemberBinding="{Binding ID}" />
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="Balance" Width="140">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Balance}" TextAlignment="Right" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
在 Window
的构造函数中,我们将一个 DataTable
赋值给了 ListView
的 DataContext
,所以将其 ItemsSource
属性设置为 '{Binding}
' 意味着简单地绑定到该 DataTable
。ListView
中显示的每一列都由一个 GridViewColumn
表示。 'Balance
' 列的 CellTemplate
已设置(而不是使用 DisplayMemberBinding
),以便货币值可以右对齐,这对于显示数值通常是这样做的。
ListView
的 ItemContainerStyle
属性设置为一个 Style
,该 Style
尚未显示。使用 ItemContainerStyle
是因为该属性会影响 ListView
生成的每个 ListViewItem
的 Style
属性。由于我们希望高亮显示整个 ListViewItem
,因此该属性是应用我们的“高亮样式”的逻辑位置。
第三步 - 编写一个高亮显示 ListViewItems 的 Style
在前一部分中,ListView
的 ItemContainerStyle
被设置为一个键为 'ItemContStyle
' 的 Style
。该 Style
如下所示:
<Style x:Key="ItemContStyle" TargetType="{x:Type ListViewItem}">
<Style.Resources>
<!-- Brushes omitted for clarity… -->
<!-- Reduces a customer's Balance to either -1, 0, or +1 -->
<local:NumberToPolarValueConverter x:Key="PolarValueConv" />
</Style.Resources>
<!-- Stretch the content so that we can right-align values
in the Balance column. -->
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Style.Triggers>
<!-- When a customer owes money, color them green. -->
<DataTrigger
Binding="{Binding Balance, Converter={StaticResource PolarValueConv}}"
Value="+1"
>
<Setter Property="Background" Value="{StaticResource ProfitBrush}" />
</DataTrigger>
<!-- When a customer is owed money, color them red. -->
<DataTrigger
Binding="{Binding Balance, Converter={StaticResource PolarValueConv}}"
Value="-1"
>
<Setter Property="Background" Value="{StaticResource LossBrush}" />
</DataTrigger>
</Style.Triggers>
</Style>
该 Style
为每个 ListViewItem
设置了两个属性:HorizontalContentAlignment
和 Background
。前者设置为 'Stretch
',以便 ListView
的“单元格”中的元素占据这些单元格的全部表面区域。这允许我们右对齐“Balance
”列中的文本。
每个 ListViewItem
的 Background
属性根据客户的 'Balance
' 值
有条件地设置为“高亮画刷”。使用 DataTrigger
来评估客户的 'Balance
' 值
,然后,如果客户欠款或有欠款,则该客户的 ListViewItem
的 Background
将设置为相应的画刷。
第四步 - 创建一个类,用于帮助确定 ListViewItem 的颜色
在前一部分中看到的 DataTrigger
在它们的 Binding
中使用了一个自定义值转换器,名为 NumberToPolarValueConverter
。该转换器的目的是接收客户的余额并返回一个简单值,指示该客户是有欠款、欠款还是没有余额。如果客户欠款(即客户余额大于零美元),则返回 +1
。如果客户有欠款,则返回 -1
。如果客户没有余额,则返回零。
这个值转换器是必需的,因为 DataTrigger
的 Value
属性不能表示范围,它只能表示一个离散值。换句话说,无法让 DataTrigger
的 Value
指示当客户余额例如小于零时触发器应该执行。
由于 Value
不能表示范围,我们可以采取相反的方法,让 DataTrigger
的 Binding
消除 'Balance
' 字段可以具有的值范围。如果 Binding
评估为一小组离散值(-1、0 或 +1),那么 Value
属性就可以轻松地用于检查这些特定值。
以下是该值转换器的实现方式:
[ValueConversion( typeof(object), typeof(int) )]
public class NumberToPolarValueConverter : IValueConverter
{
public object Convert(
object value, Type targetType,
object parameter, CultureInfo culture )
{
double number = (double)System.Convert.ChangeType( value, typeof(double) );
if( number < 0.0 )
return -1;
if( number == 0.0 )
return 0;
return +1;
}
public object ConvertBack(
object value, Type targetType,
object parameter, CultureInfo culture )
{
throw new NotSupportedException( "ConvertBack not supported" );
}
}
外部链接
WPF 中的 ADO.NET 数据绑定
相关主题
历史
- 2007 年 4 月 28 日 – 创建了文章。