I am trying to use the customisable property tab feature of the WinForms PropertyGrid control but it has me beaten. I am specifically trying to use in runtime a PropertyGrid to display object properties, as opposed to trying to create design-time support for a control, though they seem to be applications of similar technology.
This question has me seriously confused. I have attempted to follow several tutorials on the topic and none come to any real solid conclusion.
Literature Review
http://msdn.microsoft.com/en-us/library/aa302334.aspx#vsnetpropbrow_topic05
This article informs the reader that adding property tabs is easily doable and that the code sample is in the included FunkyButton project, that, isn't included anywhere.
http://www.codeproject.com/KB/grid/PropertyGridExWinForms.aspx
This project suggests the only way to use custom property tabs is to extend the base property grid functionality by overriding for instance the GetService() private method. I am quite sure this is not required, and attempted to use its information to create a service provider. It did however enlighten me that the class of the SelectedObject in the property grid needs the class attribute PropertyTabAttribute to be assigned to an extended System.Windows.Forms.PropertyGridInternal.PropertiesTab, which I have created and used.
http://www.dacris.com/blog/2008/01/02/net-how-to-show-events-tab-in-a-property-grid/
This article indicates that the property grid itself requires the tab to be added using the PropertyGrid.PropertyTabs.AddTabType() method. It then reveals that the Site property of the property grid needs to be assigned and then smugly suggests I should already know how to do this: "...you need to set the Site property of the grid to some designer site that you’ve implemented. If you’re hosting your own designers, you should know how to retrieve this."
http://www.syncfusion.com/FAQ/windowsforms/faq_c83c.aspx#q913q
In starting to write this question I found a link to this short article on the topic with included code. This project is more focused it seems on design-time functionality however when I used an instance of their object in a completely vanilla PropertyGrid, it showed up both the Properties tab button and their Custom Tab object. I was able to switch between the associated views effortlessly. However the project seems to suggest now custom attributes are required to distinguish properties between the available views. This article now suggests I ignore the Site definitions, specialised PropertyGrids and service providers, and concentrate on the displayed object itself.
Frustratingly, in modifying this project to closer reflect my application, I moved the operational property grid to a tab control's tab page, wherein it broke the ability for the property grid to show the default Properties tab, thus meaning I could switch to the custom property tab, but never back.
Conclusion
I am at a complete loss. I m开发者_开发技巧ust be close, but of all the avenues I have tried to make this work, perhaps my brain is just fried. What is the key to making property tabs work? Is it:
- The specific class definition of the PropertyGrid.SelectedObject?
- Settings for the property grid itself?
- All about the custom tab definition?
Did the last project described only work because the SelectedObject inherited from UserControl? Does the SelectedObject need to inherit from System.ComponentModel.Component?
If someone could try to clear this all up and provide the most concise possible description of how to make it work, I would be most grateful.
Many thanks.
Here is the code of a custom property tab:
public class CustomTab : PropertyTab
{
private Bitmap _bitmap;
// the tooltip displayed in the grid
public override string TabName
{
get
{
return "CustomTab";
}
}
// the icon displayed in the grid
public override Bitmap Bitmap
{
get
{
if (_bitmap == null)
{
// 1. create a file named "CustomTab.bmp". It must be a 16x16, 8-bit bitmap. Transparency pixel is magenta.
// 2. place it in the project aside this .cs
// 3. configure its build action to "Embedded Resource"
_bitmap = new Bitmap(GetType(), GetType().Name + ".bmp");
}
return _bitmap;
}
}
// TODO: return the descriptor corresponding to the properties you want to show
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object component, Attribute[] attributes)
{
return new PropertyDescriptorCollection(null);
}
public override PropertyDescriptorCollection GetProperties(object component, Attribute[] attributes)
{
return GetProperties(null, component, attributes);
}
}
And here is how you can add it to the property grid:
CustomTab tab = new CustomTab();
grid.PropertyTabs.AddTabType(typeof(CustomTab), PropertyTabScope.Global);
It will display nothing because I don't return any PropertyDescriptor in the GetProperties overload, but this is where you need to defined what descriptor you want to use.
OP Edit:
It appears that the crux of making property tabs work, clearing up the confusion of the information available on the web:
The displayed object need not inherit anything like Control or Component
The PropertyGrid.Site property need not be set
The property grid need not be extended with a custom class
The property grid need not even explicitly add the tab if it is called out in the SelectedObject by an attribute. Of course a persistent tab would need to be added.
Ensure all three PropertiesTab.GetProperties methods are overridden and point to the required method and not the base method.
The tab's bitmap override must actually do something!
The code samples are available now on the MSDN page you referred to in your description. The download link is located between "Summary" and "Contents"; searching for "Codesamples.exe" will probably take you there quickly.
I think the sample code from MSDN is quite sufficient:
On a Form
place a PropertyGrid.
When you compile the sample code, a component appears in the VS Toolbox. Put it on the form and in Properties window, set it to PropertyGrid.SelectedObject
property.
BTW, The actual customization takes place in PropertyTab::GetProperties
.
精彩评论