TOC

This article is currently in the process of being translated into Russian (~99% done).

Элемент ListView:

Фильтрация данных в элементе ListView

Мы уже совершали несколько различных задач вместе с ListView, как группировка и сортировка, но существует и другая очень важная возможность - фильтрация. Очевидно, что Вы могли бы ограничить количество элементов, которое могли бы добавить в первую очередь, но часто Вам нужно фильтровать ListView динамично, во время выполнения, обычно, основываясь на пользовательской строки фильтрации. К счастью для нас, механизмы view элемента 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 для отображения результата.

В программной части мы начинаем с добавления нескольких User объектов в ListView так же, как мы делали в предыдущих примерах. Интересующая нас часть начинается в последних двух строках конструктора, где вы приобретаем ссылку на экземпляр CollectionView для ListView и далее назначаем делегат свойству Filter. Этот делегат указывает на функцию, названную UserFilter, которую мы реализовали ниже. Она обрабатывает каждый элемент, указанный в первом(и только) параметре и возвращает результат в виде логического значения, указывающего на то, должен ли данный элемент быть виден в списке.

В методе UserFilter() мы смотрим на элемент TextBox(txtFilter), чтобы увидеть содержит ли он любой текст - и если содержит, мы используем его для проверки содержания имени User(что является свойством, которое мы решили фильтровать) в введённой строке и возвращаем положительный или отрицательный результат в зависимости от его значения. Если TextBox пуст, то возвращаем true, так как в этом случае мы хотим, чтобы все элементы были видимы.

Событие txtFilter_TextChanged также важно. При каждом изменении текста мы получаем ссылку на объект View элемента ListView и далее на нём вызываем метод Refresh(). Это гарантирует точное срабатывание делегата Filter при каждом изменении значения строки поиска/фильтра в поле ввода пользователем.

Заключение

Это была довольно простая реализация, но с того момента, как Вы получите доступ ко всем элементам(в этом случае это класс User) вы сможете выполнять любые типы фильтрации какие захотите, так как Вы имеете полный доступ ко всей информации о каждом элементе в списке. Например, образец выше может быть легко изменён для фильтрации по возрасту, учитывающего свойство Age вместо свойства Name, или же Вы могли бы изменить его таким образом, чтобы учитывалось более одного свойства, например, для фильтрации пользователей в возрастом ниже X И с именем, которое не содержит "Y".

This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!