В этой статье мы рассмотрим, как выполнять поиск и фильтрацию элементов в ListBox WPF с помощью CollectionViewSource. Мы начнем с обсуждения функциональных возможностей CollectionViewSource, а затем приведем пример его работы. Затем мы будем использовать его для поиска, а также для группировки элементов в ListBox. Этот пример может быть применен к другим элементам управления WPF, таким как ComboBox, DataGrid и т.д., Так что вы можете легко применить тот же подход, если это необходимо!
Определение CollectionViewSource
CollectionViewSource — это мощный инструмент, который позволяет нам отделять исходную коллекцию от представления и манипулировать ею без изменения фактической коллекции. Такое разделение источника и представления предотвращает неожиданные изменения в наших данных, позволяя нам привязывать одну и ту же коллекцию источников к нескольким представлениям. Свойство View CollectionViewSource дает разработчикам полный контроль над тем, как они хотят представлять свои данные, что делает его бесценным ресурсом для любого проекта, где требуется несколько представлений для одного набора данных.
Примеры поиска и группировки
В этой части статьи я продемонстрирую, как мы можем привязать одну и ту же исходную коллекцию, чтобы иметь фильтр поиска и группировку элементов в одном представлении. Делая это, пользователи могут быстро идентифицировать конкретные объекты в своих коллекциях без необходимости ручного поиска по каждому объекту. Это особенно полезно при работе с большими объемами данных, поскольку обеспечивает эффективную группировку и фильтрацию.
Приведенный рисунок дает пример того, чего мы можем достичь, связав таким образом нашу исходную коллекцию воедино.
На рисунке показано использование ListBox с левой стороны для поиска и группировки с правой стороны. Важно отметить, что обе эти функции используют одну и ту же исходную коллекцию. Это позволяет пользователям быстро выполнять поиск по своим данным и эффективно группировать элементы вместе.
Шаги по созданию поиска и группировки
Создадим MainWindow.xaml. наше представление.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
<Window x:Class="WorkOrders.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Title="MainWinow" Height="450" Width="800"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal"> <TextBlock Text="Поиск: "></TextBlock> <TextBox Text="{Binding FirstSearchText,UpdateSourceTrigger=PropertyChanged}" Width="100"/> </StackPanel> <ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Row="1"> <ListBox ItemsSource="{Binding FirstCollectionViewSource}"> <ListBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding ProcessName}"></TextBlock> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </ScrollViewer> <ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Column="1" Grid.Row="1"> <ListView ItemsSource="{Binding SecondCollectionViewSource}" HorizontalContentAlignment="Stretch" Grid.Column="1" Grid.Row="1"> <ListView.ItemTemplate> <DataTemplate> <UniformGrid Rows="1" Columns="2"> <TextBlock Text="{Binding ProcessName}"> <TextBlock Text="{Binding Id,StringFormat=ID: \{0\}}"> </TextBlock> </TextBlock> </UniformGrid> </DataTemplate> </ListView.ItemTemplate> <ListView.GroupStyle> <GroupStyle> <GroupStyle.HeaderTemplate> <DataTemplate> <Border BorderBrush="Red" BorderThickness="2" Background="White" Margin="2"> <TextBlock Text="{Binding Name, StringFormat=Priority: {0}}" FontSize="16" FontWeight="Bold" Margin="4"> </TextBlock> </Border> </DataTemplate> </GroupStyle.HeaderTemplate> </GroupStyle> </ListView.GroupStyle> </ListView> </ScrollViewer> </Grid> </Window> |
В приведенном выше коде XAML есть ListBox и ListView, но вы можете использовать любой элемент управления, производный от ItemsControl. Первый используется для фильтрации элементов, а второй — для их группировки.
Используя связанный элемент управления таким образом (в этом примере используется ListView), вы можете изменить порядок данных, чтобы отразить как группировку, так и правила фильтрации, а также порядок сортировки. К сожалению, по умолчанию визуальная индикация этой группировки недоступна; однако здесь был определен GroupStyle, чтобы обеспечить желаемые заголовки. Обратите внимание, что указанное здесь свойство Name точно не называет группу — оно относится к PriorityClass, который фактически формулирует группировку данных.
Теперь переходим к классу ViewModel. Пожалуйста, проверьте приведенный ниже код.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
public class MainViewModel { private string firstSearchText; private string secondSearchText; public MainViewModel() { AllProcess = new ObservableCollection<Process>(Process.GetProcesses()); FirstCollectionViewSource = new CollectionViewSource { Source = AllProcess }.View; SecondCollectionViewSource = new CollectionViewSource { Source = AllProcess }.View; SecondCollectionViewSource.GroupDescriptions.Add(new PropertyGroupDescription("PriorityClass")); } private bool DoesCollectionContainName(object processName) { Process prcName = processName as Process; return prcName.ProcessName.ToLower().Contains(FirstSearchText.ToLower()); } public ObservableCollection<Process> AllProcess { get; set; } public ICollectionView FirstCollectionViewSource { get; set; } public ICollectionView SecondCollectionViewSource { get; set; } public string FirstSearchText { get { return firstSearchText; } set { firstSearchText = value; FirstCollectionViewSource.Filter = DoesCollectionContainName; } } } |
В приведенном выше коде подробно описаны шаги для получения списка всех процессов в системе и привязки его к объекту ObservableCollection с именем AllProcess. Два экземпляра CollectionViewSource были созданы в конструкторе класса — FirstCollectionViewSource и SecondCollectionViewSource — которые являются свойствами типа ICollectionView, что предотвращает прямое изменение исходной коллекции.
Затем два свойства привязываются к соответствующим ListBox в файле.xaml. Кроме того, SecondCollectionViewSource имеет GroupDescription, назначенную его свойству PriorityLevel, которое является частью класса Process.
FirstCollectionViewSource оснащен фильтром для свойства FirstSearchText. Это свойство привязано к элементу управления TextBox, который находит все процессы, имена которых содержат введенный текст. Фильтр работает, принимая делегат-предикат, поэтому мы настроили функцию DoesCollectionContainName для перебора каждого элемента коллекции и возврата тех элементов, которые удовлетворяют условию.
Когда вы запустите это приложение, вы увидите, как работает CollectionViewSource на практике.
Вывод
В этой статье обсуждалось использование CollectionViewSource для фильтрации и группировки источника данных. Используя этот метод, пользователи могут расширить функциональность своих приложений, предоставив мощные возможности фильтрации и сортировки. В целом, CollectionViewSource предлагает интуитивно понятный способ запроса, фильтрации и сортировки источников данных.