views:

5975

answers:

4

How do you modify a propertygrid at runtime in every way? I want to be able to add and remove properties and add "dynamic types", what I mean with that is a type that result in a runtime generated dropdown in the propertygrid using a TypeConverter.

I have actually been able to do both those things (add/remove properties and add dynamic type) but only separately not at the same time.

To implement the support to add and remove properties at runtime I used this codeproject article and modified the code a bit to support different types (not just strings).

private System.Windows.Forms.PropertyGrid propertyGrid1;
private CustomClass myProperties = new CustomClass();

public Form1()
{
    InitializeComponent();

    myProperties.Add(new CustomProperty("Name", "Sven", typeof(string), false, true));
    myProperties.Add(new CustomProperty("MyBool", "True", typeof(bool), false, true));
    myProperties.Add(new CustomProperty("CaptionPosition", "Top", typeof(CaptionPosition), false, true));
    myProperties.Add(new CustomProperty("Custom", "", typeof(StatesList), false, true)); //<-- doesn't work
}

/// <summary>
/// CustomClass (Which is binding to property grid)
/// </summary>
public class CustomClass: CollectionBase,ICustomTypeDescriptor
{
    /// <summary>
    /// Add CustomProperty to Collectionbase List
    /// </summary>
    /// <param name="Value"></param>
    public void Add(CustomProperty Value)
    {
     base.List.Add(Value);
    }

    /// <summary>
    /// Remove item from List
    /// </summary>
    /// <param name="Name"></param>
    public void Remove(string Name)
    {
     foreach(CustomProperty prop in base.List)
     {
      if(prop.Name == Name)
      {
       base.List.Remove(prop);
       return;
      }
     }
    }

etc...

public enum CaptionPosition
{
    Top,
    Left
}

My complete solution can be downloaded here.

It works fine when I add strings, bools or enums, but when I try to add a "dynamic type" like StatesList it doesn't work. Does anyone know why and can help me to solve it?

public class StatesList : System.ComponentModel.StringConverter
{
    private string[] _States = { "Alabama", "Alaska", "Arizona", "Arkansas" };

    public override System.ComponentModel.TypeConverter.StandardValuesCollection
    GetStandardValues(ITypeDescriptorContext context)
    {
     return new StandardValuesCollection(_States);
    }

    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
     return true;
    }

    public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
    {
     return true;
    }
}

The method of using a TypeConverter works fine when you don't try to add the property at runtime, for example this code works without any problem, but I want to be able to do both.

Please take a look at my project. Thanks!

+3  A: 

What you do, is adding StatesList (a TypeConverter) as a property.
What you should do, is adding a property with StatesList as its TypeConverter.

Vincent Van Den Berghe
A: 

Ah, of course!

myProperties.Add(new CustomProperty("Custom", "", typeof(States), false, true));

[TypeConverter(typeof(StatesList))]
public class States
{
}

Works like a charm, thank you!

I have updated my project, hope it can be helpful to others, it can be found here.

salle55
You're welcome :)
Vincent Van Den Berghe
+1  A: 

thanks so much, it's just what i needed... :D One question...

How can I define Categories to added property objects?

It seems that only can set the readonly & visible parameters...

Update:

I figured out how this works... =)

The only thing to do is to add the missing members to this class...

/// <summary>
/// Custom property class 
/// </summary>
public class CustomProperty
{
 private string sName = string.Empty;

//Recently added

            private string sCategory = string.Empty;
            private string sDescription = string.Empty;

//Recently added

 private bool bReadOnly = false;
 private bool bVisible = true;
 private object objValue = null;

 public CustomProperty(string sName, string sCategory, string sDescription, object value, Type type, bool bReadOnly, bool bVisible )
 {
  this.sName = sName;
  this.sCategory = sCategory;
  this.sDescription = sDescription;
  this.objValue = value;
  this.type = type;
  this.bReadOnly = bReadOnly;
  this.bVisible = bVisible;
 }

The only thing left is to add getters & setters definitions to the class...

Ariel.

Intrabytes. http://www.intrabytes.com/

A: 

Awesome class/example thanks for sharing salle55

wakaguaka
This should be a comment, not an answer. I see that you are new to stackoverflow, so I won't down vote you, but you should remove this and add it as a comment to the answer/post you're commenting on.
rathkopf