-
ListView控制项:

ListView过滤

我们已经使用ListView做了几件不同的事情,比如分组和排序,但另一个非常有用的功能是过滤。显然,您可以首先限制添加到ListView的项目,但通常需要在运行时动态过滤ListView,通常基于用户输入的过滤器字符串。对我们来说幸运的是,ListView的视图机制也很容易做到这一点,就像我们通过排序和分组一样。

过滤实际上很容易,所以让我们直接跳到一个例子中,然后我们将讨论它:

<Window x:Class="WpfTutorialSamples.ListView_control.FilteringSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="FilteringSample" Height="200" Width="300">
    <DockPanel Margin="10">
        <TextBox DockPanel.Dock="Top" Margin="0,0,0,10" Name="txtFilter" TextChanged="txtFilter_TextChanged" />
        <ListView Name="lvUsers">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Name" Width="120" DisplayMemberBinding="{Binding Name}" />
                    <GridViewColumn Header="Age" Width="50" DisplayMemberBinding="{Binding Age}" />
                </GridView>
            </ListView.View>
        </ListView>
    </DockPanel>
</Window>
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Data;

namespace WpfTutorialSamples.ListView_control
{
	public partial class FilteringSample : Window
	{
		public FilteringSample()
		{
			InitializeComponent();
			List<User> items = new List<User>();
			items.Add(new User() { Name = "John Doe", Age = 42 });
			items.Add(new User() { Name = "Jane Doe", Age = 39 });
			items.Add(new User() { Name = "Sammy Doe", Age = 13 });
			items.Add(new User() { Name = "Donna Doe", Age = 13 });
			lvUsers.ItemsSource = items;

			CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(lvUsers.ItemsSource);
			view.Filter = UserFilter;
		}

		private bool UserFilter(object item)
		{
			if(String.IsNullOrEmpty(txtFilter.Text))
				return true;
			else
				return ((item as User).Name.IndexOf(txtFilter.Text, StringComparison.OrdinalIgnoreCase) >= 0);
		}

		private void txtFilter_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
		{
			CollectionViewSource.GetDefaultView(lvUsers.ItemsSource).Refresh();
		}
	}

	public enum SexType { Male, Female };

	public class User
	{
		public string Name { get; set; }

		public int Age { get; set; }

		public string Mail { get; set; }

		public SexType Sex { get; set; }
	}
}

XAML部分非常简单:我们有一个TextBox,用户可以在其中输入搜索字符串,然后使用ListView来显示结果。

在Code-behind中,我们首先向ListView添加一些User对象,就像我们在前面的例子中所做的那样。有趣的部分发生在构造函数的最后两行中,我们获取对ListView的CollectionView实例的引用,然后将委托分配给Filter属性。这个委托指向名为UserFilter的函数,我们在下面实现了它。它将每个项目作为第一个(也是唯一的)参数,然后返回一个布尔值,指示给定项目是否应该在列表中可见。

UserFilter()方法中,我们看看TextBox控件(txtFilter),看看它是否包含任何文本 - 如果是,我们用它来检查User的名称(这是我们的属性)已经决定过滤)包含输入的字符串,然后根据它返回true或false。如果TextBox为空,则返回true,因为在这种情况下,我们希望所有项都可见。

txtFilter_TextChanged事件也很重要。每次文本更改时,我们都会获得对ListView的View对象的引用,然后在其上调用Refresh()方法。这可确保每次用户更改搜索/过滤字符串文本框的值时都会调用过滤器委托。

小结

这是一个非常简单的实现,但由于您可以访问每个项目,在本例中是User类,您可以进行任何类型的自定义过滤,因为您可以访问有关每个项目的所有数据在列表中。例如,通过查看Age属性而不是Name属性,上面的示例可以很容易地更改为过滤年龄,或者您可以修改它以查看多个属性,例如筛选出年龄低于X且名称不包含“Y”的用户。