TribalKnowledge

This article discusses the use of the attribute DataKeyNames of the ListView which can hold individual IDs for each row and how when using a CheckBox and processing an individual click, to get that info during the OnChange event. That ID is not directly supplied to the OnChange event as easily as done when directly working with ListView events. That ID, specific to the actual data is needed so an can update  of status can be sent to the target database item which it represents.

Setup

In setting up the ListView’s HTML I provide a quick example from a previous article here (Quick Asp.Net ListView Template). The item to take out of it is the property DataKeyNames.  For this article I have a Nationalities (USA, France, Argentina…) table which has two boolean fields of Archive and Exempt which are represented as checkboxes within each row of the ListView. The ListView will know that each row’s ID maps to the column NatID field which is the primary key id of the data item. Here is the html which specifies “NatID” as the id column in the data during the databind:

<asp:ListView ID="lvNationalities"
              DataKeyNames="NatID"
              runat="server"
              OnPagePropertiesChanged="UpdateNationalities"
              ItemPlaceholderID="PlaceHolder1">

In the code behind my dynamic Linq entity looks like this and the dynamic entity contains a NatID which is the items primary key id and it has our properties for the checkbox states for archived and exempt.

var natgeos = from nat in _gtdc.Nationalities
              select new
              {
                  NatID    = nat.Nationality_ID,
                  Archived = nat.Archived,
                  Exempt   = nat.Exempt,
                  Name     = nat.Text
              };

lvNationalities.DataSource = natgeos;
lvNationalities.DataBind();

So NatID is pulled from the database item as shown above. Visually we will have to CheckBoxes for Archived and Exempt as mentioned for the user to change. Each change needs to be handled by the checkbox and the database immediately updated.  Here is a screen shot:

NationalitiesListView

CheckBox

Below is the code which specifies the specific CheckBox event. Looking at the archive CheckBox we handle an OnCheckedChanged event:

<asp:CheckBox ID="cbArchived"
              runat="server"
              AutoPostBack="true"
              Checked='<%# Eval("Archived") %>'
              OnCheckedChanged="ArchiveChanged"
              Text="Archived"/>

Because we are not using the command methodology of the ListView, when we handle the event of the checkbox we don’t have direct access to which row data has been checked. To do that we will dereference some items which will get us to the NatID of row item which was clicked. Here is the code to do that:

protected void ArchiveChanged( object sender, EventArgs e )
{

CheckBox target = sender as CheckBox;

if ( target != null )
{
    ListViewDataItem di = target.NamingContainer as ListViewDataItem;

    if ( di != null )
    {
        int id = (int)lvNationalities.DataKeys[di.DataItemIndex]["NatID"];

        _gtdc = new GTCDataContext( Utilities.GetConnectionString() );

        var item = _gtdc.Nationalities.Where( it => it.Nationality_ID == id ).FirstOrDefault();

        if ( item != null )
        {
            item.Archived = target.Checked;
            _gtdc.SubmitChanges();
        }
    }
}

}

The first step is to convert the sender object to a CheckBox. Once that is successful we use the NamingContainer property off of the CheckBox. That property allows us to access the parent item which is the ListViewDataItem. That is our link back to the ListView. With that we can divine the ID needed from the ListViewDataItem’s index into the DataKeys cache for that row’s ID. Once gotten we can update the database as shown by setting the Archive attribute for the Nationalities for the user selected item.

Share