PropertyGrid Collections Add/Remove

J

JezB

I have a property grid that works on a set of properties including a
collection. Within the property grid at runtime this expands to the standard
object collection browser, as I would like.

However I was wondering what control the programmer has over this window -
I'd like to remove the Add and Remove buttons in particular, since I only
wish to allow my users to modify elements of the collection, not to
add/remove elements.

I suspect this may be driven by the type of collection it is (mine is a
class that implements CollectionBase), but I suspect that it could be
affected by some embedded attributes, but I dont know which ones to set!
 
P

Palo Mraz

JezB said:
I have a property grid that works on a set of properties including a
collection. Within the property grid at runtime this expands to the standard
object collection browser, as I would like.

However I was wondering what control the programmer has over this window -
I'd like to remove the Add and Remove buttons in particular, since I only
wish to allow my users to modify elements of the collection, not to
add/remove elements.

Officially, you have no control over the window, because it is implemented
as a private nested class within the
Systen.ComponentModel.Design.CollectionEditor class. You can derive a class
from System.ComponentModel.Design.CollectionEditor and mark your collection
with the System.ComponentModel.EditorAttribute attribute:

Public Class ElementCollectionEditor
Inherits System.ComponentModel.Design.CollectionEditor
...

<System.ComponentModel.Editor(GetType(ElementCollectionEditor), _
GetType(System.Drawing.Design.UITypeEditor))> _
Public Class ElementCollection
Inherits CollectionBase
...

The following implementation of the CollectionEditor descendants banks on
the names of the editor form's private button controls, so it is not a
recommended solution (although it works in .NET 1.1):

Public Class ElementCollectionEditor
Inherits System.ComponentModel.Design.CollectionEditor

Public Sub New()
MyBase.New(GetType(ElementCollection))
End Sub

Protected Overrides Function CreateCollectionForm() As
System.ComponentModel.Design.CollectionEditor.CollectionForm
' Here are the *names* of the Button controls we don't want to be shown
/ functional
' in the editor form. WARNING: The names of the controls might be
changed with a new .NET
' Framework release or service pack!
Dim ButtonNamesToHide As New ArrayList(New String() {"removeButton",
"addButton"})

' Call the base class that instantiates it's embedded editor form.
Dim Form As System.ComponentModel.Design.CollectionEditor.CollectionForm
= MyBase.CreateCollectionForm()

' Lookup the buttons and hide them.
For Each Ctl As Control In Form.Controls
If TypeOf Ctl Is Button Then
If ButtonNamesToHide.Contains(Ctl.Name) Then
Ctl.Visible = False
End If
End If
Next
Return Form
End Function

End Class

The following CollectionEditor descendant implements the required
functionality in a more robust (documented) manner, although it is much less
user-friendly. This is because the Add/Remove buttons are accessible on the
form and when the user clicks one of them, she gets an error message:

Public Class ElementCollectionEditor
Inherits System.ComponentModel.Design.CollectionEditor

Public Sub New()
MyBase.New(GetType(ElementCollection))
End Sub

Protected Overrides Function CanRemoveInstance(ByVal value As Object) As
Boolean
Return False
End Function

Protected Overloads Overrides Function CreateInstance(ByVal itemType As
System.Type) As Object
Throw New NotSupportedException("Cannot add new items here.")
End Function
End Class

Or you can opt for a more challenging solution and implement a
System.ComponentModel.Design.CollectionEditor.CollectionForm-derived form.
In that case, however, you'll have to implement the whole editing UI "by
hand".

Hope this helps,

Palo
--------------------------------------------------
http://www.vbinfozine.com
An ordinary VB developer shares
his own successes and failures.
--------------------------------------------------

PS: As a point of interest, I won't able to derive from
System.ComponentModel.Design.CollectionEditor.CollectionForm in VB.NET this
way:

Public Class ElementCollectionEditor2
Inherits System.ComponentModel.Design.CollectionEditor

Public Sub New()
MyBase.New(GetType(ElementCollection))
End Sub

Private Class EditorForm
Inherits System.ComponentModel.Design.CollectionEditor.CollectionForm

End Class
End Class

Although I could easily do that in C#:

public class ElementCollectionEditor :
System.ComponentModel.Design.CollectionEditor
{
public ElementCollectionEditor() : base(typeof(ElementCollection))
{
}

private class EditorForm :
System.ComponentModel.Design.CollectionEditor.CollectionForm
{

public EditorForm(System.ComponentModel.Design.CollectionEditor editor) :
base(editor)
{
}

protected override void OnEditValueChanged()
{
}
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top