Archive for June, 2010

Easy .NET directory helper

Wednesday, June 23rd, 2010

Add this class to your C# project:

public class Directory
{
    private string _path;

    private Directory(string path)
    {
        _path = path;
    }

    public static Directory ApplicationData
    {
        get
        {
            return new Directory(Environment.GetFolderPath(
                Environment.SpecialFolder.ApplicationData));
        }
    }

    public static Directory CommonApplicationData
    {
        get
        {
            return new Directory(Environment.GetFolderPath(
                Environment.SpecialFolder.CommonApplicationData));
        }
    }

    public static Directory operator /(Directory root, string folder)
    {
        return new Directory(Path.Combine(root._path, folder));
    }

    public static implicit operator string(Directory directory)
    {
        return directory._path;
    }
}

Now you can express directories naturally:

string databaseFileName = Directory.ApplicationData / "MichaelLPerry" / "CorrespondenceIM" / "Correspondence.sdf";

I don’t have a good place for code like this to live. What do you do with these kinds of utilities?

Silverlight ComboBox sets SelectedItem when DataContext changes

Friday, June 18th, 2010

I think we can officially call this a bug in Silverlight. Create a master list and a detail view. Bind the SelectedItem of a combo box in the detail view to a reference typed property. Silverlight will set the property to null when you select a new item in the master list.

Try it out below. The list on the left displays the person’s name and preferred phone number. Select “Michael”, and the detail pane shows his phone number and favorite color. Then select “Jenny”. Notice that Michael’s phone number disappeared. Click back on him and see that the phone number is indeed gone.

Favorite color is an enumeration – a value type. Phone number is a class – a reference type. Even though the phone number has a valid Equals and GetHashCode implementation, Silverlight treats it differently. For some reason, it decides it needs to set it to null whenever the DataContext changes.

This behavior is clearly incorrect. The list of items does not contain the value “null”. Even if it did, the user did not select “null”. And as further evidence, WPF does not behave this way. Download the source code, which has been compiled for both Silverlight and WPF. The WPF version of exactly the same source code behaves correctly.

Here’s my solution
Any property bound to SelectedItem should protect itself from a null assignment. In this case:

public PhoneNumber PreferredPhone
{
    get { return _preferredPhone; }
    set
    {
        if (value == null)
            return; 

        _preferredPhone = value;
        RaisePropertyChanged("PreferredPhone");
        RaisePropertyChanged("Display");
    }
}

What if null is a valid value for the property? Then represent null with a stand-in. Perhaps two classes could implement a common IPhoneNumber interface: PhoneNumber and NullPhoneNumber.

It’s a pretty simple workaround, but still an embarrassing bug in Silverlight.