Showing posts with label How To. Show all posts
Showing posts with label How To. Show all posts

Sunday, June 20, 2010

Bypassing the Property Grid's Sort Order

While working on a programming project one of the things I wanted to include was the ability to list out the values in the collection in the same way the array lists its items.

Normally, the collection displays an ellipsis button, allowing the user to manipulate the collection, but does not allow the user to expand the list of items like an array does. I figured this would be very simple to add. The .NET framework provides a base class for an object called a TypeConverter. The TypeConverter allows objects of various types to be translated to and from various representations.


Beyond that, the TypeConverter can supply a list of standard values (Enumerators use this, which allows the property grid to display a drop-down list containing the various valid values.) The TypeConverter can also supply an editor class for the type (You see this in form designers all the time, the font dialog, the drop-down for colors, the drop-down for for docking, etc...) Finally, the type converter can also supply a list of properties that the object can display as child properties of a property. It is this that I will focus on:

public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return true;
}
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
List<String> lst = (List<String>)value;
ListItemDescriptor[] props = new ListItemDescriptor[lst.Count];

for (int i = 0; i < lst.Count; i++)
props[i] = new ListItemDescriptor(i);

return new PropertyDescriptorCollection(props);
}

The above code demonstrates how the properties are provided by the TypeDescriptor. Using the above code results in the following list in the grid:
Far from optimal for dealing with a list of items. The list is sorted alphabetically. But arrays seem to sort by index. That was what I wanted, so I began spelunking through the reference source code of the .NET framework. Examining the Array code and ArrayConverter code revealed nothing. They were doing essentially what I was doing. I then explored the grid. It appears the PropertyGrid itself considers an array a special case and sorts the items by index. That is no use to me. 
Using the sort method of the PropertyDescriptorCollection object does nothing, since the grid will always override it with the user's sort preference. So, how to sort the items by index?
The secret is in the property descriptor collection. Replacing the return statement above with the following:


return new ListPropertyDescriptorCollection(props);

The following listing shows the ListPropertyDescriptorCollection class that does the magic:
private class ListPropertyDescriptorCollection : PropertyDescriptorCollection
{ 
    public ListPropertyDescriptorCollection(PropertyDescriptor[] props)
    : base(props)
   {
  
    }

    public override PropertyDescriptorCollection Sort
    (System.Collections.IComparer comparer) 
   { 
        if (comparer.GetType().Name == "DisplayNameSortComparer") 
       { 
            ListItemDescriptor.ListItemDescriptorSortComparer comp = 
             new ListItemDescriptor.ListItemDescriptorSortComparer(); 
            return Sort(comp); 
       } 
         else 
       { 
            return base.Sort(comparer);
       }
    }
 }


The code that performs the trick should be rather self-evident:

ListItemDescriptor.ListItemDescriptorSortComparer comp = new ListItemDescriptor.ListItemDescriptorSortComparer();
 return Sort(comp);

Two lines of code in this function do all that is necessary to force the numeric sort. The comparer in this case compares the indicies of the descriptors, causing the sort function to sort by the numeric index. This completely replaces any sort function used with the desired sort, thereby forcing a sort by index. 


 

Sunday, January 24, 2010

Growing Crystals = Fail

Lets say for a moment you and your kids decide to do a science experiment. You want to grow crystals. Great! There are lots of resources out there that tell you how to do all sorts of crystals. One of which is salt. Ordinary Table Salt.



So you and your family set out to grow beautiful cubic crystals. You heat up some water, and dump tons of salt in the water until nothing will dissolve anymore. You pour your supersaturated solution of good old sodium chloride into a cup, and dangle a string in the cup. You wait..... and wait... and wait. A week passes, and you have nothing to show for it at all. The sugar crystals came out great, but sugar is so pedestrian. The cubic salt crystals would have been so much better, but it's a total no-go. What happened?


I've wondered about this since I was a kid and tried to grow sugar crystals and salt crystals. Sugar did fine, but I really wanted to see the cool cubes of salt. It didn't work. Recently, I tried to grow salt again, prompted by seeing a huge crystal of salt on the show "How It's Made." So, I set about growing salt, being careful to make sure the pan was clean, the glass was clean, and everything was ideal, even filtering the undissolved crystals through a coffee filter. After about a week, I checked on my project. The results were disappointing to say the least. A few microscopic crystals formed near the surface of the water, and a cauliflower-like mass formed around the pencil suspending the string. Something was seriously wrong. A quick look at the ingredients gives a clue: There are two impurities in the salt; an iodine compound (a necessary nutritional supplement. Most table salt is iodized) and an anti-caking agent. I suspect this is more the culprit than the iodine itself, since the iodine needed is relatively small in relation to the salt. Not only that, but the purpose of the anti-caking compound is to interfere with the salt's ability to build a crystal lattice.





In fact, most salts in the store (even those without the iodine) have some sort of anti-caking agent. Most, but not all. Salt used in the canning process is completely pure. This can be found near the canning jars and lids. After preparing a new solution using this salt, the difference was very apparent. The solution as it cooled formed a film of crystals at the surface, and seemed to be brimming with glinting, brilliant "diamond dust" I filtered the solution and hung my string in this new solution, and set it in a place where it will be relatively undisturbed. Within minutes tiny needles began to form in the water, and sink to the bottom, in a couple hours crystals were already starting to form on the string. Success at last!



The next stage will be to take an ideal specimen from the crystals formed by the solution and attach it to some nylon fishing line to use as a seed for the final large crystal. Stay tuned!