Multiple Row Selection With GridView

We often need the capability of selecting multiple rows from a grid, unfortunately the GridView component in ASP.Net 2.0 does not offer an out-of-box support for such functionality.Fortunately, implementing such behavior is pretty straight if you have a clear understanding of how the GridView component works. Many of the samples demonstrated in various other posts require registering some  kind of client side JavaScript, here I will show a slightly different approach in which no custom JavaScript is needed (of course, there are JavaScripts generated automatically by the framework).

Suppose we are creating a simple application where you can select multiple people from a contact list and then do somthing with your selection (e.g. export the selection etc.) An intuitive way is to include a column of CheckBoxes in the front of all the rows so that the staus of each CheckBox indicates whether that row is included in the user selection (See below):

Select User Name Phone Number
Bob (232) 111-1312
Sue (088) 676-9987
Jim (678) 123-4567
 

In this demonstration, I will use a customized object data source called UserDefinition: 

[Serializable()]
public class UserDefinition
{
    private bool _entrySelected = false;
    private string _userName = string.Empty;
    private string _phoneNumber = string.Empty;
 
    public bool EntrySelected
    {
        get { return _entrySelected; }
        set { _entrySelected = value; }
    }
 
    public string UserName
    {
        get { return _userName; }
        set { _userName = value; }
    }
 
    public string PhoneNumber
    {
        get { return _phoneNumber; }
        set { _phoneNumber = value; }
    }
 
    public UserDefinition(string name, string phone)
    {
        _userName = name;
        _phoneNumber = phone;
    }
}

Alternatively, you could use pretty much any data sources that you are accustomed to. The concept should be similar  enough.

And the GridView is defined as follows:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
    <Columns>
        <asp:TemplateField HeaderText="Select">
            <ItemTemplate>
                <asp:CheckBox ID="CBEntrySelected" runat="server" AutoPostBack="True" Checked=‘<%# Bind("EntrySelected") %>’
                    OnCheckedChanged="CBEntrySelected_CheckedStateChanged" />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField HeaderText="User Name" DataField="UserName" />
        <asp:BoundField HeaderText="Phone Number" DataField="PhoneNumber" />
    </Columns>
</asp:GridView>

Note that the AutoPostBack property is set to true so that the server side code would have an opportunity to record the user’s action. So far, every thing should be pretty straightforward. The only trick is in the server side code:

    protected void Page_Load(object sender, EventArgs e)
    {
        DisplayGrid();
    }
 
    private void DisplayGrid()
    {
        List<UserDefinition> list = new List<UserDefinition>();
 
        list.Add(new UserDefinition("Bob", "(232) 111-1312"));
        list.Add(new UserDefinition("Sue", "(088) 676-9987"));
        list.Add(new UserDefinition("Jim", "(678) 123-4567"));
 
        GridView1.DataSource = list;
 
        if (!Page.IsPostBack)
        {
            GridView1.DataBind();
            ViewState["CurrentView"] = list;
        }
    }
 
    protected void CBEntrySelected_CheckedStateChanged(object sender, EventArgs e)
    {
        CheckBox checkBox = sender as CheckBox;
        GridViewRow selectedRow = checkBox.Parent.Parent as GridViewRow;
        List<UserDefinition> list = ViewState["CurrentView"] as List<UserDefinition>;
        list[selectedRow.RowIndex].EntrySelected = checkBox.Checked;
    }
 
    protected void BtnSubmit_Click(object sender, EventArgs e)
    {
        List<UserDefinition> list = ViewState["CurrentView"] as List<UserDefinition>;
        StringBuilder sb = new StringBuilder();
 
        sb.Append("<br />Selected items:<br />");
 
        foreach (UserDefinition def in list)
        {
            if (def.EntrySelected)
            {
                sb.Append(string.Format("{0} : {1}<br />", def.UserName, def.PhoneNumber));
            }
        }
 
        Label1.Text = sb.ToString();
    }

Note that in our CkeckBox checked event handler CBEntrySelected_CheckedStateChanged, we used the GridView object hierarchy to figure out which row was selected/unselected by user and record it accordingly in the object that the grid renders. The hierarchy is as follows:

 CheckBox -> DataControlFieldCell -> GridViewRow -> ChildTable -> GridView

 Also note that in our simple example, only the RowIndex is used to determine whether a row is selected or not. This only works when paging is not involved. When there are multiple pages, we have to go two hierarchies higher to the GridView level, where we can use PageIndex and PageSize to identify the correct selection (i.e. PageSize * PageIndex + RowIndex).

 

Be Sociable, Share!

One Comment

  1. koltaviy says:

    Thanks a lot!!

Leave a Reply