
This post is to demo on how to implement a standard values type converter for a String property. With this type converter, the property will be shown on property browser as a drop-down list of standard defined values and also accept custom value that being keyed in by user.
Let’s say there is a class Sample (sample.cs) that has 2 properties Name and Occupation. We would like to make a standard values list for the occupation later. Below is step-by-step of the implementation. You may also get full source code here.
public class Sample
{
private String name = String.Empty;
private String occupation = String.Empty;
public Sample()
{
this.name = "Your Name";
this.occupation = "Teacher";
}
public String Name
{
get { return this.name; }
set { this.name = value; }
}
public String Occupation
{
get { return this.occupation; }
set { this.occupation = value; }
}
public override string ToString()
{
return String.Format("{0}@{1}", this.name, this.occupation);
}
}
1. To implement a simple type converter that give a drop-down list of standard values in a property browser, first we define a class that derives from System.ComponentModel.TypeConverter.
public class StringListConverter : TypeConverter
{
}
2. Then we need a list to hold the standard values. And we also add those standard values into the list in the constructor.
private List lstStandardValues;
public StringListConverter()
{
lstStandardValues = new List();
lstStandardValues.Add("Designer");
lstStandardValues.Add("Teacher");
lstStandardValues.Add("Engineer");
lstStandardValues.Sort();
}
3. We need to indicate that the converter supports for a list of standard values, as well as return the standard values collection when it requested.
// Indicates this converter provides a list of standard values.
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
// Returns a starndard values object.
public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
StandardValuesCollection svc = new StandardValuesCollection(lstStandardValues);
return svc;
}
4. In order to let user to key in their custom value instead of selecting from the standard values, we need to put indication that shows the type converter support for conversion from a custom value (normally it is a string).
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(String))
return true;
else
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value.GetType() == typeof(String))
{
String newVal = (String)value;
if (!lstStandardValues.Contains(newVal))
{
lstStandardValues.Add(newVal);
lstStandardValues.Sort();
}
return newVal;
}
else
return base.ConvertFrom(context, culture, value);
}
5. Finally, we put an attribute to the Occupation property to indicate that it has a type converter of StringListConverter.
[TypeConverter(typeof(StringListConverter))]
public String Occupation
{
get { return this.occupation; }
set { this.occupation = value; }
}
Here is the full source code of Sample.cs and StringListConverter.cs:
public class Sample
{
private String name = String.Empty;
private String occupation = String.Empty;
public Sample()
{
this.name = "Your Name";
this.occupation = "Teacher";
}
public String Name
{
get { return this.name; }
set { this.name = value; }
}
[TypeConverter(typeof(StringListConverter))]
public String Occupation
{
get { return this.occupation; }
set { this.occupation = value; }
}
public override string ToString()
{
return String.Format("{0}@{1}", this.name, this.occupation);
}
}
public class StringListConverter : TypeConverter
{
private List lstStandardValues;
public StringListConverter()
{
lstStandardValues = new List();
lstStandardValues.Add("Designer");
lstStandardValues.Add("Teacher");
lstStandardValues.Add("Engineer");
lstStandardValues.Sort();
}
// Indicates this converter provides a list of standard values.
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
// Returns a starndard values object.
public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
StandardValuesCollection svc = new StandardValuesCollection(lstStandardValues);
return svc;
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(String))
return true;
else
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value.GetType() == typeof(String))
{
String newVal = (String)value;
if (!lstStandardValues.Contains(newVal))
{
lstStandardValues.Add(newVal);
lstStandardValues.Sort();
}
return newVal;
}
else
return base.ConvertFrom(context, culture, value);
}
}
Thank you! This has saved me hours of effort!