# Thursday, June 04, 2009

DropDownList, GridView, and Dynamically selecting the appropriate ListItem during Edit...

I have seen a number of questions regarding how to specify what the selected ListItem is on a DropDownList used in an EditRow of A GridView. So I thought it might make a good blog.

Note: for an example that uses Ajax, specifically the CascadingDropDown, look here http://www.myfriedmind.com/techBlog/2009/06/22/CascadingDropDownListsGridViewsAndDynamicallySelectingTheAppropriateListItemDuringEdit.aspx.

Basically what people are trying to do is use a DropDownList as one of the input controls on a DataRow when edit is selected for that Row. This, of course, limits what people can enter which is a good thing. For example, what if you wanted to create a DropDownList that specified which state someone was from, or what time (using 15-minute increments)?

Creating the DropDownList is fairly straightforward, as is populating it. What is confusing people is how to specify what the selected value is. To do that you need to handle the OnRowDataBound event, snag the DataItem and select the ListItem that matches the appropriate property. Like so:

Sample DataObject (in c#)

class MyObject
{
   public int ObjId {get; set;}
   public string StateAbbreviation {get; set; }
}

Sample DataObject (in vb.net)

Class MyObject
    Public ObjId As Integer
    Public StateAbbreviation As String
End Class


Entry on the SampleGridview.aspx page (as simple as you can get it )

<asp:GridView runat="server" ID="lstMyData" DataKeyNames="ObjId"
    AutoGenerateColumns="false" EnableViewState="true"
    AutoGenerateEditButton="true"
    OnRowDataBound="lstMyData_RowDataBound" >
    <Columns>
        <asp:TemplateField>
            <ItemTemplate>
                <asp:Label runat="server" ID="lblState" Text='<%# Eval("StateAbbreviation") %>' />
            </ItemTemplate>
            <EditItemTemplate>
                <asp:DropDownList runat="server" ID="uxState" />
            </EditItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

Codebehind (in c#) SampleGridview.aspx.cs

protected void lstMyData_RowDataBound(object sender,
        GridViewRowEventArgs e)
{
    // verify this is a DataRow, not a Header, Footer, etc...
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        // in case you want to do something else here....
       
        // see if this is the Row used for Editing
        if ((e.Row.RowState & DataControlRowState.Edit) != 0)
        {
            // get the DataItem that is bound
            // and cast it accordingly
            MyObject _myObject = (MyObject)e.Row.DataItem;

            // get the dropdownlist
            DropDownList _uxState =
                (DropDownList) e.Row.FindControl("uxState");

            // dynamically create the DDL for demo...
            // this could also be done statically in the aspx page
            _uxState.Items.Add(new ListItem("Hawaii", "HI"));
            _uxState.Items.Add(new ListItem("Iowa", "IA"));
            _uxState.Items.Add(new ListItem("Minnesota", "MN"));
            _uxState.Items.Add(new ListItem("Wisconsin", "WI"));

            // find the matching ListItem and Select it
            ListItem _matchingItem =
                _uxState.Items.FindByValue(_myObject.StateAbbreviation);
            if (_matchingItem == null)
            {
                // Houston we have a problem, no match...
                // handle this as you see fit
            }
            else
            {
                _matchingItem.Selected = true;
            }
        }
    }
}

Protected Sub lstMyData_RowDataBound(ByVal sender As Object, _
    ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) _
    Handles lstMyData.RowDataBound
    If e.Row.RowType = DataControlRowType.DataRow Then

            ' in case you want to do something else here....

            ' see if this is the Row used for Editing
            If (e.Row.RowState And DataControlRowState.Edit) <> 0 Then


                ' get the DataItem that is bound
                ' and cast it accordingly
                Dim _myObject As MyObject = _
                    DirectCast(e.Row.DataItem, MyObject)

                ' get the dropdownlist
                Dim _uxState As DropDownList = _
                    DirectCast(e.Row.FindControl("uxState"), DropDownList)

                ' dynamically create the DDL for demo...
                ' this could also be done statically in the aspx page
                _uxState.Items.Add(New ListItem("Hawaii", "HI"))
                _uxState.Items.Add(New ListItem("Iowa", "IA"))
                _uxState.Items.Add(New ListItem("Minnesota", "MN"))
                _uxState.Items.Add(New ListItem("Wisconsin", "WI"))

                ' find the matching ListItem and Select it
                Dim _matchingItem As ListItem = _
                    _uxState.Items.FindByValue(_myObject.StateAbbreviation)
                If _matchingItem Is Nothing Then
                    ' Houston we have a problem, no match...
                    ' handle this as you see fit
                Else
                    _matchingItem.Selected = True
                End If
            End If
     End If
End Sub

So basically what you are doing is getting a hold of both the value that you want selected (by using the e.Row.DataItem) and the DropDownList (by using e.Row.FindControl) and then simply doing a match...

Hope this helps...

Comments are closed.