02juli

Counting selected items in a List Control using Linq

In my previous blog post I wrote about a method I found on clearing all items in a List Control using the (apparently) built-in method ClearSelection().

In this post I discuss a small technique some of you might also find useful. Besides clearing the items in a list control it was also necessary for the before mentioned application to count the number of selected items in a List Control (mosty a <asp:CheckBoxList>). In some lists users where restricted to selecting a maximum of 5 items out of 10, or similar. If a user selects a sixth item, an error message is shown.

Traditional approach using foreach()

The traditional approach would be something like the code below.

First, declare the CheckBoxList on the page like this

<asp:CheckBoxList runat="server" ID="chkList" RepeatColumns="2" RepeatDirection="Vertical"

AutoPostBack="true" OnSelectedIndexChanged="chkListChanged" />
<
asp:Label ID="lblNoItems" runat="server" />

For the sake of the example I use the Page_Load() event in code behind to fill the list with 20 items:

 protected void Page_Load(object sender, EventArgs e)

    {

        if (!Page.IsPostBack)

        {

            // fill items in CheckBoxList

            for (int i = 1; i <= 20; i++)

            {

                ListItem li = new ListItem();

                li.Text = string.Format("Item {0}", i);

                li.Value = i.ToString();

                chkList.Items.Add(li);

            }

        }

    }

Then, write the method chkListChanged() to handle the selection of the items.

protected void chkListChanged(object sender, EventArgs e)
{

int selectedItems = 0;

       foreach (ListItem li in chkList.Items)

        {

            if (li.Selected)

                selectedItems++;

        }

        if (selectedItems > 5)

        {

            // throw some error message

            lblNoItems.Text = " Too many items selected...";

        }
}

An approach using Linq

Since the project I'm working on is a full .NET 3.5 Linq-based solution, I figured it would be elegant to use Linq also to retrieve the number of selected items in the List. This way it is like "querying a List Control". This is (IMHO) quite an exciting concept, if you were used to only build queries for SQL-databases. After some googling I composed the following method

var total = from i in chkList.Items.Cast<ListItem>()

                    where i.Selected == true

                    select i;

now the variable total is available. It holds all the selected items in the list. We can use the Linq method Count() to test how many items have been selected and show an appropriate message in lblNoItems.

int allowedItems = 5;       

        lblNoItems.Text = total.Count() <= allowedItems

            ? string.Format("No. of selected items: {0}. You're OK!", total.Count())

            : string.Format("To many items selected ({0}), please deselect {1} item(s)!",

                total.Count(), (total.Count() - allowedItems));

Two things to notice here:

  • In the Linq query you must explicitly cast the items in the List to a <ListItem> object using the Cast() method, otherwise the query won't work.
  • I use the ? : operator to decide wich message is shown instead of an if-else compound statement.

As I've discovered, there are more advantages using Linq this way. For example, the variable total not only holds the number of selected items in the list (as the variable selectedItems does in the traditional approach), but is a complete array of all selected ListItem objects. You could further manipulate this, for example serialize them and store in a users profile or in a database, and so on (again, using a foreach-loop).

This is what the page looks like when 5 items or less are selected

And here's the UI once you select a sixth item

The files are available for download,

Thanks for reading,

-- Peter Kassenaar,
2 juli 2008.

countCheckBoxList.zip (1,56 kb)

Reacties zijn gesloten