VisualHint's blog
Jun11
Even so Smart FieldPackEditor.Net is still in early beta, I received this week-end a message from a developer working at a big israelian company about the support for Hebrew. Here is an excerpt:
I examined the control and let me tell
you it is very professionally designed
and implemented; way to go! Also the
RTL and Hebrew are working great, a
feat not easily performed by many
professional companies.
Supporting RTL is something new for me and when I designed the component I even hadn't the RTL languages installed on my machine, so this message is a real reward for me. Now I know that the code I produced was not just a shy attempt to see if RTL languages could be handled. They can! And needless to say that I am armed to prepare the RTL support in Smart PropertyGrid.
This developer also sent me some great feedback about the sample application. That's why I fixed some issues over the week-end and republished a new build of the beta package.
Jun03
Time permitting, I sometimes haunt the newsgroups and developer forums to help when the PropertyGrid is involved. Last week, a poster noticed a very subtle issue concerning .Net 1.1 and .Net 2.0 and I decided to know more about it. It appears that the MS PropertyGrid behaves differently in these two versions of .Net. Here is an excerpt of the original request for help:
... When there are multiple objects
selected, and an object property value
is changed in the grid, it is
assigning the same object instance to
each of the selected objects in .Net
1.0, but in .Net 2.0 it is assigning different instances...
The poster also noticed that the culprit was the method SetValue in the MergePropertyDescriptor class. In .Net 1.x it was simply calling PropertyDescriptor.SetValue() with the same new instance for the target properties but in .Net 2.0 it tries first to make a copy (except if we have a value type) by trying different techniques in a method called CopyValue:
- Clones the value if its type implements ICloneable.
- Creates a new copy of the value by calling the constructor of its type if the attached TypeConverter can convert to InstanceDescriptor.
- Creates a new copy of the value by first converting it to a string and then back to an instance of the value type.
- Creates a new copy of the value by serializing it into memory and deserializing it to an instance of the value type if, of course, the type implements ISerializable.
If all tries fail, then the original value is returned.
My thoughts about this issue is that the behavior should be chosen by the developer. In some cases we will want to assign to the target properties distinct instances of the same value and in other cases it makes more sense to assign the same value as if it was a kind of singleton. I tend to prefer what .Net 2.0 does but hey, having the choice is better. I will check if I can offer this choice in SPG, which so far behaves like .Net 1.x.
With the MS PropertyGrid however, I first thought that there was no solution since CopyValue can't be bypassed. But there is one. Implementing this solution for every property would be tedious but for just some of them, when you want to avoid a multiplicity of instances for cost reasons, this can be useful.
Attach a TypeConverter to the type of your property (this won't work if it is attached to the property itself) and override the ConvertTo method so that it will convert to an InstanceDescriptor class. In the class corresponding to your property type, add a static method that will be responsible for supplying a unique instance per possible string representation (it could be done elsewhere like in the TypeConverter itself). In the converter, the InstanceDescriptor will point to this class method.
An example is better than a long explanation so here is a short sample.
Note: this solution won't solve the problem of the original poster unfortunately because for him this happens at designtime and the TypeConverter, quite complex, can't be modified. However, at runtime, it can help in a variety of cases.
May24
To conclude this series of videos, I'll show what can be done with the editor base class. Everything is inside to handle a set of packs and fields which can edit any predetermined data. And since a field is pretty abstract (after all, this is just a rectangle in which we can draw), I'm sure that some nice scenarios will appear after the product is released. Anyway, here is the show:

If there is no last minute drama, the beta will be available next week. If you want to be informed, simply monitor the rss feed or subscribe to the mailing list on the homepage. And of course, feel free to leave some comments here.
May23
In this third video, I show several features of the FieldPackEditor: how flexible it is to bind a DatTimePicker to a data source, how independant field packs in the same editor can be bound to different sources and how the editor can be used in the DataGridView as a perfectly well integrated inplace control. Keep in mind that this editor will also be compatible with Smart PropertyGrid.Net and integrated in place in its value column.

May22
Just before the beta is released I will publish each day of this week a screencast to showcase the main features of Smart FieldPackEditor.Net.
Here is the schedule for this week:
- Tuesday, overview of the FieldpackEditor.
- Wednesday, how to handle the null value.
- Thursday, SFPE, data binding and the DataGridView.
- Friday, multi packs and other editors.
Here is the second screencast of the week. It will show you how SFPE can nullify the underlying value and how it can restore a valid datetime value. Click on the screenshot to launch the movie.

May21
Just before the beta is released I will publish each day of this week a screencast to showcase the main features of Smart FieldPackEditor.Net.
Here is the schedule for this week:
- Tuesday, overview of the FieldpackEditor.
- Wednesday, how to handle the null value.
- Thursday, SFPE, data binding and the DataGridView.
- Friday, multi packs and other editors.
Here is the first screencast of the week. It will show you various general features of the FieldPackEditor derived as a DateTimePicker. Click on the screenshot to launch the movie.

May15
Some days ago I came across a blog showing the trials and tribulations of a developer trying to display and use the standard DateTimePicker in the DataGridView. This story is really typical of all the considerable efforts one have to make in order to get a semi-viable solution. So far I was not even considering touching the DataGridView. It was an unknown component to me and I was not aware of its extensibility to enable custom editors to be used in a cell. After readind this article I jumped on the challenge and decided to integrate Smart FieldPackEditor.Net to the grid.
While SFPE is not even in beta yet, it took me one day to get almost everything running smoothly. By everything I mean:
- Nice insertion of the editor inside a cell. No text shift. Back and Fore colors of the cell used by the editor.
- Correct formatting of the datetime value.
- Null values without a hitch.
- Default keyboard handling.
Some nice features can be added to this list, making the use of this DateTimePicker as smooth as desired:
- Correct field selection when clicking in the editor.
- End of edition forced when closing the dropdown month calendar.
- No fixed width fields, so that the text displayed by the grid is the same than the text displayed by the editor.
- Choice of updown and/or dropdown buttons
- And all the other benefits of the Smart FieldPackEditor…
As early as Tuesday 22, I will publish each day a series of four short screencasts. Here is the schedule:
- Tuesday, overview of the FieldpackEditor.
- Wednesday, how to handle the null value.
- Thursday, SFPE, data binding and the DataGridView.
- Friday, multi packs and other editors.
May10
SPG offers some great ways to build dynamic properties. But often this is a mix of declarative code and dynamic calls to the SPG API to alter the content or the behavior of the grid. However in some cases a complete dynamic solution is needed. For example, some classes may be generated by external tools and it’s impossible or not desired to decorate their properties with attributes. In other contexts, enumerations are not welcome because their content is too ... hardcoded. This article proposes a way to setup a property based on a single integer identifier and a collection of strings to display in the combobox. To make it a little more complex, our combobox will be the unit of another numerical property.
The first thing we need is a new TypeConverter to instruct the grid that we have a set of values to display in a combobox. The two involved methods to override are GetStandardValuesSupported() and GetStandardValues(). Of course we will derive our converter from the Int32Converter. Here is the code:
public class MyIntConverter : Int32Converter
{
public override bool GetStandardValuesSupported(
ITypeDescriptorContext context)
{
return true;
}
public override TypeConverter.StandardValuesCollection
GetStandardValues(ITypeDescriptorContext context)
{
return new StandardValuesCollection( ??? );
}
}
Notice the question marks? This is where you pass the allowed identifiers for your list. There are several ways to get a dynamic list from the TypeConverter. For example you could use the passed context (which in SPG is of type PropertyTypeDescriptorContext) to get the list from the target instance. Here we will create a new attribute that will contain the initial list of integers. The definition of this attribute could be:
public class AllowedIntsAttribute : Attribute
{
public int[] AllowedInts;
public AllowedIntsAttribute(params int[] allowedInts)
{
AllowedInts = allowedInts;
}
}
GetStandardValues can then be written like this:
public override TypeConverter.StandardValuesCollection
GetStandardValues(ITypeDescriptorContext context)
{
PropertyTypeDescriptorContext c = (PropertyTypeDescriptorContext)context;
AllowedIntsAttribute attr = (AllowedIntsAttribute)c.OwnerPropertyEnumerator.Property.
GetValue(PropertyUnitLook.UnitValue).GetAttribute(typeof(AllowedIntsAttribute));
return new StandardValuesCollection(attr.AllowedInts);
}
And here is how all is connected when the grid is filled:
propEnum = AppendManagedProperty(rootEnum, _id++, "Width", typeof(int),
2, "");
propEnum.Property.Look = new PropertyUnitLook();
propEnum.Property.Feel =
GetRegisteredFeel(PropertyGrid.FeelEditUnit);
propEnum.Property.AddManagedValue(PropertyUnitLook.UnitValue, typeof(int),
10, new AllowedIntsAttribute(1,2),
new TypeConverterAttribute(typeof(MyIntConverter)),
new PropertyValueDisplayedAsAttribute(new string[2]
{ "feet", "meters" }));
If the list of identifiers and the list of displayed strings need to be modified, this is possible in SPG. Attributes set dynamically can be accessed with PropertyValue.GetAttribute() and modified if their API enable to do so.
I hope you will appreciate this tutorial. If something is unclear or you need more explanations, please leave a comment.
May09
Just to make it clear that this is the first concern about the MS DateTimePicker, here is a list of famous links:
These articles all try various tricks to create a nullable DateTimePicker. Unfortunately, while the intentions are good, it does always create secondary issues (look into the comments). SFPE will naturally support null values but from a user point of view the path to set null can still be debated. There are two questions:
- How does the user clear the control and hence puts null as the value?
- How does the user inputs a new non null value when the current value is null?
SFPE is flexible so a lot of techniques can be implemented. But before writing here the result of my experiments (I don’t want to influence your ideas), I would like to hear from you in the comments what would be your perfect solution. Don’t limit yourself to what the MS DateTimePicker could do. Forget about it! Just try to imagine the best answers for the two above questions. This “perfect solution” could then be kept for the default mechanism in SFPE.
May06
“How to format a number in the PropertyGrid” is a question that I’m often asked. The following answer is valid for the MS PropertyGrid and for Smart PropertyGrid.Net. Therefore it is not in the SPG documentation.
The following explanation will be given for a Double number. You can easily apply it to a Single or a Decimal.
If your target instance has a Double property, it uses by default the DoubleConverter TypeConverter. Unfortunately (for the present need) this converter uses the “R” format specifier when it converts from a double to a string in the ConvertTo method and the NumberStyles.Float style when it converts back a string to a double in the ConvertFrom method. “R” is called the round-trip format and it does not use the culture set for the application. It’s useful to ensure that a double converted to a string will result in the same original double when converted back.
It means that to solve our problem we must define a new TypeConverter and attach it to our Double property. We can derive it from DoubleConverter but we will override the ConvertTo and ConvertFrom methods. Here is the code of this converter:
public class MyConverter : DoubleConverter
{
public override object ConvertTo(ITypeDescriptorContext context,
CultureInfo culture, object value, Type destinationType)
{
if ((destinationType == typeof(string)) &&
(value.GetType() == typeof(double)))
{
double num = (double)value;
return num.ToString("N", culture.NumberFormat);
}
return base.ConvertTo(context, culture, value, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context,
CultureInfo culture, object value)
{
if (value is string)
return double.Parse(value as string, culture);
return base.ConvertFrom(context, culture, value);
}
}
To set a specific culture usable by the PropertyGrid, you can change the global culture of the application. For example:
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-us");
In SPG.Net you have also another option. You can set a CultureInfo instance per property. If you don’t, it will use the one of the application. This is useful for example to display numbers with various precisions or different currency formats.
protected override void OnPropertyCreated(PropertyCreatedEventArgs e)
{
PropertyValue propertyValue = e.PropertyEnum.Property.Value;
if ((propertyValue != null) && (propertyValue.UnderlyingType ==
typeof(double)))
{
e.PropertyEnum.Property.Value.CultureInfo.NumberFormat.
NumberDecimalDigits = 6;
}
base.OnPropertyCreated(e);
}