There are many scenarios where we have fields containing nicely formatted lists (i.e. "item1, item2, item3" or "item1;item2;item3") and we'd like to provide users with an easy, error-proof way of editing these fields. The obvious solution is to use the CheckedListBox control provided in Visual Studio. But what if we want to use this as an editor in a datagrid? A CheckedListBox is not among the common datagrid editors to choose from and ultimately we would want it inside a drop-down.

This blog post demonstrates how to create a drop-down CheckedListBox in a C1FlexGrid for editing and formatting lists.

CheckedListBox Editor for FlexGrid

The C1FlexGrid control supports several built-in editors (checkbox, combo, drop-down list, datetimepicker, data/image maps). Plus you can use any regular .NET control as a cell's editor by simply setting a Column's Editor property to an instance of the control, as shown below.

c1FlexGrid1.Cols[0].Editor = new CheckedListBox();

This would give us a CheckedListBox as the cell editor for column 0, however the CheckedListBox is not inside a drop-down. We also need to do some additional work somewhere to tell it how to parse and format our list of items. To accomplish this we have a couple options. The easiest solution is to use the C1DropDownControl, which is part of ComponentOne Input for WinForms and enables us to design our own drop-downs using our own logic and any .NET controls. Another option is to create our own control inheriting from the UITypeEditor class. This is described at the end of this post.

Set up the Project

In this sample we will be displaying a C1FlexGrid bound to a simple list of automobile insurance client objects. One of the fields is a list of coverage options separated by commas. We will use C1DropDownControl to create our drop-down CheckedListBox. You can download C1FlexGrid and C1DropDownControl as part of ComponentOne Studio for WinForms. Create a new project in Visual Studio, and drop a C1FlexGrid onto the form. Set its ExtendLastCol = True. On page load, insert the following code which just creates and loads some sample data:

List _listClients = new List();
_listClients.Add(new Client("CL001", "Collision"));
_listClients.Add(new Client("CL003", "Collision, Liability"));
_listClients.Add(new Client("CL004", "Comprehensive, Medical Payments, Uninsured Motorist"));
c1FlexGrid1.DataSource = _listClients;

The "Client" object is defined as such:

public class Client
{
    public Client(string id, string options)
    {
        ID = id;
        CoverageOptions = options;
    }
    public string ID { get; set; }
    public string CoverageOptions { get; set; }
}

All code in this post is in C#, however a VB sample has also been provided below.

Using C1DropDownControl

The C1DropDownControl is a designer-friendly control which allows you to fully customize your own drop-downs at design-time. There is minimal coding required to use it as a C1FlexGrid cell editor and then some code to provide our logic. Drop a C1DropDownControl onto the form containing C1FlexGrid.

C1DropDownControl

Set its VisibleButtons.UpDown = False. We will only be providing logic for the drop-down button. Next, we will design the drop-down portion. Add a new form to your project and call it "CheckedListBoxDropDown." This form will not inherit from the standard System.Windows.Form class, but instead from the C1.Win.C1Input.DropDownForm class.

In the code-behind page, modify this as such:

C1DropDownControl Switch to design view and add a CheckedListBox control from the toolbox. Set the control's Dock = Fill, BorderStyle = None, CheckOnClick = True, and resize the form to about 100 x 80.

We could hard code our list of items right here at design-time. But we might want to reuse this editor multiple times across our application so it's smarter to do this dynamically. So we'll add a constructor that accepts a string array.

public CheckedListBoxDropDown(string[] items)
{
    InitializeComponent();
    foreach (string item in items)
    {
        checkedListBox1.Items.Add(item);
    }
}

Next, we must add our logic to two important events on the DropDownForm: Open and PostChanges. The Open event fires when the drop-down is opened. Here we will take the pre-existing value, parse it, and check the correct checkboxes.

private void CheckedListBoxDropDown_Open(object sender, EventArgs e)
{
    //Check items which are included in text (useful if used as a grid editor)
    string s = OwnerControl.Text;
    for (int i = 0; i < checkedListBox1.Items.Count; i  )
    {
        if (s.Contains(checkedListBox1.Items[i].ToString()))
            checkedListBox1.SetItemChecked(i, true);
        else
            checkedListBox1.SetItemChecked(i, false);
    }
    checkedListBox1.SelectedIndex = -1;
}

The PostChanges event fires when the user is done editing. Here we want to take the checked items and build our formatted string.

private void CheckedListBoxDropDown_PostChanges(object sender, EventArgs e)
{
    //Format selected items into comma separated list
    string conc = "";
    foreach (string item in checkedListBox1.CheckedItems)
    {
        conc  = item   ", ";
    }
    if (conc.Length > 0)
        conc = conc.Remove(conc.LastIndexOf(','), 2);
    OwnerControl.Value = conc;
}

In the code above we have access to the "OwnerControl" object, which is the C1TextBox portion of the C1DropDownControl we connect our DropDownForm to. This is the control that is actually bound to our datasource. We also must set the Options.AlwaysPostChanges property to True for this event to fire when the drop-down closes (the C1Input.DropDownForm doesn't always have to post changes when the drop-down is closed. You could configure it to work differently through the Options properties). Finally, we need to connect our drop-down form to C1DropDownControl and to our C1FlexGrid. We can do this best in code using the FlexGrid's Editor property on the column or row we want.

//Connect CheckedListBoxDropDown form to c1DropDownControl1
CheckedListBoxDropDown dropdown = new CheckedListBoxDropDown(new string[] { "Collision", "Comprehensive", "Liability", "Medical Payments", "Uninsured Motorist", "Additional Options" });
c1DropDownControl1.DropDownForm = dropdown; //Connect c1DropDownControl1 to c1FlexGrid
c1FlexGrid1.Cols["CoverageOptions"].Editor = c1DropDownControl1;

When we run this we see our fully working, bound checkedlistbox drop-down editor. Checkedlistbox drop-down editor

Download Sample (VS2008)

FlexGridCheckboxlist_5F00_CS.zip FlexGridCheckboxlist_5F00_VB.zip

Using UITypeEditor

Another option is to write our own drop-down inheriting from the UITypeEditor class. This does not require the C1Input library and a bit more code needs to be written (or pasted). FlexGrid ships with a sample called "CustomEditors" which shows how to inherit from the UITypeEditor class to make some common, useful editors for C1FlexGrid, such as a color picker, image picker and even a docking editor. This class helps to create a control that can be used as a grid editor. There is too much code to insert here.

A separate sample implementing a CheckedListBox using UITypeEditor can be downloaded below (C# only). FlexCheckedListBox_5F00_UITypeEditor.zip

In another article, we demonstrate how to use FlexGrid as an advanced ListBox.

Use CheckedListBox Editors for FlexGrid

Download the latest version of ComponentOne Studio Enterprise

Download Now!