I'm having a little trouble with a PropertyGrid
.
I have set the selected object to a class containing various properties and 90% of them work correctly but for any where the property is a List(Of String)
it doesn't appear to call the Set
part of the property.
The class I have is as follows (shortened version):
Public Class VideosProperties
Public Property EpisodeColorOdd As Color
Get
Return Videos_EpisodeColorOdd
End Get
Set(value As Color)
Videos_EpisodeColorOdd = value
End Set
End Property
<Editor("System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"System.Drawing.Design.UITypeEditor,System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")>
Public Property Extensions As List(Of String)
Get
Return Videos_Extensions
End Get
Set(value As List(Of String))
Videos_Extensions = value
End Set
End Property
End Class
I have set the SelectedObject
to be this class using the following code:
Dim _Properties As Object
_Properties = New VideosProperties
PropertyGrid1.SelectedObject = _Properties
I have Initialized the List using the following code:
Extensions = New List(Of String)
When I run my code, the PropertyGrid
shows the EpisodeColorOdd
property and this works correctly, but the Extensions property doesn't.
When you edit the Extensions property using the PropertyGrid
, it doesn't call the Set(value as List(Of String))
part of the property.
I've had a look around and can't seem to find a solution (I'm probably not looking hard enough).
Can anyone help?
EDIT
Plutonix - Your code doesn't work. I have already copied and pasted into a new project and I get errors.
I get an error at
<Editor("System.Windows.Forms...etc")>
telling me "Type 'Editor' is not defined", so I Imported "System.ComponentModel" and now get an error saying "Overload resolution failed because no accessible 'New' accepts this number of arguments." at the same point.
If I remove the that part it doesn't work correctly.
I run the code, the form opens, I click on the Foods property and an Editor opens, I click Add and get the error "Constructor on type 'System.String' not found." which I've had before, and I fixed using
<Editor("System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor,System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")>
instead of
<Editor("System.Windows.Forms...etc")>
Now though, when I click on the property, it brings up a different editor and doesn't actually access the Set part of the property. So, I'm back to square one.
I cant be sure but from the code shown, you dont initialize the collection. Both the PropertyGrid
and StringCollectionEditor
are intended to edit existing properties values. By not initializing the List
- which itself is an object - that property container does not exist and neither of them will create it for you.
Your code shows the getter/setter boilerplate, but nothing about the backing fields.
Also, since VideosProperties
is a Type, you should use it to declare your variable as that Type rather than As Object
. By doing that, you are casting the var to the lowest possible form; your properties are only available via late binding which requires Option Strict
off.
Public Class Animal
' auto implement props available since VS2010:
Public Property Name As String
Public Property Species As String
Public Property Weight As Double
Public Property Coloring As Color
' backing field for the List:
Private mFoods As List(Of String)
' this of course would be the same as your code...
' no need to repeat
<Editor("System.Windows.Forms...etc")>
Public Property Foods As List(Of String)
Get
Return mFoods
End Get
Set(value As List(Of String))
' see notes
End Set
End Property
Public Sub New(n As String, s As String)
Name = n
Species = s
' initialize the List instance:
mFoods = New List(Of String)
End Sub
End Class
The key is that in the constructor (Sub New
) you create the list instance to hold the food items, video extensions or whatever. Using it:
' class/form level variable declared as Animal NOT Object
Private A As Animal
...
A = New Animal("Ziggy", "Feline")
A.Weight = 12.4 ' not possible if A is As Object
pGrid.SelectedObject = A
After the edit, A.Foods
will contain whatever was entered via the StringCollectionEditor
. If A
is declared As Object
, the code line to set the Weight
will prevent the code from compiling (with Option Strict
on). This is because System.Object
does not have a Weight
property. A As Animal
allows the compiler to see and use the properties defined. I suspect you are not using Option Strict
.
If your object has a valid List
instance when you send your object to the PropertyGrid
and a valid Editor is specified, you'll see this:
The PropGrid will display "Collection" indicating it knows what it is, and the "..." indicates the PropGrid has a valid editor associated with it. Proof that it retains the collection:
lbFoods.Items.AddRange(A.Foods.ToArray)
' results in:
Note that I have nothing in the setter for Foods
, yet it works. Collection Editors do not usually pass collection items back en masse via the setter. Instead, they use the Add
and/or AddRange
method of the collection.
So, I can omit the setter which also prevents some piece of code from setting the List
back to Nothing
. Of course, code can change the string items to something else or re order them which also might be bad.
To avoid this, you might want to use a Collection Class which implements List(of T)
or Collection(Of T)
. This way your code can provide access to items, limit what can be done, and even validate items added.
See Guidelines for Collections for more tips and information.