I like PropertyGrid control.
It's really neat.
But it is documented very poorly on MSDN. Once again, .NET Reflector saves the day.
Visual Studio has PropertyGrid controls all over the place, and somehow they got the SelectedObject to show commands on the PropertyGrid command panel.
MSDN does not describe how they did that
Here: "PropertyGrid Class (System.Windows.Forms)" http://msdn.microsoft.com/en-us/library/system.windows.forms.propertygrid.aspx (see CommandsVisible property)
Or Here: "Getting the Most Out of the .NET Framework PropertyGrid Control" http://msdn.microsoft.com/en-us/library/aa302326.aspx
Here I will describe how to get those command links to appear.
See also "why I hate iserviceprovider", (posted feb 20, 2009) on beefycode.com http://beefycode.com/
PropertyGrid control is a black box with a chain of undocumented dependency injection thingies.
A better implementation IMO would have been to expose command links in a PropertyGrid control when the object referenced in PropertyGrid.SelectedObject implements IMenuCommandService. |
Services Services
Command links appear in the PropertyGrid when all these conditions are met:
- PropertyGrid.SelectedObject is set to the instance of an object that implements the IComponent interface
- The IComponent implementation has a value for ISite
- ISite is a service provider, it must provide
- an instance of IMenuCommandService (i.e. your ISite implementation should have a ServiceContainer, and in that ServiceContainer is an IMenuCommandService)
- OR it must provide an instance of IDesignerHost
- an instance of IMenuCommandService (i.e. your ISite implementation should have a ServiceContainer, and in that ServiceContainer is an IMenuCommandService)
- If you are using IMenuCommandService (3.a) then add commands to the IMenuCommandService using AddVerb(new DesignerVerb(…))
The PropertyGrid gets it's commands from IMenuCommandService.Verbs
The DesignerVerb is pretty straight forwards actually, the Text will show up as the link, and clicking on the command link will invoke the Handler. - If you are using IDesignerHost (3.b) …
… yeah … well … good luck with that.
Anyway, according to .NET Reflector, your IDesignerHost will have its GetDesigner(component) method called where component is the selected object instance.
It needs to return an IDesigner instance.
The PropertyGrid gets its commands from IDesigner.Verbs. It needs to be a collection of DesignerVerb instances.
This comment has been removed by the author.
ReplyDeleteThis is the simplest way to do this:
ReplyDeletePublic Class GridObject
Implements IComponent
Public Event Disposed(sender As Object, e As System.EventArgs) Implements System.ComponentModel.IComponent.Disposed
Private disposedValue As Boolean
Private _site As ISite
Public Property Site As System.ComponentModel.ISite Implements System.ComponentModel.IComponent.Site
Get
If Me._site Is Nothing Then
Me._site = New GridObjectSite()
End If
Return Me._site
End Get
Set(value As System.ComponentModel.ISite)
Me._site = value
End Set
End Property
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
End If
End If
Me.disposedValue = True
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Me.Dispose(True)
GC.SuppressFinalize(Me)
End Sub
End Class
Public Class GridObjectSite
Implements ISite
Implements IMenuCommandService
Private _verbs As DesignerVerbCollection
Public ReadOnly Property Verbs As System.ComponentModel.Design.DesignerVerbCollection Implements System.ComponentModel.Design.IMenuCommandService.Verbs
Get
If Me._verbs Is Nothing Then
Me._verbs.Add(New DesignerVerb("TEST", Nothing))
End If
Return Me._verbs
End Get
End Property
Public Function GetService(serviceType As System.Type) As Object Implements System.IServiceProvider.GetService
If serviceType Is GetType(IMenuCommandService) Then
Return Me
End If
Return Nothing
End Function
'//all the other methods, you dont need to do anything with
End Class
Add custom properties to PropertyGrid control
ReplyDelete