views:

218

answers:

1

Hi, A bunch of dotnet framework components use a DataSource component. I have an object that has a number of settings that can modify the DataSource which it represents. I would like to set this object as the dropdown DataSource of a set of ComboBoxes and DataGridViewComboBoxCells.

My problem comes when trying to actually hook the thing into the ComboBox. I guess that because the changes to the DataSource can happen once the DataSource has been set, I have to use one of these BindingSource things, but the MSDN literature is pulling its usual prank of telling me what a bindingSource is without telling me what it does or how it works.

What's the best way you guys can suggest of hooking this Object up as a DataSource/BindingSource?

EDIT:
Obviously this class is junk, but it illustrates the sort of object I have now.
Most of the timing is up in the air at the moment, but basically what this shows is that my class is not a collection itself, but contains one. I need to be able to instruct the DataSource property of a ComboBox that there is a volatile list to be found here, and that it should use that list as the DataSource for its dropdown.

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
+2  A: 

Short version: use BindingList<T>...

Long version:

A DataSource is typically either:

  • an individual object (for simple binding)
  • a list source (IListSource)
  • a list (IList)

Since you are using it for a drop-down, it sounds like you want one of the second two, typically IList (IListSource is relatively rare, except for DataTable).

For changes once you have bound, you need notifications. For simple bindings (individual objects), either INotifyPropertyChanged or *Changed events are the way to go - but for lists you need to implement IBindingList and raise the ListChanged event to tell the control what happened.

To be honest, this is a lot of non-interesting work that it is very easy to make a mess of.

The pragmatic approach is to work with BindingList<T> (possibly inheriting from it). This gives you all the list notifications, including support for items in the list changing if you implement INotifyPropertyChanged on the items (it doesn't support *Changed events, though).

Caveat: not all controls care about notifications... and if they don't there isn't a lot you can do about it. So if you don't see additions/swaps/etc even when using BindingList<T> - or you don't see item updates when implement INotifyPropertyChanged, then... er, tough?

Marc Gravell
Ah, iBindingList lives in System.ComponentModel, which I don't have hooked directly to Intellisense.I had looked at iBindingSource, which still looks incomprehensible, and is probably totally unrelated to what I'm looking for. iBindingList is a heck of an implementation to have to fill up, but it's *much* more what I was looking for. Thanks very much.One thing, though, I don't suppose there's an iBindingEnumerable or similar? I'll probably just have lots of inactive functions in my iBindingList implementation, so that people can't add stuff, but it would be nice to do without list methods...
Frosty840
Nope, basically. ASP.NET can make do with `IEnumerable<>`, because it is only read once - but everything else wants to be able to get at data multiple times, so it uses the indexer on IList.
Marc Gravell
It could be worse - you might have to implement ITypedList ;-p (which involves writing your own PropertyDescriptors...)
Marc Gravell
btw - IBindingList is in **addition** to implementing the (non-generic) IList interface...
Marc Gravell
Oh, so it is. VB put in all the method declarations for me, so I didn't notice, but you're right; iBindingList does force implementation of both iList and iEnumerable. It's a shame there's no <T>iBindingList, but as I'm not going to put any code in my implementation of the List manipulation functions, it's a moot point.
Frosty840