В моем окне wpf у меня есть два списка. Один - для доступных предметов, а другой - для выбранных элементов. Доступные элементы обычно будут содержать более 3000 элементов, если они не будут отфильтрованы. Пользователю предоставляется сводка для фильтрации типа элемента и текстового поля для фильтрации имени элемента. В настоящее время я использую Linq для фильтрации элементов, но он обновляет список очень медленно. Мне интересно, есть ли лучший подход.Быстрая и эффективная фильтрация списка, связанного с коллекцией в ViewModel
Интересные примечания. Я создал привязанное поведение, чтобы я мог привязать свойство selecteditems (обратите внимание на ') на модель viewmodel, поэтому для работы требуется тип коллекции. У меня есть набор текстовых фильтров для обновления свойства при изменении, а в настройщике свойств я вызываю метод фильтра.
Вид:
<DatePicker Grid.Row="0" Grid.Column="1" Height="26" VerticalAlignment="Center" SelectedDate="{Binding FromDate}" />
<DatePicker Grid.Row="0" Grid.Column="3" Height="26" VerticalAlignment="Center" SelectedDate="{Binding ToDate}" />
<ComboBox Grid.Row="1" Grid.Column="1" Height="22" VerticalAlignment="Center" ItemsSource="{Binding Classes}" SelectedItem="{Binding SelectedClass}" />
<TextBox Grid.Row="4" Grid.Column="1" Height="22" VerticalAlignment="Center" Text="{Binding CiNameFilterText, UpdateSourceTrigger=PropertyChanged}" Margin="55,0,0,178" />
<ListBox Grid.Row="4" Grid.Column="1" Height="172" ItemsSource="{Binding AvailableCis}" DisplayMemberPath="CiName" SelectionMode="Extended" Ocean_WPF:ListBoxBehavior.SelectedItems="{Binding AvailableCisSelected}" Margin="0,28,0,0" />
<ListBox Grid.Row="4" Grid.Column="3" Height="200" ItemsSource="{Binding SelectedCis}" DisplayMemberPath="CiName" SelectionMode="Extended" Ocean_WPF:ListBoxBehavior.SelectedItems="{Binding SelectedCisSelected}" />
ViewModel:
Protected Sub FilterCiList()
Try
If (_caCiData IsNot Nothing) Then
If ((_selectedClass IsNot Nothing AndAlso Not _selectedClass.Equals(String.Empty)) AndAlso (_ciNameFilterText IsNot Nothing AndAlso Not _ciNameFilterText.Equals(String.Empty))) Then
Me.AvailableCis = New ObservableCollection(Of CA.SoftwareRow)(_caCiData.Where(Function(ci) ci.Class.ToUpper.Equals(_selectedClass.ToUpper) AndAlso ci.CiName.ToUpper.Contains(_ciNameFilterText.ToUpper)).OrderBy(Function(a) a.CiName))
ElseIf ((_selectedClass IsNot Nothing AndAlso Not _selectedClass.Equals(String.Empty)) AndAlso (_ciNameFilterText Is Nothing OrElse _ciNameFilterText.Equals(String.Empty))) Then
Me.AvailableCis = New ObservableCollection(Of CA.SoftwareRow)(_caCiData.Where(Function(ci) ci.Class.ToUpper.Equals(_selectedClass.ToUpper)).OrderBy(Function(a) a.CiName))
ElseIf ((_selectedClass Is Nothing OrElse _selectedClass.Equals(String.Empty)) AndAlso (_ciNameFilterText IsNot Nothing AndAlso Not _ciNameFilterText.Equals(String.Empty))) Then
Me.AvailableCis = New ObservableCollection(Of CA.SoftwareRow)(_caCiData.Where(Function(ci) ci.CiName.ToUpper.Contains(_ciNameFilterText.ToUpper)).OrderBy(Function(a) a.CiName))
Else
Me.AvailableCis = New ObservableCollection(Of CA.SoftwareRow)(_caCiData.OrderBy(Function(a) a.CiName))
End If
If (Me.SelectedCis IsNot Nothing) Then
For Each Ci In Me.SelectedCis
Me.AvailableCis.Remove(Ci)
Next
End If
End If
Catch ex As Exception
_viewModelUIService.ExceptionDialog(ex)
End Try
End Sub
_caCiData является полным списком нефильтрованного. Если я фильтрую список, мне нужно отображать только элементы, соответствующие фильтру, поэтому я просто добавляю эти элементы в свойство AvailableCis, используя запрос Linq.
Там должен быть лучшим способом сделать это, как фильтрация происходит медленно (занимает около 5 секунд, прежде чем он сможет обновить список в представлении)
Edit: мой друг предложил DataView, будет что работать лучше, чем фильтровать всю коллекцию каждый раз?