Tonight I spent sometime playing with checkboxes! (Yes I know, I should get out more…) Here’s what I learned. Let’s say you’ve got a form with a group of checkboxes. That might look something like this:

Yes I know this is one of the most impressive forms you’ve ever seen. But let’s say that you’ve got a group of checkboxes and you need to capture which checkboxes are selected. You could wire up an event handler for the “Save” button’s click event, then write up a bunch of if-else statements to see which checkboxes are checked and yada yada…
Your code might look something like…
if ( checkBox1.Checked ) {}
if ( checkBox2.Checked ) {}
if ( checkBox3.Checked ) {}
I didn’t like this so I wanted to come up with a different way, something that’s not so smelly. Here’s what I came up with. The ICheckBoxGroup
internal interface ICheckBoxGroup< T > {
void Add( CheckBox checkbox, T item );
IEnumerable< T > GetAllEnabled( );
IEnumerable< T > GetAllThatSatisfies( Predicate< CheckBox > condition );
}
This allows me to bind a full blown domain object to each checkbox. In this example I’m binding a Sport to each checkbox.
ICheckBoxGroup< ISport > group = new CheckBoxGroup< ISport >( );
group.Add( checkBox1, Sport.Hockey );
group.Add( checkBox2, Sport.BasketBall );
group.Add( checkBox3, Sport.FootBall );
group.Add( checkBox4, Sport.Golf );
group.Add( checkBox5, Sport.Tennis );
When the “Save” button is clicked I’m asking for all the Sports that have been selected like this…
StringBuilder builder = new StringBuilder( );
foreach ( ISport employee in group.GetAllEnabled( ) ) {
builder.AppendFormat( "{0}{1}", employee, Environment.NewLine );
}
MessageBox.Show( builder.ToString( ) );
The “GetAllEnabled” method is returning an IEnumerable
public class CheckBoxGroup< T > : ICheckBoxGroup< T > {
public CheckBoxGroup( ) {
_checkboxes = new List< CheckBox >( );
}
public void Add( CheckBox checkbox, T item ) {
checkbox.Tag = item;
checkbox.Text = item.ToString( );
_checkboxes.Add( checkbox );
}
public IEnumerable< T > GetAllEnabled( ) {
return GetAllThatSatisfies( delegate( CheckBox box ) { return box.Checked; } );
}
public IEnumerable< T > GetAllThatSatisfies( Predicate< CheckBox > condition ) {
foreach ( CheckBox checkBox in _checkboxes ) {
if ( condition( checkBox ) ) {
yield return ( T )checkBox.Tag;
}
}
}
private readonly IList< CheckBox > _checkboxes;
}
Just remember to override ToString on your types otherwise the default implementation will just write the fully qualified name of your type as the text next to your checkbox. I know this example could be greatly improved, but after a bus ride home pondering about this, this was what I could come up. Feel free to toss me your example.
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace PlayingWithWinForms {
public partial class Form1 : Form {
public Form1( ) {
InitializeComponent( );
ICheckBoxGroup< ISport > group = new CheckBoxGroup< ISport >( );
group.Add( checkBox1, Sport.Hockey );
group.Add( checkBox2, Sport.BasketBall );
group.Add( checkBox3, Sport.FootBall );
group.Add( checkBox4, Sport.Golf );
group.Add( checkBox5, Sport.Tennis );
button1.Click += delegate {
StringBuilder builder = new StringBuilder( );
foreach ( ISport employee in group.GetAllEnabled( ) ) {
builder.AppendFormat( "{0}{1}", employee, Environment.NewLine );
}
MessageBox.Show( builder.ToString( ) );
};
}
}
internal interface ICheckBoxGroup< T > {
void Add( CheckBox checkbox, T item );
IEnumerable< T > GetAllEnabled( );
IEnumerable< T > GetAllThatSatisfies( Predicate< CheckBox > condition );
}
public class CheckBoxGroup< T > : ICheckBoxGroup< T > {
public CheckBoxGroup( ) {
_checkboxes = new List< CheckBox >( );
}
public void Add( CheckBox checkbox, T item ) {
checkbox.Tag = item;
checkbox.Text = item.ToString( );
_checkboxes.Add( checkbox );
}
public IEnumerable< T > GetAllEnabled( ) {
return GetAllThatSatisfies( delegate( CheckBox box ) { return box.Checked; } );
}
public IEnumerable< T > GetAllThatSatisfies( Predicate< CheckBox > condition ) {
foreach ( CheckBox checkBox in _checkboxes ) {
if ( condition( checkBox ) ) {
yield return ( T )checkBox.Tag;
}
}
}
private readonly IList< CheckBox > _checkboxes;
}
public class Sport : ISport {
private Sport( string name ) {
_name = name;
}
public static readonly ISport Hockey = new Sport( "Hockey" );
public static readonly ISport BasketBall = new Sport( "Basket Ball" );
public static readonly ISport FootBall = new Sport( "Football" );
public static readonly ISport Golf = new Sport( "Golf" );
public static readonly ISport Tennis = new Sport( "Tennis" );
public string Name {
get { return _name; }
}
public override string ToString( ) {
return Name;
}
private readonly string _name;
}
public interface ISport {
string Name { get; }
}
}