【问题标题】:Quick and efficient filtering of a listbox bound to a collection in the ViewModel快速有效地过滤绑定到 ViewModel 中的集合的列表框
【发布时间】:2012-03-24 01:17:15
【问题描述】:

在我的 wpf 窗口中,我有两个列表框。一个用于可用项目,另一个用于选定项目。未过滤时,可用项目通常包含 3000 多个项目。用户会看到一个组合框来过滤项目类型和一个文本框来过滤项目名称。目前我正在使用 Linq 过滤项目,但它刷新列表的速度非常慢。我想知道是否有更好的方法。

一些有趣的注意事项:我创建了一个附加行为,允许我将 selecteditems(注意's')属性绑定到视图模型,并且此行为需要一个集合类型才能工作。 我设置了文本过滤器以在更改时更新属性,并在属性设置器中调用过滤器方法。

查看:

<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 秒才能刷新视图中的列表)

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

【问题讨论】:

    标签: linq mvvm filtering


    【解决方案1】:

    我已经弄清楚了这一点。建议 Dataview 的同一位朋友只是记得 WPF 存在一个错误,并且加载了太多项目。这确实减慢了 UI 的速度。我将列表框更改为 Datagrids 并将它们设置为看起来像列表框。结果是白天黑夜。我现在有我想要的速度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-11
      • 2016-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-01
      相关资源
      最近更新 更多