codeGEN
codeGEN

Reputation: 714

Property of type dictionary

Is there a way to declare a property of type dictionary of string, string in VB.Net. I am using this on a usercontrol to add properties via the designer.

I tried the following:

Private v As Dictionary(Of String, String)
    Public Property VList As Dictionary(Of String, String)
        Get
            Return v
        End Get
        Set(ByVal value As Dictionary(Of String, String))
            v = value
        End Set
    End Property

But when I try this the string collection editor window opens up but the add & remove buttons are disabled. What is the correct way to declare this property?

I want to add the key & value via the designer.

Upvotes: 1

Views: 3134

Answers (1)

The Dictionary does not have a built in UITypeEditor. There are many reasons why there isn't: there are 2 Types which are generic, it also doesnt have an Item accessor, there is no simple Add method, the key must be unique and there is no built in way to serialize a Dictionary "item".

The right way is to use a Collection class inheriting from Collection<T> so you can control access to the contents (note: this is from System.Collections.ObjectModel not the horrible VB Collection!). The fast way to setup a working interface is to use a List(Of myTypeClass), but this is dangerous in production code because it allows all sorts of actions on the innerlist which you likely do not want.

<Serializable><TypeConverter(GetType(FooConverter))>
Public Class FooBar
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
    Public Property Name As String
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
    Public Property Value As String

   ' simple ctor REQUIRED for the UITypeEditor
   Public Sub New()
       Name = ""
       Value = ""
   End Sub

   ' ctor for the TypeConverter (NOT included)
   Public Sub New(n As String, v As String)
       Name = n
       Value = v
   End Sub

  Public Overrides Function ToString
      Return Name
  End Sub
End Class

' must be instanced
Private myFoo As New List(Of FooBar)

' list is an object so it cant be serialized, but the CONTENTS can be
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
Public Property FooList As List(of FooBar)
  Get
     If myFoo Is Nothing Then
         myFoo = New List(of FooBar)
     End If
     Return myFoo
  End Get
  Set
     ' do nothing
  End Set
End Sub

' for designer serialization
Private Function ShouldSerializeFooList As Boolean
    Return myFoo.Count > 0   ' or myFoo IsNot Nothing
End Sub

public Sub ResetMyFolist
  myFoo = New List(of FooBar)
End Sub

Caveats:

It is almost always better to write a class container for the Foobar items. Usually you would inherit from Collection<T>. List<T> as shown is a container and a collection, so the contents can be cleared, reset, modified etc when exposed as shown. They are fast and easy to implement though and the basic concept is the same.

If a Dictionary is really what you want, you can write your own UITypeEditor (not UIDesigner, this is not a control) but this would probably require a great deal of work on many levels. The reason there are not gobs of them flying around is that most people make do with one of the standard collections and simply enforce unique names in other ways. (Adding "Properties" to a usercontrol, suggests that really the key or name ought to be fixed and known to the app ahead of time so it knows what it is and what to do with it(?)).

Often VS can perform designer serialization on its own with simple properties like those in FooBar. However, since they are items in a collection, you will likely need to also write a TypeConverter which can return an InstanceDescriptor, to help VS instance them. But that is a different question.

Upvotes: 2

Related Questions