A long time ago, in a framework far far away

I have been really busy lately, haven’t had much of a chance to work on some of the WCF post ideas I have sitting in my drafts folder. So I thought a quick simple run through of a little problem I had to resolve the other day might be an o.k. “filler post”.

Note: This is not a problem if you’re using WPF in .NET 3.0 onwards, combo boxes by default expand to the largest element. This problem was encountered on a .NET 2.0 forms control ComboBox.

DotNET Far Far Away

The problem was with long text inside the drop-down list for any given ComboBox in the application. The text would simply be truncated as the drop down panel would only be as wide as the ComboBox.Width. A quick web search uncovered an MSDN article “Building a better ComboBox” from Jan 2005. This article and its download-able code sample solves 95% of the problem. The code supplied is very simple, it has a function which determines the length of the longest text item, then adjusts the drop down panel accordingly. There were some complications/limitations so I spent some more time investigating and playing.

A note on the MSDN article sample code, it’s very straight forward, this specialised combo box extends on the standard combo box. The bulk of the code is to handle the situation where the combo box drop down goes off the edge of the screen.

public class BetterComboBox : ComboBox

This is what I needed to achieve with a 2.0 forms control, demonstrated by this image of the default behavior of a WPF ComboBox control:

WPF Combobox

WPF Combobox

Once the existing combo boxes were modified to be of the new BetterComboBox type, the first problem was with a breakpoint I had set to verify the execution of drop down resizing was never being reached.

This was simply an issue with the order in which events were occurring after a data binding. Upon the assignment of DataSource, the event would fire, but the ComboBox.Items collection was not yet populated. This is actually by design in the framework, that the Items collection is not populated/processed until the object is displayed. It was therefore as simple as refreshing with a call to RefreshList().

This is why the design of the BetterComboBox made use of the HandleCreated event. But my particular implementation required the adjustment occur upon the DataBinding event.

The search for this issue lead me to a few common problems that people are having, and the answer to this StackOverflow question was helpful.

Once the items were showing the next problem I encountered led me down the wrong investigation path my first instinct was to challenge the ability of the improved ComboBox to calculate the appropriate pixel length of my strings. I quickly found a Code Project post (by Pierre Arnaud) about the limitations of:

System.Drawing.Graphics.MeasureString()

There in fact is a limitation, but it wasn’t the cause of my problem, none-the-less an improved measurement function is a welcome addition, so I included it in the customisation.

Once the improved MeasureString() was implemented the actual problem became quickly apparent, that the ToString() method being called on each item was too long. This was due the varying types of elements being bound to the ComboBox data sources. Each class did not have an overload for the ToString() method, so it was the fully qualified class name: Namespace.Something.SomethingElse.ClassName, instead of the actual property that would be bound as the DisplayMemeber.

public override String ToString()
{ return _property; }

So with the ComboBox item’s collection populated, the to-string overload on a few classes, an improved string calculation method, a new appropriate width would successfully be calculated and applied, and the equivalent of an auto-resizing WPF ComboBox was achieved. Fun times in 2.0!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s