This might be impossible or a bit wrong headed, however in WinForms I’ve got combo boxes that need populating with specific options. The project uses about 10 different forms, all with similar but slightly different functionality: hence why I didn’t use just one form and hide/show controls as appropriate.
Now I made a simple dictionary of options and fed the values with an Enum. Now I realise I’ve got duplicate code and would like to consolidate it. The option sets are date order and name order, but I’ve got one or two more to list.
This is what I’ve tried but cannot pass the dictionary into:
Public Sub BuildOrderOptions(nameorder As ComboBox, Options As Dictionary(Of String, [Enum]))
nameorder.Items.Clear()
For Each item In Options
nameorder.Items.Add(item)
Next
nameorder.DisplayMember = "Key"
nameorder.ValueMember = "Value"
End Sub
Property NameOrderOptions As New Dictionary(Of String, PersonList.orderOption) From {{"First Name", PersonList.orderOption.FirstName},
{"Last Name", PersonList.orderOption.LastName},
{"Room Number", PersonList.orderOption.RoomNumber}}
Property DateOrderOptions As New Dictionary(Of String, OrderDate) From {{"Newest First", OrderDate.NewestFirst}, {"Oldest First", OrderDate.OldestFirst}}
I’ve tried a few variations with Type and [enum].getnames etc but I can’t pass the differing dictionary types in at all – I think I’ve overcomplicated the whole business by now but feel I’m missing an elegant solution. Shortly I’ll either convert back to string matching alone, or just have functions per box type – evil duplication but I can move on.
Am I right in thinking there is a nicer way to do this? Unless I just define some kind of global resource for the options maybe-but globals are bad right?
Edit: Fixed thanks to Steven. In case anyone finds it useful OR better yet, anyone can critique and make nicer, here’s the module code that all the forms can use to generate their options.
Public Sub BuildOrderOptions(nameorder As ComboBox, Options As IDictionary)
nameorder.Items.Clear()
For Each item In Options
nameorder.Items.Add(item)
Next
nameorder.DisplayMember = "Key"
nameorder.ValueMember = "Value"
End Sub
Property NameOrderOptions As New Dictionary(Of String, orderOption) From {{"First Name", orderOption.FirstName},
{"Last Name", orderOption.LastName},
{"Room Number", orderOption.RoomNumber}}
Property DateOrderOptions As New Dictionary(Of String, OrderDate) From {{"Newest First", OrderDate.NewestFirst}, {"Oldest First", OrderDate.OldestFirst}}
Property personStatusOptions As New Dictionary(Of String, personStatus) From {{"Active", personStatus.Active},
{"InActive", personStatus.InActive},
{"All", personStatus.All}}
Public Sub BuildComboBoxes(ListBoxes As Dictionary(Of ComboBox, IDictionary))
For Each pair In ListBoxes
BuildOrderOptions(pair.Key, pair.Value)
Next
End Sub
Public Enum OrderDate
OldestFirst
NewestFirst
End Enum
Public Enum personStatus
Active
InActive
All
End Enum
Public Enum orderOption
None
FirstName
LastName
RoomNumber
End Enum
And here’s the way I’ve got one form using it – yes, I could have had a bunch of parameters or multiple function calls: I just like having a single object giving me a single parameter to pass on.
BuildComboBoxes( New Dictionary ( Of ComboBox , IDictionary ) From {{NameOrder, NameOrderOptions},
{DateOrder, DateOrderOptions},
{personStatus, PersonStatusOptions}})
You just need to change your method to accept any
IDictionaryobject rather than a specific type of dictionary:When you are using generics, such as
Dictionary(Of TKey, TValue), the generic type is not really a type at all. You can think of it like a template for any number of specific types. So each time you use a generic type using different type parameters, they are entirely different and incompatible types. For instance:As you have found out, even if you try to use a base class as the generic type parameter, the two are still incompatible. So, even though
Streamis the base class forMemoryStream, you still cannot do this: