Reputation: 570
Currently making a form with drop down list that changes data based on the drop down list before it. I'm using this example as reference and this is what I have made so far:
Design:
<asp:Table ID="Table1" runat="server" Width="100%">
<asp:TableRow runat="server">
<asp:TableCell runat="server" Width="10%">
<asp:Label ID="Label1" runat="server" Text="Line" Font-Size="x-Large"></asp:Label>
</asp:TableCell>
<asp:TableCell ID="TableCell11" runat="server" Width="3%">
<asp:Label ID="label_txt" runat="server" Text=" :" Font-Size="x-Large"></asp:Label>
</asp:TableCell>
<asp:TableCell runat="server" Width = "40%">
<asp:dropdownlist ID="line" runat="server" BorderStyle="Solid" Font-Size="x-Large" BorderWidth="1px" Width = 80% ReadOnly="True"
autopostback=true onselectedindexchanged= "line_selectedindexchanged"></asp:dropdownlist>
</asp:TableCell>
</asp:TableRow>
<asp:TableRow runat="server">
<asp:TableCell ID="TableCell1" runat="server" Width = 10%>
<asp:Label ID="Label2" runat="server" Text="Process" Font-Size="x-Large"></asp:Label>
</asp:TableCell>
<asp:TableCell ID="TableCell12" runat="server" Width = 3%>
<asp:Label ID="Label8" runat="server" Text=" :" Font-Size="x-Large"></asp:Label>
</asp:TableCell>
<asp:TableCell ID="TableCell2" runat="server" Width = 40%>
<asp:dropdownlist ID="process" runat="server" BorderStyle="Solid" Font-Size="x-Large" BorderWidth="1px" Width = 80% ReadOnly="True"
autopostback=true onselectedindexchanged= "process_selectedindexchanged"></asp:dropdownlist>
</asp:TableCell>
</asp:TableRow>
<asp:TableRow runat="server">
<asp:TableCell ID="TableCell5" runat="server" Width=10%>
<asp:Label ID="Label4" runat="server" Text="Equipment" Font-Size="x-Large"></asp:Label>
</asp:TableCell>
<asp:TableCell ID="TableCell14" runat="server" Width=3%>
<asp:Label ID="Label10" runat="server" Text=" :" Font-Size="x-Large"></asp:Label>
</asp:TableCell>
<asp:TableCell ID="TableCell6" runat="server" Width=40%>
<asp:dropdownlist ID="equipment" runat="server" BorderStyle="Solid" Font-Size="x-Large" BorderWidth="1px" Width=80% ReadOnly="True"
autopostback=true onselectedindexchanged= "equipment_selectedindexchanged"></asp:dropdownlist>
</asp:TableCell>
</asp:tablerow>
<asp:TableRow ID="TableRow3" runat="server">
<asp:TableCell ID="TableCell3" runat="server" Width = 10%>
<asp:Label ID="Label3" runat="server" Text="Step" Font-Size="x-Large"></asp:Label>
</asp:TableCell>
<asp:TableCell ID="TableCell13" runat="server" Width = 3%>
<asp:Label ID="Label9" runat="server" Text=" :" Font-Size="x-Large"></asp:Label>
</asp:TableCell>
<asp:TableCell ID="TableCell4" runat="server" Width = 40%>
<asp:DropDownList ID="step" runat="server" BorderStyle="Solid" Font-Size="x-Large" BorderWidth="1px" Width = 80%
autopostback=true >
</asp:DropDownList>
</asp:TableCell>
</asp:TableRow>
</asp:Table>
Code:
Imports System.Data.SqlClient
Public Class WebForm1
Inherits System.Web.UI.Page
Dim conn As SqlConnection = New SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("SQLIOTConnectionString").ConnectionString)
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Session("EmpID") Is Nothing Then
Response.Redirect("~/Login.aspx")
Else
If Not IsPostBack Then 'whenever hv dropdownlist, need to have this in load sub, or else won't get ddl data.
CaseDate.Text = DateTime.Now.ToString("yyyy-MM-dd")
CreateBy.Text = Session("EmpID").ToString
ReportPIC.Text = Session("EmpID").ToString
FillLine()
End If
End If
End Sub
Protected Sub line_selectedindexchanged(ByVal sender As Object, ByVal e As EventArgs)
Dim level1_ID As Integer = Convert.ToInt32(line.SelectedValue.ToString())
FillProcess(level1_ID)
End Sub
Protected Sub process_selectedindexchanged(ByVal sender As Object, ByVal e As EventArgs)
Dim level2_ID As Integer = Convert.ToInt32(process.SelectedValue.ToString())
FillEquipment(level2_ID)
End Sub
Protected Sub equipment_selectedindexchanged(ByVal sender As Object, ByVal e As EventArgs)
Dim level3_ID As Integer = Convert.ToInt32(equipment.SelectedValue.ToString())
FillStep(level3_ID)
End Sub
Private Sub FillLine()
Dim cmd As New SqlCommand
cmd.Connection = conn
cmd.CommandType = CommandType.Text
cmd.CommandText = "select distinct level1_id, [LCODE1]+ ' | '+[LNAME1] as [LCODE1]" _
& " FROM [SQLIOT].[dbo].[ZVIEW_MCM_LEVEL_LOOKUP]"
Dim objDs As New DataSet()
Dim dAdapter As New SqlDataAdapter()
dAdapter.SelectCommand = cmd
conn.Open()
dAdapter.Fill(objDs)
conn.Close()
If objDs.Tables(0).Rows.Count > 0 Then
line.DataSource = objDs.Tables(0)
line.DataTextField = "LCODE1"
line.DataValueField = "level1_id"
line.DataBind()
line.Items.Insert(0, "")
End If
End Sub
Private Sub FillProcess(ByVal level1_ID As Integer)
Dim cmd As New SqlCommand
cmd.Connection = conn
cmd.CommandType = CommandType.Text
cmd.CommandText = "select distinct level2_id, [LCODE2]+ ' | '+[LNAME2] as [LCODE2]" _
& " FROM [SQLIOT].[dbo].[ZVIEW_MCM_LEVEL_LOOKUP] where level1_id = @level1_id"
cmd.Parameters.AddWithValue("@level1_id", level1_ID)
Dim objDs As New DataSet()
Dim dAdapter As New SqlDataAdapter()
dAdapter.SelectCommand = cmd
conn.Open()
dAdapter.Fill(objDs)
conn.Close()
If objDs.Tables(0).Rows.Count > 0 Then
process.DataSource = objDs.Tables(0)
process.DataTextField = "LCODE2"
process.DataValueField = "level2_id"
process.DataBind()
process.Items.Insert(0, "")
End If
End Sub
Private Sub FillEquipment(ByVal level2_ID As Integer)
Dim cmd As New SqlCommand
cmd.Connection = conn
cmd.CommandType = CommandType.Text
cmd.CommandText = "select distinct level3_id, [LCODE3]+ ' | '+[LNAME3] as [LCODE3]" _
& " FROM [SQLIOT].[dbo].[ZVIEW_MCM_LEVEL_LOOKUP] where level2_id = @level2_id"
cmd.Parameters.AddWithValue("@level2_id", level2_ID)
Dim objDs As New DataSet()
Dim dAdapter As New SqlDataAdapter()
dAdapter.SelectCommand = cmd
conn.Open()
dAdapter.Fill(objDs)
conn.Close()
If objDs.Tables(0).Rows.Count > 0 Then
process.DataSource = objDs.Tables(0)
process.DataTextField = "LCODE3"
process.DataValueField = "level3_id"
process.DataBind()
process.Items.Insert(0, "")
End If
End Sub
Private Sub FillStep(ByVal level3_ID As Integer)
Dim cmd As New SqlCommand
cmd.Connection = conn
cmd.CommandType = CommandType.Text
cmd.CommandText = "select distinct [LCODE4]+ ' | '+[LNAME4] as [LCODE4]" _
& " FROM [SQLIOT].[dbo].[ZVIEW_MCM_LEVEL_LOOKUP] where level3_id = @level3_id"
cmd.Parameters.AddWithValue("@level3_id", level3_ID)
Dim objDs As New DataSet()
Dim dAdapter As New SqlDataAdapter()
dAdapter.SelectCommand = cmd
conn.Open()
dAdapter.Fill(objDs)
conn.Close()
If objDs.Tables(0).Rows.Count > 0 Then
process.DataSource = objDs.Tables(0)
process.DataTextField = "LCODE4"
'process.DataValueField = "level3_id"
process.DataBind()
process.Items.Insert(0, "")
End If
End Sub
From what I understand in the example, once I select a value from the first drop down list, the next one before it will have value and so on. But during testing, after I select value from the 1st drop down list, I get an error
JavaScript runtime error: Member not found.
I have no idea how JavaScript works, nor did I even touch it... Can anyone help with this issue?
EDIT:
Using Mary's suggestion:
Protected Sub line_selectedindexchanged(ByVal sender As Object, ByVal e As EventArgs)
Dim level1_ID As Integer = Convert.ToInt32(line.SelectedValue.ToString())
FillProcess(level1_ID)
End Sub
Protected Sub ddlprocess_selectedindexchanged(ByVal sender As Object, ByVal e As EventArgs)
Dim level2_ID As Integer = Convert.ToInt32(ddlprocess.SelectedValue.ToString())
FillEquipment(level2_ID)
End Sub
Protected Sub equipment_selectedindexchanged(ByVal sender As Object, ByVal e As EventArgs)
Dim level3_ID As Integer = Convert.ToInt32(equipment.SelectedValue.ToString())
FillStep(level3_ID)
End Sub
Private Sub FillLine()
Dim dt As New DataTable
Dim strSql = "select distinct level1_id, [LCODE1]+ ' | '+[LNAME1] as [LCODE1]" _
& " FROM [SQLIOT].[dbo].[ZVIEW_MCM_LEVEL_LOOKUP]"
Using conn As New SqlConnection(ConStr),
cmd As New SqlCommand(strSql, conn)
conn.Open()
dt.Load(cmd.ExecuteReader)
End Using
If dt.Rows.Count > 0 Then
line.DataSource = dt
line.DataTextField = "LCODE1"
line.DataValueField = "level1_id"
line.DataBind()
line.Items.Insert(0, "")
End If
End Sub
Private Sub FillProcess(ByVal level1_ID As Integer)
Dim dt As New DataTable
Dim strSql = "select distinct level2_id, [LCODE2]+ ' | '+[LNAME2] as [LCODE2]" _
& "FROM [SQLIOT].[dbo].[ZVIEW_MCM_LEVEL_LOOKUP] where level1_id = @level1_id"
Using conn As New SqlConnection(ConStr),
cmd As New SqlCommand(strSql, conn)
cmd.Parameters.Add("@level1_id", SqlDbType.Int).Value = level1_ID
conn.Open()
dt.Load(cmd.ExecuteReader)
End Using
If dt.Rows.Count > 0 Then
ddlprocess.DataSource = dt
ddlprocess.DataTextField = "LCODE2"
ddlprocess.DataValueField = "level2_id"
ddlprocess.DataBind()
ddlprocess.Items.Insert(0, "")
End If
End Sub
Private Sub FillEquipment(ByVal level2_ID As Integer)
Dim dt As New DataTable
Dim strSql = "select distinct level3_id, [LCODE3]+ ' | '+[LNAME3] as [LCODE3]" _
& "FROM [SQLIOT].[dbo].[ZVIEW_MCM_LEVEL_LOOKUP] where level2_id = @level2_id"
Using conn As New SqlConnection(ConStr),
cmd As New SqlCommand(strSql, conn)
cmd.Parameters.Add("@level2_id", SqlDbType.Int).Value = level2_ID
conn.Open()
dt.Load(cmd.ExecuteReader)
End Using
If dt.Rows.Count > 0 Then
equipment.DataSource = dt
equipment.DataTextField = "LCODE3"
equipment.DataValueField = "level3_id"
equipment.DataBind()
equipment.Items.Insert(0, "")
End If
End Sub
Private Sub FillStep(ByVal level3_ID As Integer)
Dim dt As New DataTable
Dim strSql = "select distinct level4_id, [LCODE4]+ ' | '+[LNAME4] as [LCODE4]" _
& "FROM [SQLIOT].[dbo].[ZVIEW_MCM_LEVEL_LOOKUP] where level3_id = @level3_id"
Using conn As New SqlConnection(ConStr),
cmd As New SqlCommand(strSql, conn)
cmd.Parameters.Add("@level3_id", SqlDbType.Int).Value = level3_ID
conn.Open()
dt.Load(cmd.ExecuteReader)
End Using
If dt.Rows.Count > 0 Then
[step].DataSource = dt
[step].DataTextField = "LCODE4"
[step].DataValueField = "level3_id"
[step].DataBind()
[step].Items.Insert(0, "")
End If
End Sub
But the same problem remains...
Upvotes: 0
Views: 117
Reputation: 15091
The only thing I could see that would cause the error was the name process. That could cause a conflict with the Process class in System.Diagnostics. I changed the name to ddlProcess
.
I loaded a datatable instead of fooling with a DataSet
or DataAdapter
.
Connections need to be local to the method where they are used so they can be closed and disposed. They use unmanaged resources which are released in their .Dispose
method. Using...End Using
blocks handle this for you even if there is an error. I included the command in the using block.
In Sql Server the .Add
method is preferred. See http://www.dbdelta.com/addwithvalue-is-evil/
and
https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/
and another one:
https://dba.stackexchange.com/questions/195937/addwithvalue-performance-and-plan-cache-implications
Here is another
https://andrevdm.blogspot.com/2010/12/parameterised-queriesdont-use.html
I was a bit surprised that drop down list allowed you to insert an item when it was already databound. Maybe delete that line if it is not necessary.
Private ConStr As String = System.Configuration.ConfigurationManager.ConnectionStrings("SQLIOTConnectionString").ConnectionString
Private Sub FillProcess(ByVal level1_ID As Integer)
Dim dt As New DataTable
Dim strSql = "select distinct level2_id, [LCODE2]+ ' | '+[LNAME2] as [LCODE2]
FROM [SQLIOT].[dbo].[ZVIEW_MCM_LEVEL_LOOKUP] where level1_id = @level1_id"
Using conn As New SqlConnection(ConStr),
cmd As New SqlCommand(strSql, conn)
cmd.Parameters.Add("@level1_id", SqlDbType.Int).Value = level1_ID
conn.Open()
dt.Load(cmd.ExecuteReader)
End Using
If dt.Rows.Count > 0 Then
ddlProcess.DataSource = dt
ddlProcess.DataTextField = "LCODE2"
ddlProcess.DataValueField = "level2_id"
ddlProcess.DataBind()
ddlProcess.Items.Insert(0, "")
End If
End Sub
Upvotes: 1