What Control is Microsoft Using Here?

A

Anthony Bouch

Can anyone tell me what type of control Microsoft is using on the project
properties pages in Visual Studio .Net? To see it right click on a project
and select Properties. The control I'm interested in is the one in the
middle displaying the Application, Project, and Wrapper Assembly data.

It appears to be the perfect combination of a treeview with a datagrid. Not
sure. I'm assuming that Visual Studio .Net was written in C++ and so it
might be an in-house control that Microsoft uses internally.

I like the expanding section dividers and then editable grid below each
section. At first I was thinking that it might be multiple data grids - but
when you move the column divider in the middle all of the sections change
width. Not sure what this is really.

I'm building a configuration editor that will read the configuration
sections of an App.config, or Web.config XML file.

Any tips or suggestions on how I could build (or find) a control that can do
this would be great.

Tony
 
S

ShadowChaser

It's called the "PropertyGrid".

To use it, go to your toolbox, right click, select "Add/Remove Items", then
scrol down until you see the option titled "PropertyGrid" in the
System.Windows.Forms namespace. Check it, press OK, and voila, just drag and
drop it into your form :)

It's a VERY powerfull control - you can assign any object to it and it will
let you edit all of it's properties, just like in the designer!

-Eric B
 
H

Herfried K. Wagner [MVP]

* "Anthony Bouch said:
Can anyone tell me what type of control Microsoft is using on the project
properties pages in Visual Studio .Net? To see it right click on a project
and select Properties. The control I'm interested in is the one in the
middle displaying the Application, Project, and Wrapper Assembly data.

'System.Windows.Forms.PropertyGrid'
<http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemwindowsformspropertygridclasstopic.asp>

Sample:

<http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/usingpropgrid.asp>
 
A

Anthony Bouch

Cool - thanks a bunch to both of you.

ShadowChaser said:
It's called the "PropertyGrid".

To use it, go to your toolbox, right click, select "Add/Remove Items", then
scrol down until you see the option titled "PropertyGrid" in the
System.Windows.Forms namespace. Check it, press OK, and voila, just drag and
drop it into your form :)

It's a VERY powerfull control - you can assign any object to it and it will
let you edit all of it's properties, just like in the designer!

-Eric B

can
 
A

Anthony Bouch

Knowing that it was a PropertyGrid was the first step.

Being able to create a custom class from the custom configuration sections
that we use in our Web.config and App.Config files was the next task (We
don't only use appsettings - we have two specific custom configuration
sections). I tried to find the original posting in order to thank Venu
Madhav for the posting below. Hopefully he won't mind the reposting here.

Venu Madhav's CustomClass which let's you add properties to the class at
runtime - which in turn can then be used to populate the gird. I add the
properties to the class using an XmlDocument to read the nodes and
attributes for our custom configuration sections. Very cool.

using System;
using System.Management;
using System.Data;
using System.ComponentModel;
using System.Management.Instrumentation;
using System.Collections;

namespace PropGrid
{
/// <summary>
/// CustomClass implements ICustomTypeDescriptor and derives
ExpandableObjectConverter
/// This class can be instantiated and properties to this class can
be added to it dynamically.
/// Use AddProperty(string propName, System.Type propType, string
propDesc, object propValue) to add a property.
/// </summary>

