Tijmen 03:10, 8 August 2009

At my current project we needed a quick sort of throw away app that was going to be used by a small group of people. Without going into much details the app basically is a planning and analysis module for the allocation of employees to divisions.

Since development speed is crucial we decided to work with Linq2sql and winforms. No need for all sorts of layers; just get it done.

 

We needed to fill a combobox with values. This should be trivial, but was a bit more trouble than expected. I ended up using the excellent description found here. Basically all you need to do is:

var comboBox = new ComboBox();
var choices = new Dictionary<string, string>();
choices["A"] = "Arthur";
choices["F"] = "Ford";
choices["T"] = "Trillian";
choices["Z"] = "Zaphod";
comboBox.DataSource = new BindingSource(choices, null);
comboBox.DisplayMember = "Value";
comboBox.ValueMember = "Key"; 

 

Notice the clever use of new BindingSource(choices, null);

 

Nothing complex here, but this is static and I wanted to get the values from the db. Next to that it would be nice if we could have some sort of generic function that could take a type of TEntity (table) and some hints to which properties in TEntity it needed as Key and Value.

I ended up with this:

public interface IComboBoxHelper
{
    void SetComboBoxContent<TEntity, TKey, TValue>(
            Func<TEntity, TKey> key,
            Func<TEntity, TValue> value, 
            ComboBox comboBox)
        where TEntity : class;
}

Usage becomes pretty straightforward: register the IComboBoxHelper and it's implementation to the Dependency injection container. Add a constructor dependency and use the helper variable:

comboBoxHelper.SetComboBoxContent<Divisie, int, string>(s=> s.Divisie_PK, s=> s.Divisienaam, comboBox);

The implementation of the IComboBoxHelper takes a datacontext and is responsible for looking up the required entity.

Let's have a look at the actual implementation:

public class ComboBoxHelper : IComboBoxHelper
{
    readonly HRDataContext dataContext;

    public ComboBoxHelper(HRDataContext dataContext)
    {
        this.dataContext = dataContext;
    }
   
    public void SetComboBoxContent<TEntity, TKey, TValue>(
            Func<TEntity, TKey> key,
            Func<TEntity, TValue> value, 
            ComboBox comboBox)
        where TEntity : class
    {
        Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>();

        IQueryable<TEntity> entities = dataContext.GetTable<TEntity>().Select(s => s);
        entities.ForEach(s => dictionary.Add(key(s), value(s)));
        var source = new BindingSource(dictionary, null);
        comboBox.DataSource = source;
        comboBox.DisplayMember = "Value";
        comboBox.ValueMember = "Key";
    }
}

Nothing too complicated, but the use of Func's to get to the properties in the required Entity is pretty nice.

Technorati Tags: ,,