Reputation: 21
I am trying to use property grid for displaying data. I have to write StringConverters for my predefined string constants so that they can be shown on a combo box.
Consider a list of colors and another list of angles 0,90,180,270. There are many such lists I want to display on the grid.
I am writing new classes deriving from StringConverters and overriding GetStandardValues
class AngleConverter : StringConverter
{
string[] Units = { "0", "90", "180","270" };
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
return new StandardValuesCollection(Units);
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return true;
}
}
Class UnitConverter : ... Same code except change in the string array. I use this Class before the property like [TypeConverter(typeof(AngleConverter))]. I need to create new class if I want to add a string list to be displayed in a list box on the grid.
Is there a generic way of doing this without creating new classes everytime.
Thanks --Hari
Upvotes: 2
Views: 3744
Reputation: 4745
Well, I would write another attribute to contain the standard values. Then your StringConverter derived class would simply detect this attribute and grab the values from there:
private string _unit = "m/s";
[PropertyValueDisplayedAs(new string[] { "m/s", "km/h" })]
[TypeConverter(typeof(MyStringConverter))]
public string ConstraintString
{
get { return _unit; }
set { _unit = value; }
}
Your converter would look like:
public class MyStringConverter : StringConverter
{
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
PropertyValueDisplayedAsAttribute attr = (PropertyValueDisplayedAsAttribute)context.PropertyDescriptor.Attributes[typeof(PropertyValueDisplayedAsAttribute)];
return new StandardValuesCollection(attr.DisplayedValues);
}
}
Of course you could cache the standard values in the converter to avoid requesting them if they don't change per property. I'll let you write PropertyValueDisplayedAsAttribute wich is a very simple attribute holding a collection.
Upvotes: 2
Reputation: 2417
Alternatively you can use ObjectDataProvider.
Of course, if I understand correctly what you want.
See also: Binding to enumeration.
Upvotes: 0
Reputation: 27608
EDIT: According to Thomas Lycken's answer at this link, it might help if your properties are enums...
I don't know if you can avoid writing new classes or not. I am not familiar enough with what you are doing to know if there is a significantly better or easier way or not. Having said that, you could shorten your class somewhat by making an abstract base class something like this:
class MyBaseStringConverter : StringConverter
{
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
//Call the abstract GetValues function here.
return new StandardValuesCollection(GetValues());
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return true;
}
protected abstract string [] GetValues();
}
public AngleConverter : MyBaseStringConverter
{
protected override string [] GetValues()
{
return new string [] { "0", "90", "180", "270" };
}
}
public ColorConverter : MyBaseStringConverter
{
protected override string [] GetValues()
{
return new string [] { "Red", "Green", "Blue" };
}
}
Upvotes: 2