[TypeConverter(typeof(ExpandableObjectConverter))]
class CustomClass : Component, ICustomTypeDescriptor
{
/// <summary>
/// Constructor of CustomClass which initializes the DataTable.
/// </summary>
public CustomClass()
{
myTable = new DataTable("Properties");
categoryList = new ArrayList();
dataTypeList = new ArrayList();
}

/// <summary>
/// Adds a property into the CustomClass.
/// </summary>
/// <param name="propName">Name of the property that needs to be
added.</param>
/// <param name="propType">DataType of the property that needs to be
added.</param>
/// <param name="propDesc">Description of the property that needs to
be added.</param>
/// <param name="propValue">Value of the property that needs to be
added.</param>
public void AddProperty(string propName, System.Type propType,
string propDesc, object propValue, string categoryItem, bool isArray)
{
DataColumn myDC = new DataColumn(propName, propType);
myDC.Caption = propDesc;

myTable.Columns.Add(myDC);

if(myTable.Rows.Count == 0)
{
DataRow myDR = myTable.NewRow();
myTable.Rows.Add(myDR);
}

this[propName] = propValue;

categoryList.Add(categoryItem);
dataTypeList.Add(isArray);
}

/// <summary>
/// Adds a property into the CustomClass from the given
PropertyData.
/// </summary>
/// <param name="myPD">The PropertyData which needs to needs to be
added to the CustomClass.</param>
public void AddProperty(PropertyData myPD, string categoryItem, bool
isArray)
{
DataColumn myDC = new DataColumn(myPD.Name, myPD.GetType());
myDC.Caption = myPD.Name;

myTable.Columns.Add(myDC);

if(myTable.Rows.Count == 0)
{
DataRow myDR = myTable.NewRow();
myTable.Rows.Add(myDR);
}

this[myPD.Name] = myPD.Value;

categoryList.Add(categoryItem);
dataTypeList.Add(isArray);
}

ArrayList categoryList;
ArrayList dataTypeList;

public object this[string name]
{
get
{
return myTable.Rows[0][name];
}
set
{
myTable.Rows[0][name] = value;
}
}

private DataTable myTable;
private PropertyDescriptorCollection privateProp;

/// <summary>
///
/// </summary>
/// <returns></returns>
public string GetClassName()
{
return(TypeDescriptor.GetClassName(this, true));
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public AttributeCollection GetAttributes()
{
return(TypeDescriptor.GetAttributes(this, true));
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public string GetComponentName()
{
return(TypeDescriptor.GetComponentName(this, true));
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public TypeConverter GetConverter()
{
return(TypeDescriptor.GetConverter(this, true));
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public EventDescriptor GetDefaultEvent()
{
return(TypeDescriptor.GetDefaultEvent(this, true));
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public PropertyDescriptor GetDefaultProperty()
{
PropertyDescriptorCollection myProps = GetAllProperties();

if(myProps.Count > 0)
return(myProps[0]);
else
return(null);
}

/// <summary>
///
/// </summary>
/// <param name="editorBaseType"></param>
/// <returns></returns>
public object GetEditor(Type editorBaseType)
{
return(TypeDescriptor.GetEditor(this, editorBaseType,true));
}

/// <summary>
///
/// </summary>
/// <param name="attributes"></param>
/// <returns></returns>
public EventDescriptorCollection GetEvents(Attribute[] attributes)
{
return(TypeDescriptor.GetEvents(this, attributes, true));
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public EventDescriptorCollection GetEvents()
{
return(TypeDescriptor.GetEvents(this, true));
}

/// <summary>
///
/// </summary>
/// <param name="attributes"></param>
/// <returns></returns>
public PropertyDescriptorCollection GetProperties(Attribute[]
attributes)
{
return(GetAllProperties());
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public PropertyDescriptorCollection GetProperties()
{
return(GetAllProperties());
}

/// <summary>
///
/// </summary>
/// <param name="pd"></param>
/// <returns></returns>
public object GetPropertyOwner(PropertyDescriptor pd)
{
return(this);
}

private PropertyDescriptorCollection GetAllProperties()
{
if(privateProp == null)
{
privateProp = new PropertyDescriptorCollection(new
PropertyDescriptor[]{});
int i = 0;

foreach(DataColumn myDC in myTable.Columns)
{
AddNewColumn myANC = new
AddNewColumn(myDC,
categoryList.ToString(), (bool)dataTypeList);
privateProp.Add(myANC);
PropertyDescriptorCollection myPDC =
myANC.GetChildProperties();
i++;
}
}
return privateProp;
}

public class AddNewColumn : PropertyDescriptor
{
private DataColumn myDC;
private string insertCategory;
private Type myType;
private bool isExpandable;

public AddNewColumn(DataColumn thisDC, string insCat, bool
expandable):base(thisDC.ColumnName, new Attribute[]{})
{
myDC = thisDC;
myType = thisDC.GetType();
insertCategory = insCat;
isExpandable = expandable;
}

public override System.Type ComponentType
{
get
{
return null;
}
}

public override string Category
{
get
{
return insertCategory;
}
}

public override bool IsReadOnly
{
get
{
return myDC.ReadOnly;
}
}

public override System.Type PropertyType
{
get
{
if(isExpandable)
return myType;
else
return myDC.DataType;
}
}

public override bool CanResetValue ( object component )
{
return true;
}

public override object GetValue ( object component )
{
CustomClass myCC = component as CustomClass;

if(myCC != null)
return myCC[myDC.ColumnName];
else
throw new ArgumentException ( "Component is not derived
from
DynamicProperties" );
}

public override void SetValue ( object component , object
value )
{
CustomClass myCC = component as CustomClass;

if(myCC != null)
myCC[myDC.ColumnName] = value;
else
throw new ArgumentException ( "Component is not derived
from
DynamicProperties" );
}

public override void ResetValue ( object component )
{
CustomClass myCC = component as CustomClass;

if(myCC != null)
myCC[myDC.ColumnName] = null;
else
throw new ArgumentException ( "Component is not derived
from
DynamicProperties" );
}

public override bool ShouldSerializeValue ( object component )
{
return false;
}

public override string Description
{
get
{
return myDC.Caption;
}
}
}
}
}
 

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