快速有效地过滤绑定到ViewModel中集合的列表框

时间:2012-03-06 14:39:04

标签: linq mvvm filtering

在我的wpf窗口中,我有两个列表框。一个是可用项目,另一个是所选项目。未过滤时,可用商品通常会包含3000多件商品。向用户呈现用于过滤项目类型的组合框和用于过滤项目名称的文本框。目前我正在使用Linq来过滤这些项目,但它很快就刷新了这个列表。我想知道是否有更好的方法。

感兴趣的一些注释:我创建了一个附加行为,允许我将selecteditems(注意's')属性绑定到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}" />

视图模型:

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是完整的未过滤列表。如果我过滤列表,我只需要显示与过滤器匹配的项目,所以我只是使用Linq查询将这些项目添加到AvailableCis属性。

必须有更好的方法来做到这一点,因为过滤很慢(在视图中刷新列表之前大约需要5秒)

编辑:我的一位朋友建议使用数据视图,这会比每次过滤整个集合更好吗?

1 个答案:

答案 0 :(得分:0)

我已经把这一个想出来了。建议Dataview的同一个朋友记得WPF有一个错误并且加载了太多的项目。这真的减慢了用户界面的速度。我将列表框更改为Datagrids,并将它们设置为类似于列表框。结果是白天和黑夜。我现在有我想要的速度。