65.9K
CodeProject 正在变化。 阅读更多。
Home

高亮 WPF ListView 中的项目

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (36投票s)

2007年4月28日

CPOL

4分钟阅读

viewsIcon

361749

downloadIcon

6491

逐步回顾如何有条件地高亮 ListViewItems。

Screenshot - HighlightingItemsInWPFListView.png

引言

本文介绍如何根据项的值或与项相关的值来更改 ListView 中项的颜色。这里使用的技术是将 ListView 绑定到一个 ADO.NET DataTable,并利用自定义值转换器来确定每个 ListViewItem 应为何种颜色。

背景

这是一个常见场景:您有一个 DataTable 需要显示在 ListView 中,并且包含某个范围内(例如,小于零)值的任何行都应以特殊颜色“高亮显示”。也许决定 ListViewItem 颜色的值甚至没有在 ListView 中显示,而仅存在于 DataRow 中。如何在 WPF 中实现此功能?

此任务涉及四个步骤

  1. 填充 DataTable 并将其绑定到 ListView
  2. 指定 ListView 如何显示 DataTable(即,指定项的来源、配置列等)。
  3. 编写一个高亮显示 ListViewItemStyle
  4. 创建一个有助于确定 ListViewItem 颜色的类。

本文的演示应用程序创建了一个简单的 DataTable,其中包含客户 ID、姓名和余额。如果客户有欠款(即,她的余额为负数),则该客户的项将以红色高亮显示。如果客户欠款,则该项将为绿色。

第一步 - 填充 DataTable 并将其绑定到 ListView

假设我们的 Window 子类中包含一个名为 'listView' 的 ListView。首先,我们必须创建 DataTable 并将其设置为 ListViewDataContext

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 赋值给了 ListViewDataContext,所以将其 ItemsSource 属性设置为 '{Binding}' 意味着简单地绑定到该 DataTableListView 中显示的每一列都由一个 GridViewColumn 表示。 'Balance' 列的 CellTemplate 已设置(而不是使用 DisplayMemberBinding),以便货币值可以右对齐,这对于显示数值通常是这样做的。

ListViewItemContainerStyle 属性设置为一个 Style,该 Style 尚未显示。使用 ItemContainerStyle 是因为该属性会影响 ListView 生成的每个 ListViewItemStyle 属性。由于我们希望高亮显示整个 ListViewItem,因此该属性是应用我们的“高亮样式”的逻辑位置。

第三步 - 编写一个高亮显示 ListViewItems 的 Style

在前一部分中,ListViewItemContainerStyle 被设置为一个键为 '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 设置了两个属性:HorizontalContentAlignmentBackground。前者设置为 'Stretch',以便 ListView 的“单元格”中的元素占据这些单元格的全部表面区域。这允许我们右对齐“Balance”列中的文本。

每个 ListViewItemBackground 属性根据客户的 'Balance' 有条件地设置为“高亮画刷”。使用 DataTrigger 来评估客户的 'Balance' ,然后,如果客户欠款或有欠款,则该客户的 ListViewItemBackground 将设置为相应的画刷。

第四步 - 创建一个类,用于帮助确定 ListViewItem 的颜色

在前一部分中看到的 DataTrigger 在它们的 Binding 中使用了一个自定义值转换器,名为 NumberToPolarValueConverter。该转换器的目的是接收客户的余额并返回一个简单值,指示该客户是有欠款、欠款还是没有余额。如果客户欠款(即客户余额大于零美元),则返回 +1。如果客户有欠款,则返回 -1。如果客户没有余额,则返回零。

这个值转换器是必需的,因为 DataTriggerValue 属性不能表示范围,它只能表示一个离散值。换句话说,无法让 DataTriggerValue 指示当客户余额例如小于零时触发器应该执行。

由于 Value 不能表示范围,我们可以采取相反的方法,让 DataTriggerBinding 消除 '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 日 – 创建了文章。
© . All rights reserved.