Как отфильтровать список универсальных объектов

#vb.net #list #linq-to-objects

#vb.net #Список #linq-to-objects

Вопрос:

Я нашел код для реализации SortableBindingList, который расширяет BindingList, и теоретически он позволяет сортировать и фильтровать список общих объектов. Он отлично работает, сортируя список, но я не могу получить фильтрацию.

Код фильтра выглядит следующим образом

        Protected Sub UpdateFilter()
        _isSorted = False 'remove sort.
        Try
            'We filter on the entire collection
            Dim filtered = _originalData.AsQueryable()

            If Not String.IsNullOrEmpty(_filter) Then filtered = filtered.Where(_filter)

            Dim filteredResult = filtered.ToList()
            Items.Clear()

            If filteredResult IsNot Nothing AndAlso filteredResult.Count > 0 Then
                For Each tItem As T In filtered
                    Items.Add(tItem)
                Next
            End If
        Catch
            'Reset the list
            Items.Clear()
            For Each tItem As T In _originalData
                Items.Add(tItem)
            Next

            'Rethrow the error
            Throw
        Finally
            OnListChanged(New ListChangedEventArgs(ListChangedType.Reset, -1))
        End Try
    End Sub
  

Проблема в том, что следующий пример получает как фильтр строку в предложении where, но компиляция выдает ошибку, поскольку она ожидает функцию
Я не знаю, как это решить

Извините, если вы плохо понимаете. Я плохо говорю по-английски

Комментарии:

1. Where Предложение ожидает Function(item as T) (где T — тип элементов в _originalData ), который возвращает Boolean результат. Вам понадобится функция, которая может анализировать _filter и обрабатывать логику, которую она представляет, до Boolean результата. Это непростая задача. Более простой способ (но все же требующий значительного объема работы) — предоставить пользователю форму, которая позволяет ему выбрать свойство, определенное на T , применить оператор сравнения и ввести значение для сравнения свойства. Выполнение этого таким образом ограничивает возможности, которые необходимо учитывать в коде вычисления выражения.

2. Продолжение.. Если вы знакомы с MS Excel, посмотрите, как они обрабатывают определение пользовательского автофильтра, представляя диалоговое окно с выпадающими списками.

Ответ №1:

Вам нужно передать предикат. Я надеюсь, что этот пример поможет вам.

 Private Function AddFilter(list As List(Of String), filter As Func(Of String, Integer, Boolean)) As List(Of String)
    Dim l As IEnumerable(Of String) = Nothing
    If Not IsNothing(filter) Then
        l = list.Where(filter)
    End If
    Return l.ToList
End Function

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim A As New List(Of String) From {"Mathew", "Mark", "Luke", "John"}
    Dim predicate As Func(Of String, Integer, Boolean) = Function(str, index) str.StartsWith("M")
    Dim FilteredList = AddFilter(A, predicate)
    For Each s As String In FilteredList
        Debug.Print(s)
    Next
End Sub
  

Ответ №2:

В каком-то сообщении есть ответ, который рекомендует это.

Вы можете использовать динамический Linq:

Затемняйте фильтр как String = «property1>10 и property2 как ‘anystring’ или property3<=25».

Тусклые результаты = элементы.Где(фильтр).

Но я не знаю, как использовать dinamic linq