Question

I'm running into a little problem with a gridview and a dropdownlist. I can get the dropdownlist to load initially, but when it autopostback's it returns with no value. I am populating the dropdownlist in the RowEditing sub. I'm guessing that I must somehow rebind in the RowDataBound sub, but don't know how to go about it. If I try to find the control's SelectedValue I end up with nothing.

VB Code

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  If Not IsPostBack Then
    bindGridView()
  End If
End Sub
'Menu Click

'bindGridView
Public Sub bindGridView(Optional ByVal sortExp As String = "", Optional ByVal sortDir As String = "")
  Dim strConnString As String = ConfigurationManager.ConnectionStrings("WEBConnectionString").ConnectionString
  Dim conn As SqlConnection = New SqlConnection(strConnString)
  conn.Open()
  Dim strProgramNumber As String = 5
  Dim strRecordType As String = "Input Source"
  Dim strProgramInformation As String = "\\path\to\file"
  Dim sql As String
  Dim cmd As SqlCommand = New SqlCommand()
  cmd.Connection = conn
  If sortExp <> String.Empty Then
    sortExp = (sortExp & " " & sortDir).ToString
    sql = "SELECT tblPrgTrackPrograms.ProgramNumber, " & _
          "tblPrgTrackPrograms.ProgramName, " & _
          "tblPrgTrackPrograms.ProgramStatus, " & _
          "tblPrgTrackProgramDocumentation.RecordType, " & _
          "tblPrgTrackProgramDocumentation.ProgramInformation  " & _
          "FROM tblPrgTrackPrograms INNER JOIN tblPrgTrackProgramDocumentation ON " & _
          "tblPrgTrackPrograms.ProgramNumber = tblPrgTrackProgramDocumentation.ProgramNumber ORDER BY " & _
          "@sortExp"
    cmd.Parameters.AddWithValue("sortExp", sortExp)

  Else
    sql = "SELECT tblPrgTrackPrograms.ProgramNumber, " & _
          "tblPrgTrackPrograms.ProgramName, " & _
          "tblPrgTrackPrograms.ProgramStatus, " & _
          "tblPrgTrackProgramDocumentation.RecordType, " & _
          "tblPrgTrackProgramDocumentation.ProgramInformation  " & _
          "FROM tblPrgTrackPrograms INNER JOIN tblPrgTrackProgramDocumentation ON " & _
          "tblPrgTrackPrograms.ProgramNumber = tblPrgTrackProgramDocumentation.ProgramNumber"
  End If
  cmd.CommandText = sql
  Dim myDataSet As New DataSet()
  Dim mySQLAdapter As New SqlDataAdapter(cmd)
  mySQLAdapter.SelectCommand.Connection = conn
  mySQLAdapter.Fill(myDataSet)
  conn.Close()
  gvProgramDetails.DataSource = myDataSet
  gvProgramDetails.DataBind()
End Sub
'ProgramDetails Load
Protected Sub gvProgramDetails_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles gvProgramDetails.Load
  bindGridView()
End Sub
'ProgramDetails Paging
Protected Sub gvProgramDetails_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs) Handles gvProgramDetails.PageIndexChanging
  gvProgramDetails.PageIndex = e.NewPageIndex
  bindGridView()
End Sub
'ProgramDetails Sorting
Protected Sub gvProgramDetails_Sorting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewSortEventArgs) Handles gvProgramDetails.Sorting
  Dim SortDirection As String
  If Session("SortDirection") = vbNullString Then
    Session("SortDirection") = "DESC"
  Else
    SortDirection = Session("SortDirection").ToString
    If SortDirection = "ASC" Then
        SortDirection = "DESC"
    ElseIf SortDirection = "DESC" Then
        SortDirection = "ASC"
    Else
        SortDirection = "ASC"
    End If
    bindGridView(e.SortExpression, Session("SortDirection"))
    'Need to store sort info in view state    
    Session("SortDirection") = SortDirection
  End If
End Sub

