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)