在 ListView 控件中显示带淡入淡出效果的更新列表视图项
如果列表视图频繁更新,用户往往难以注意到所有更新。此 ListView 控件将通过显示列表视图项的变化,根据变化方式使用不同的颜色,并让列表项逐渐淡化至原始颜色来解决此问题。
图 1:带有列表视图控件的演示应用程序。
引言
通常,列表视图由用户直接更新,方法是选择一个列表视图项然后进行编辑或删除。新项通常添加到列表的底部。这工作得很好,因为用户知道哪些项已更改或删除,以及新项将出现在哪里。它的一个缺点是,如果列表已排序,则新项将不会以排序的方式显示,而是按创建顺序列出。
然而,有些列表视图会因为导致列表视图更新的某个事件而自动修改。如果这些更新频繁发生,用户将很难看到发生了什么变化,因为用户没有发起更改,也没有期望它。例如,一个实时显示股票价格的列表视图。股票价格通常以快速的方式更新,跟上这些更新并非易事。突出这些变化无疑对用户来说将是一个受欢迎的功能。
FadingListView
类是解决这些问题的方案。更改的列表视图项显示不同的颜色,与其他列表视图项区分开,使其“突出”;表明它是一个“热门”项。然后,该项会随时间慢慢冷却,并变回其原始颜色,即正常颜色。添加的项也是如此;除了我们应该使用另一种颜色来显示项是最近添加的,而不是最近编辑的。由于我们现在使用另一种颜色显示添加的项,因此我们无需将它们显示在列表的底部,而是将它们显示在用户期望它们出现的位置, nicely sorted in the list. 删除项的工作方式略有不同。我们不会直接从列表中删除它们,而是首先用某种特殊的颜色着色,然后让它们逐渐消失,即慢慢改变它们的颜色,使其与列表视图控件的背景颜色相同。它们将逐渐变得不可见,然后就可以从列表中删除了。
FadingListView 的实现
FadingListView
继承自 ListView
。ListView
类很难通过继承来重写,因为它被分割成许多类,即 ListView
、ListViewItemCollection
、ListViewItem
等等。我们需要重写的大多数方法和属性都是非 virtual
的,因此我们需要通过添加新方法而不是重写现有方法来解决此问题。
因此,我们需要添加一些方法,供任何希望使用列表视图的客户端代码调用。用于列表视图项处理颜色渐变的额外信息将存储在项的用户数据标签中,这是一个关联的数据对象,可用于此类目的。我们使用一个名为 TagWrapper
的类来保存用户的数据标签以及项的状态和当前颜色。一个每秒滴答一次的计时器用于通过缓慢的颜色转换来实现渐变效果。每秒,我们都会遍历所有现有的列表视图项,然后将它们的颜色淡化一步,直到它们淡回到原始颜色。如果它们被删除,它们将淡化为列表视图的背景颜色;即变得不可见。当发生这种情况时,我们将它们从列表中删除。该类的源代码有丰富的注释,因此请参阅附件代码以获取更多详细信息。
使用 FadingListView
FadingListView
控件具有设计时支持,可以设置其一些属性。如图 2 所示,可以设置不同的颜色来区分列表视图项的变化。还可以设置这些颜色在淡出之前应使用的时间。当然,也可以使用 FadingListView
类的 public
属性在代码中进行设置。
图 2:设计时支持。
以下代码展示了如何在添加、编辑和删除列表视图项时使用 FadingListView
类。
// Create a FadingListView object.
FadingListView fadingListView = new FadingListView();
// To add a list view item we call AddItem().
ListViewItem listViewItem = new ListViewItem();
// Update listViewItem.
fadingListView.AddItem(listViewItem);
// To change a list view item we call ChangeItem().
// Here we will change the currently selected item.
ListViewItem listViewItem = fadingListView.SelectedItems[0];
// Update listViewItem.
fadingListView.ChangeItem(listViewItem);
// To delete a list view item we call DeleteItem().
// Here we will delete the currently selected item.
ListViewItem listViewItem = fadingListView.SelectedItems[0];
fadingListView.DeleteItem(listViewItem);
由于我们使用了列表视图项的标签,因此无法像通常那样使用 ListViewItem
对象的 Tag
属性来访问它。取而代之的是,我们有两个新的 static
函数:SetTag()
和 GetTag()
。在下面的代码中,listViewItem
是一个 ListViewItem
类型的对象,它应该使用 AddItem()
方法添加到我们的列表视图中。
FadingListView.SetTag(listViewItem, "some reference");
string itemRef = (string)FadingListView.GetTag(listViewItem);
ColorTransform 类
FadingListView
类使用一个辅助类 ColorTransform
来执行实际的颜色转换。有关 ColorTransform
类的用法和内部工作原理的解释,可以在我的 C# 博客 中找到,具体是这篇 博客文章。
限制
FadingListView
的当前实现仅支持单选。由于我们每秒都会循环遍历所有列表视图项,因此如果列表视图包含更多项,此实现可能会变慢。SetTag()
和 GetTag()
方法要求在调用它们之前,列表视图项已通过 AddItem()
方法添加到列表中,否则将抛出异常。