You can override what the property grid sees by having individual classes
implement the ICustomTypeDescriptor interface.
Generally, you cannot change what the property grid sees at runtime without
implementing some scheme based on this interface. This implies that all the
classes you want to examine with the property grid must be custom ones which
is ok if you're creating an application that browses some custom object
model but no good if you want to be able to dynamically modify what's
available in the existing classes.
The application that follows my signature demonstrates how to create a
custom attribute attribute and custom property descriptor that enables
dynamic selection of properties based on a choice made in a master-control
property. This scheme could possibly be adapted to your purposes.
In this example, an attribute (DynamicPropertyFilterAttribute) is created
that enables you to select a property name and a value, The property name is
used to specify a property that contains the trigger condition for showing
or filtering the attributed property and the value is the one used to enable
the attributed property to be seen.
An ICustomTypeDescriptor is employed to enable the
DynamicPropertyFilterAttribute to enable the functionality. In this
instance, the type descriptor implementation does the following;
a.. Gets a list of standard properties from the standard TypeDescriptor
b.. Examines the attributes of the property to see if it contains the
DynamicPropertyFilterAttribute. If it does not, the property is added to the
final list of properties. If it does the property nominated in the attribute
is examined to get it's value. If that value corresponds to one of the
values in the ShowOn property of the attribute then the current property is
added to the list of final poperties, otherwise, it's excluded.
c.. The list of final properties is returned to the PropertyGrid.
The FilterablePropertyBase class is used in the demonstration. Note how the
GetProperties method calls a specialized routine that does the filtering as
explained. Any class based on this class will be able to use the
DynamicPropertyFilterAttribute to specify when and how properties will be
seen. The FilterableDemoClass inherits from this base and demonstrates the
use of the DynamicPropertyFilterAttribute.
--
Bob Powell [MVP]
C#, System.Drawing
The November edition of Well Formed is now available.
Learn how to create Shell Extensions in managed code.
http://www.bobpowell.net/currentissue.htm
Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/gdiplus_faq.htm
Read my Blog at
http://bobpowelldotnet.blogspot.com
----------------------------------------------------------------
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace CustomProps
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.PropertyGrid propertyGrid1;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
this.propertyGrid1.SelectedObject=new FilterableDemoClass();
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.propertyGrid1 = new System.Windows.Forms.PropertyGrid();
this.SuspendLayout();
//
// propertyGrid1
//
this.propertyGrid1.CommandsVisibleIfAvailable = true;
this.propertyGrid1.LargeButtons = false;
this.propertyGrid1.LineColor = System.Drawing.SystemColors.ScrollBar;
this.propertyGrid1.Location = new System.Drawing.Point(0, 8);
this.propertyGrid1.Name = "propertyGrid1";
this.propertyGrid1.Size = new System.Drawing.Size(432, 256);
this.propertyGrid1.TabIndex = 0;
this.propertyGrid1.Text = "propertyGrid1";
this.propertyGrid1.ViewBackColor = System.Drawing.SystemColors.Window;
this.propertyGrid1.ViewForeColor =
System.Drawing.SystemColors.WindowText;
this.propertyGrid1.PropertyValueChanged += new
System.Windows.Forms.PropertyValueChangedEventHandler(this.propertyGrid1_Pro
pertyValueChanged);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(432, 266);
this.Controls.Add(this.propertyGrid1);
this.FormBorderStyle =
System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void Form1_Load(object sender, System.EventArgs e)
{
this.propertyGrid1.SelectedObject=new FilterableDemoClass();
}
private void propertyGrid1_PropertyValueChanged(object s,
System.Windows.Forms.PropertyValueChangedEventArgs e)
{
this.propertyGrid1.Refresh();
}
}
//////////////////////////////////////////////////////////
//Dynamic property filtering.
[
AttributeUsage(AttributeTargets.Property, Inherited=true)
]
class DynamicPropertyFilterAttribute : Attribute
{
string _propertyName;
public string PropertyName
{
get{return _propertyName;}
}
string _showOn;
public string ShowOn
{
get{return _showOn;}
}
public DynamicPropertyFilterAttribute(string propName, string value)
{
_propertyName=propName;
_showOn=value;
}
}
public class FilterablePropertyBase : ICustomTypeDescriptor
{
protected PropertyDescriptorCollection GetFilteredProperties(Attribute[]
attributes)
{
PropertyDescriptorCollection pdc =
TypeDescriptor.GetProperties(this,attributes,true);
PropertyDescriptorCollection finalProps = new
PropertyDescriptorCollection(new PropertyDescriptor[0]);
foreach(PropertyDescriptor pd in pdc)
{
bool include=false;
bool Dynamic=false;
foreach(Attribute a in pd.Attributes)
{
if(a is DynamicPropertyFilterAttribute)
{
Dynamic=true;
DynamicPropertyFilterAttribute
dpf=(DynamicPropertyFilterAttribute)a;
PropertyDescriptor temp=pdc[dpf.PropertyName];
if(dpf.ShowOn.IndexOf(temp.GetValue(this).ToString())>-1)
{
include=true;
}
}
}
if(!Dynamic || include)
finalProps.Add(pd);
}
return finalProps;
}
#region ICustomTypeDescriptor Members
public TypeConverter GetConverter()
{
return TypeDescriptor.GetConverter(this,true);
}
public EventDescriptorCollection GetEvents(Attribute[] attributes)
{
return TypeDescriptor.GetEvents(this,attributes,true);
}
EventDescriptorCollection
System.ComponentModel.ICustomTypeDescriptor.GetEvents()
{
return TypeDescriptor.GetEvents(this,true);
}
public string GetComponentName()
{
return TypeDescriptor.GetComponentName(this,true);
}
public object GetPropertyOwner(PropertyDescriptor pd)
{
return this;
}
public AttributeCollection GetAttributes()
{
return TypeDescriptor.GetAttributes(this,true);
}
public PropertyDescriptorCollection GetProperties(Attribute[]
attributes)
{
return GetFilteredProperties(attributes);
}
PropertyDescriptorCollection
System.ComponentModel.ICustomTypeDescriptor.GetProperties()
{
return GetFilteredProperties(new Attribute[0]);
}
public object GetEditor(Type editorBaseType)
{
return TypeDescriptor.GetEditor(this,editorBaseType,true);
}
public PropertyDescriptor GetDefaultProperty()
{
return TypeDescriptor.GetDefaultProperty(this,true);
}
public EventDescriptor GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(this,true);
}
public string GetClassName()
{
return TypeDescriptor.GetClassName(this,true);
}
#endregion
}
class FilterableDemoClass : FilterablePropertyBase
{
public enum FilterSelect
{
One,
Some,
All
}
FilterSelect _chooseOne=FilterSelect.One;
public FilterSelect ChooseOne
{
get{return _chooseOne;}
set{_chooseOne=value;}
}
string _firstProperty;
[
DynamicPropertyFilter("ChooseOne", "One,All")
]
public string FirstProperty
{
get{return _firstProperty;}
set{_firstProperty=value;}
}
string _secondProperty;
[
DynamicPropertyFilter("ChooseOne", "Some,All")
]
public string SecondProperty
{
get{return _secondProperty;}
set{_secondProperty=value;}
}
string _thirdProperty;
[
DynamicPropertyFilter("ChooseOne", "Some,All")
]
public string ThirdProperty
{
get{return _thirdProperty;}
set{_thirdProperty=value;}
}
string _fourthProperty;
[
DynamicPropertyFilter("ChooseOne", "All")
]
public string FourthProperty
{
get{return _fourthProperty;}
set{_fourthProperty=value;}
}
}
}
----------------------------------------------------------------
JezB said:
If I base a PropertyGrid control on a class, I have a certain amount of
control on which public properties exposed by the class appear in the
control via the [Browsable(true)] attribute of the property. I need to have
a finer degree of control since (based upon a number of factors) I may
either want to show or hide certain properties, and do not want to
create
a
separate class for all possible combinations. Can this be done? Can I access
the control's set of properties at run-time and turn them on/off ?