Использование объекта, не являющегося коллекцией, в качестве источника данных

Группа компонентов платформы dotnet использует компонент DataSource. У меня есть объект с рядом настроек, которые могут изменять источник данных, который он представляет. Я хотел бы установить этот объект как раскрывающийся DataSource набора ComboBoxes и DataGridViewComboBoxCells.

Моя проблема возникает при попытке на самом деле зацепить вещь в ComboBox. Я предполагаю, что, поскольку изменения в DataSource могут произойти после установки DataSource, я должен использовать одну из этих вещей BindingSource, но литература MSDN вытягивает свою обычную шутку, рассказывая мне, что такое BindingSource, не говоря мне, что он делает или как это работает.

Какой лучший способ, ребята, вы можете предложить для подключения этого объекта в качестве DataSource/BindingSource?

РЕДАКТИРОВАТЬ:
Очевидно, что этот класс является мусором, но он иллюстрирует тип объекта, который у меня есть сейчас.
Большая часть времени в данный момент находится в воздухе, но в основном это показывает, что мой класс не является сама коллекция, но содержит один. Мне нужно иметь возможность указать свойству DataSource ComboBox, что здесь находится изменчивый список, и что он должен использовать этот список в качестве источника данных для своего раскрывающегося списка.

Public Class DynamicDataSource
    Private basicList As New List(Of String)(New String() {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"})
    Private _showEvensOnly As Boolean
    Private _showNotContainingO As Boolean
    Public Property ShowEvensOnly() As Boolean
        Get
            Return _showEvensOnly
        End Get
        Set(ByVal value As Boolean)
            _showEvensOnly = value
        End Set
    End Property
    Public Property ShowNotContainingO() As Boolean
        Get
            Return _showNotContainingO
        End Get
        Set(ByVal value As Boolean)
            _showNotContainingO = value
        End Set
    End Property
    Public Function GetDynamicList() As List(Of String)
        Dim processMe As New List(Of String)(basicList)
        If Me._showEvensOnly Then
            For JJ As Integer = processMe.Count - 1 To 0 Step -1
                If JJ Mod 2 = 0 Then
                    processMe.Remove(processMe(JJ))
                End If
            Next
        End If

        If Me._showNotContainingO Then
            For JJ As Integer = processMe.Count - 1 To 0 Step -1
                If processMe(JJ).ToUpper.Contains("O"c) Then
                    processMe.Remove(processMe(JJ))
                End If
            Next
        End If

        Return processMe
    End Function
End Class

person Frosty840    schedule 24.06.2009    source источник
comment
Некоторый пример кода был бы хорош :)   -  person Josh    schedule 24.06.2009
comment
Я думал, что это было достаточно ясно, но я думаю, это потому, что я уже знаю, в чем проблема. ;) Я что-нибудь подкину.   -  person Frosty840    schedule 24.06.2009


Ответы (1)


Короткая версия: используйте BindingList<T>...

Длинная версия:

DataSource обычно либо:

  • отдельный объект (для простой привязки)
  • источник списка (IListSource)
  • список (IList)

Поскольку вы используете его для раскрывающегося списка, похоже, вам нужен один из двух вторых, обычно IList (IListSource встречается относительно редко, за исключением DataTable).

Для изменений после привязки вам нужны уведомления. Для простых привязок (отдельных объектов) подходят события INotifyPropertyChanged или *Changed, но для списков необходимо реализовать IBindingList и вызвать событие ListChanged, чтобы сообщить элементу управления, что произошло.

Честно говоря, это очень много неинтересной работы, которую очень легко испортить.

Прагматичный подход — работать с BindingList<T> (возможно, наследуя от него). Это дает вам все уведомления списка, включая поддержку элементов в списке, изменяющемся, если вы реализуете INotifyPropertyChanged для элементов (однако он не поддерживает события *Changed).

Предостережение: не все элементы управления заботятся об уведомлениях... и если они этого не делают, вы мало что можете с этим поделать. Итак, если вы не видите добавления/замены/и т. д. даже при использовании BindingList<T> или вы не видите обновлений элементов при реализации INotifyPropertyChanged, тогда... эээ, сложно?

person Marc Gravell    schedule 24.06.2009
comment
Ах, iBindingList живет в System.ComponentModel, которую я не подключил напрямую к Intellisense. Я просмотрел iBindingSource, который все еще выглядит непонятным и, вероятно, совершенно не связан с тем, что я ищу. iBindingList — чертовски сложная реализация, которую нужно заполнить, но это намного больше того, что я искал. Большое спасибо. Одна вещь, однако, я не думаю, что есть iBindingEnumerable или что-то подобное? У меня, вероятно, просто будет много неактивных функций в моей реализации iBindingList, чтобы люди не могли добавлять что-то, но было бы неплохо обойтись без методов списка... - person Frosty840; 24.06.2009
comment
Нет, в принципе. ASP.NET может обойтись IEnumerable<>, потому что он читается только один раз, но все остальные хотят иметь возможность получать данные несколько раз, поэтому он использует индексатор в IList. - person Marc Gravell; 24.06.2009
comment
Могло быть и хуже - вам, возможно, придется реализовать ITypedList ;-p (что включает в себя написание ваших собственных дескрипторов свойств...) - person Marc Gravell; 24.06.2009
comment
кстати - IBindingList является дополнением к реализации (не общего) интерфейса IList... - person Marc Gravell; 24.06.2009
comment
О, так оно и есть. VB поместил за меня все объявления методов, так что я не заметил, но вы правы; iBindingList принудительно реализует как iList, так и iEnumerable. Жаль, что нет ‹T›iBindingList, но поскольку я не собираюсь вставлять какой-либо код в свою реализацию функций манипулирования списками, это спорный вопрос. - person Frosty840; 24.06.2009