'ProgramDetails RowEditing
Protected Sub gvProgramDetails_RowEditing(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewEditEventArgs) Handles gvProgramDetails.RowEditing
  Dim lbl As Label = CType(gvProgramDetails.Rows(e.NewEditIndex).FindControl("lblRecordType"), Label)
  Dim strValue As String = lbl.Text
  gvProgramDetails.EditIndex = e.NewEditIndex
  bindGridView()
  Dim row As GridViewRow = gvProgramDetails.Rows(e.NewEditIndex)
  Dim strConnString As String = ConfigurationManager.ConnectionStrings("CSPaperWEBConnectionString").ConnectionString
  Dim ddlRecordType As DropDownList = CType(row.FindControl("ddlRecordType"), DropDownList)
  Dim conn As SqlConnection = New SqlConnection(strConnString)
  conn.Open()
  Dim sql As String
  Dim cmd As SqlCommand = New SqlCommand()
  cmd.Connection = conn
  sql = "select RecordType from [tblPrgTrackValidRecordTypes] "
  cmd.CommandText = sql
  Dim myDataSet As New DataSet()
  Dim mySQLAdapter As New SqlDataAdapter(cmd)
  mySQLAdapter.SelectCommand.Connection = conn
  mySQLAdapter.Fill(myDataSet)
  conn.Close()
  If ddlRecordType IsNot Nothing Then
    ddlRecordType.DataTextField = "RecordType"
    ddlRecordType.DataValueField = "RecordType"
    ddlRecordType.DataSource = myDataSet
    ddlRecordType.SelectedValue = strValue
    ddlRecordType.DataBind()
  End If
End Sub
Protected Sub gvProgramDetails_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvProgramDetails.RowDataBound
  If e.Row.RowType = DataControlRowType.DataRow Then
    Dim ctrl As Control = e.Row.FindControl("ddlRecordType")
    If ctrl IsNot Nothing Then
      Dim ddlRecordType As DropDownList = ctrl
      MsgBox(ddlRecordType.SelectedValue)

    End If
  End If
End Sub
'ProgramDetails RowUpdating
Protected Sub gvProgramDetails_RowUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewUpdateEventArgs) Handles gvProgramDetails.RowUpdating
  Dim ddlRecordType As DropDownList = gvProgramDetails.Rows(e.RowIndex).FindControl("ddlRecordType")
  MsgBox(ddlRecordType.SelectedValue)
  gvProgramDetails.EditIndex = -1
  bindGridView()
End Sub
'ProgramDetails RowCancelingEdit
Protected Sub gvProgramDetails_RowCancelingEdit1(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCancelEditEventArgs) Handles gvProgramDetails.RowCancelingEdit
  gvProgramDetails.EditIndex = -1
  bindGridView()
End Sub
'ProgramDetails RowDeleting
Protected Sub gvProgramDetails_RowDeleting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewDeleteEventArgs) Handles gvProgramDetails.RowDeleting
  Dim strConnString As String = ConfigurationManager.ConnectionStrings("WEBConnectionString").ConnectionString
  Dim conn As SqlConnection = New SqlConnection(strConnString)
  conn.Open()
  Dim strProgramNumber As String = 5
  Dim strRecordType As String = "Input Source"
  Dim strProgramInformation As String = "\\path\to\file"
  Dim sql As String = "delete from tblPrgTrackProgramDocumentation where ProgramNumber = @ProgramNumber and RecordType = @RecordType and ProgramInformation = @ProgramInformation"
  Dim cmd As SqlCommand = New SqlCommand()
  cmd.Connection = conn
  cmd.CommandText = sql
  cmd.Parameters.AddWithValue("ProgramNumber", strProgramNumber)
  cmd.Parameters.AddWithValue("RecordType", strRecordType)
  cmd.Parameters.AddWithValue("ProgramInformation", strProgramInformation)
  cmd.ExecuteNonQuery()
  cmd.Dispose()
  bindGridView()
End Sub

ASP front end

<ajx:UpdatePanel ID="ajaxpanel" runat="server">   
  <ContentTemplate>        
    <asp:GridView ID="gvProgramDetails" runat="server" AutoGenerateColumns="False" 
    CssClass="gridview" DataKeyNames="ProgramNumber" AllowPaging="True" PageSize="3" AllowSorting="True" >
      <Columns>
        <asp:TemplateField ShowHeader="False">
          <ItemTemplate>
            <asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False" 
            CommandName="Delete" Text="Delete" OnClientClick="return confirm('Are you sure you want to delete this record');"></asp:LinkButton>
          </ItemTemplate>
          <EditItemTemplate>
          </EditItemTemplate>
          <ControlStyle CssClass="button delete" />
        </asp:TemplateField>
        <asp:CommandField ControlStyle-CssClass="button save" ShowEditButton="True">
          <ControlStyle CssClass="button save" />
        </asp:CommandField>
        <asp:BoundField DataField="ProgramNumber" HeaderText="ProgramNumber" 
          InsertVisible="False" ReadOnly="True" SortExpression="ProgramNumber" />
        <asp:BoundField DataField="ProgramName" HeaderText="ProgramName" ReadOnly="True"
          SortExpression="ProgramName" />
        <asp:BoundField DataField="ProgramStatus" HeaderText="ProgramStatus" ReadOnly="True"
          SortExpression="ProgramStatus" />
        <asp:TemplateField HeaderText="RecordType" SortExpression="RecordType">
          <EditItemTemplate>
            <asp:DropDownList ID="ddlRecordType"  runat="server" autopostback="True">
            </asp:DropDownList>
          </EditItemTemplate>
          <ItemTemplate>
            <asp:Label ID="lblRecordType" runat="server" Text='<%# Bind("RecordType") %>'></asp:Label>
          </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="ProgramInformation" HeaderText="ProgramInformation" 
          SortExpression="ProgramInformation" />
      </Columns>
    </asp:GridView>
    <asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:WEBConnectionString %>"
    SelectCommand="SELECT * FROM [tblPrgTrackValidRecordTypes]"></asp:SqlDataSource>
  </ContentTemplate>
