DropDownList after postback all values/index lost
-
13-06-2021 - |
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">
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.