</ajx:UpdatePanel>

For those of you who answer drag the control in from the toolbox, create datasource, and set bind("RecordType") please don't. I've tried it that way and the value would always post back with whatever Recordtype was. So unless if you can solve that version of this gridview don't use drag/drop control solution. I'm scratching my brain to solve this one.


Update


I created under App_Code Process/ddlRecordType.vb

Imports Microsoft.VisualBasic
Namespace processes.ProgramTrack.dllRecordType
   Public Class ddlRecordType
        Public Sub ddlRecordType()

        End Sub
        Public Function GetRecords() As DataSet
            Dim conn As New SqlConnection
            Dim cmd As New SqlCommand
            conn.ConnectionString = ConfigurationManager.ConnectionStrings("WEBConnectionString").ConnectionString.ToString
            cmd.CommandText = "select RecordType from [tblPrgTrackValidRecordTypes] "
            cmd.Connection = conn
            Dim myDataSet As New DataSet()
            Dim mySQLAdapter As New SqlDataAdapter(cmd)
            mySQLAdapter.Fill(myDataSet)
            Return myDataSet
        End Function
    End Class
End Namespace

My markup then looks like this.

<asp:DropDownList ID="ddlRecordType" DatasourceID="odsRecordType" DataTextField="RecordType" DataValueField="RecordType" runat="server" autopostback="True"   >                          </asp:DropDownList>                                     
<asp:ObjectDataSource ID="odsRecordType" runat="server" TypeName="processes.ProgramTrack.dllRecordType.ddlRecordType" SelectMethod="GetRecords"></asp:ObjectDataSource> 

Then I get the same problem as before about the DDL not maintaining it's value at postback. Should I start a new Question or continue with this one?

Update to fix the DDL not maintaining. Disable Viewstate for the gridview.

<asp:GridView ID="gvProgramDetails" runat="server" AutoGenerateColumns="False" CssClass="gridview"DataKeyNames="ProgramNumber" AllowPaging="True" PageSize="10" EnableViewState="False" AllowSorting="True">
Was it helpful?

Solution

Try creating an objectDataSource for the DDL, and use that. The problem is that the DDL has to be initialized at page load, or on page init, OR via a DataSource control. If you weren't using the Ajax UpdatePanel (go ahead, take it out, watch your code work, it should anyways) then you would be able to do it like this.

If you'll introduce an ObjectDataSource (and you can pass parameters to it too) then you should end up with what you want.

Edit:

I'm going to provide code from a project of mine, so that you can see how I'm using it. This code will not be perfect to your needs, but will show you how to do what you want.

namespace Appropriate.Namespace.Here {
  public class MyType {
    public List<KeyValuePair<string, string>> GetRoles() {
      List<KeyValuePair<string, string>> l = new List<KeyValuePair<string, string>>();
    
      l.Add( new KeyValuePair<string, string>( "Level1", "Analyst" ) );
      l.Add( new KeyValuePair<string, string>( "Level2", "Customer Service" ) );
      l.Add( new KeyValuePair<string, string>( "Level3", "Customer Service Manager" ) );
      l.Add( new KeyValuePair<string, string>( "Level4", "Full-Access User" ) );
      l.Add( new KeyValuePair<string, string>( "Level5", "Super User" ) );
    
      return l;
    }
  }
}

<asp:DropDownList ID="cmbRoles" runat="server" AutoPostBack="False" DataSourceID="odsRoles" DataTextField="Value" DataValueField="Key" />
<asp:ObjectDataSource ID="odsRoles" runat="server" TypeName="Appropriate.Namespace.Here.MyType" SelectMethod="GetRoles" />

Notice how the namespace and typename work together to give me the SelectMethod? I'm not providing an override on the select parameters, altho you could. You would do that in the page backing code, and I could give some insight on that as well, but I'm trying to not be entirely overly complex.

Notice how I'm returning a List from the method? And I'm just defining it in that method? You could just as easily do a database call there.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top