I'm working on a web app using Visual Studio VB.NET. I have a web form with two panels. I have the code below:
Protected Sub WebForm2_load(sender As Object, e As EventArgs) Handles Me.Load
Dim y As Integer = 1
Protected cr(100) As Button
If con.State = ConnectionState.Open Then
con.Close()
End If
con.Open()
Dim requ As String
requ = "SELECT DISTINCT ENSEIGNEMENTS.Code_Mat From ENSEIGNANT INNER Join ENSEIGNEMENTS On ENSEIGNANT.Code_Ens = ENSEIGNEMENTS.Code_Ens where NomUser='" + un + "' and Sem='S1'"
cmd = New SqlCommand(requ, con)
Dim rd As SqlDataReader = cmd.ExecuteReader()
While rd.Read()
cr(y) = New Button
cr(y).Text = rd("Code_Mat").ToString
cr(y).ID = "btn" & y.ToString
Panel1.Controls.Add(cr(y))
AddHandler cr(y).Click, AddressOf btnc
y = y + 1
End While
End Sub
Protected Sub btnc(ByVal sender As Object, ByVal e As System.EventArgs)
Protected cr1(100) As Button
If con.State = ConnectionState.Open Then
con.Close()
End If
con.Open()
Dim btn As Button()
Dim x As Integer = 1
Dim requete As String
cdmat = CType(sender, Button).Text
'Response.Redirect("TestGroupes.aspx")
requete = "SELECT ENSEIGNEMENTS.Gr FROM ENSEIGNANT INNER JOIN ENSEIGNEMENTS ON ENSEIGNANT.Code_Ens = ENSEIGNEMENTS.Code_Ens WHERE (((ENSEIGNEMENTS.Code_Mat)='" + cdmat + "') AND ((ENSEIGNANT.[NomUser])='" + un + "') AND ((ENSEIGNEMENTS.[Sem])='S1'))"
Dim commande As New SqlCommand
commande = New SqlCommand(requete, con)
Dim reader As SqlDataReader = commande.ExecuteReader()
While reader.Read()
cr1(x) = New Button()
cr1(x).Text = reader("Gr").ToString
cr1(x).ID = "bt" & x.ToString
Panel2.Controls.Add(cr1(x))
AddHandler cr1(x).Click, AddressOf Groupe
x = x + 1
End While
End Sub
Protected Sub Groupe(sender As Object, e As EventArgs)
MsgBox("hhhhh")
End Sub
My problem is that AddHandler cr(y).Click, AdressOf btnc and WenForm2_load work well but AddHandler cr1(x).Click, AdressOf Groupe does not: when I click on a button in Panel2 nothing happens.
You always create the primary buttons (Code_Mat), but you also need to re-create the secondary buttons (Gr) when it posts back, so you'll need to save the variable(s) used to create those secondary buttons.
As a demonstration, I created a new Web Forms project named "testing" with one page named "index.aspx":
<%# Page Language="vb" AutoEventWireup="false" CodeBehind="index.aspx.vb" Inherits="testing.index" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Panel ID="Panel1" runat="server"></asp:Panel>
<asp:Panel ID="Panel2" runat="server"></asp:Panel>
</div>
<asp:Literal id="msg" runat="server">msg</asp:Literal>
</form>
</body>
</html>
Using this code-behind:
Public Class index
Inherits System.Web.UI.Page
Sub Groupe(sender As Object, e As EventArgs)
Dim bn = DirectCast(sender, Button)
msg.Text = bn.CommandArgument
End Sub
Sub CreateSecondaryButtonsHelper(codeMat As String)
Panel2.Controls.Clear()
For i = 1 To 3
Dim bn As New Button With {.Text = "Gr" & i & codeMat, .ID = "bnB" & i, .CommandArgument = "Hello from " & codeMat & i}
AddHandler bn.Click, AddressOf Groupe
Panel2.Controls.Add(bn)
Next
End Sub
Sub CreateSecondaryButtons(ByVal sender As Object, ByVal e As System.EventArgs)
Dim clickedButton = DirectCast(sender, Button)
CreateSecondaryButtonsHelper(clickedButton.Text)
Session("CodeMat") = clickedButton.Text
End Sub
Sub CreateMainButtons()
For i = 1 To 3
Dim bn As New Button With {.Text = "CodeMat" & i, .ID = "bnA" & i}
AddHandler bn.Click, AddressOf CreateSecondaryButtons
Panel1.Controls.Add(bn)
Next
If Session("CodeMat") IsNot Nothing Then
CreateSecondaryButtonsHelper(CStr(Session("CodeMat")))
End If
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
CreateMainButtons()
End Sub
End Class
It is rather dull, but I think it shows what you want to do.
N.B. You should make a new SqlConnection each time you use it and call .Dispose() on it as soon as you've finished using it. Also, using SQL parameters to pass the values instead of making up a string with them will make it more reliable and avoid SQL injection attacks.
Related
I've been reading posts and articles and just getting a little confused and consequently burning through time I don't have at the moment
Can someone look at my code and tell me where I've gone wrong?
Partial Class PayerContacts
Inherits System.Web.UI.Page
Dim connStrDRContacts As String = ConfigurationManager.ConnectionStrings("DRContacts_SQL").ConnectionString
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
navBuild()
End Sub
Protected Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init
If IsPostBack Then
LoadContacts(ViewState("objSender"))
End If
End Sub
Private Function navBuild() As Integer
Dim SQLstrDRs As String = "SELECT * FROM DRList"
Dim DbConnDRs As SqlConnection = New SqlConnection(connStrDRContacts)
DbConnDRs.Open()
Dim dtDRsTemp As New DataTable
Dim SQLAdapterDRs As New SqlDataAdapter(SQLstrDRs, DbConnDRs)
SQLAdapterDRs.Fill(dtDRsTemp)
'Loop through each row of the DataView to create HTML table data
Dim NewTableRow As New TableRow
For Each row As DataRow In dtDRsTemp.Rows
'CREATE table with button to display contacts related to client (one to many)
Dim NewTableButton As LinkButton = New LinkButton
NewTableButton.ID = "btnDRName" & NewTableText
NewTableButton.ViewStateMode = UI.ViewStateMode.Enabled
AddHandler NewTableButton.Click, AddressOf LoadContacts
Next
Return 0
End Function
Protected Sub LoadContacts(sender As Object, e As EventArgs)
Dim LoopCount As Integer = 0
Dim SQLstrLoadTable As String = "SELECT * FROM ContactList WHERE DRVendor = '" & sender.Text.ToString & "'"
and so on....
SQLAdapterLoadTable.Fill(dtLoadTableTemp)
Dim NewTableRow As New TableRow
For Each row As DataRow In dtLoadTableTemp.Rows
'CREATE Accordion to display data
NewAccordion.ID = "ContactAccordion" & LoopCount
NewAccordion.Visible = True
blah, blah...
'SET Pane
NewAccordionPane.HeaderContainer.ID = "PaneHeader" & LoopCount
NewAccordionPane.ContentContainer.ID = "PaneContent" & LoopCount
'CREATE button to open ModalPopup to EDIT each record
Dim imgGear As New ImageButton
imgGear.ID = "btnGear" & row!ID.ToString
imgGear.ViewStateMode = UI.ViewStateMode.Enabled
AddHandler imgGear.Click, AddressOf EditRecord
'LOAD Pane
NewAccordionPane.HeaderContainer.Controls.Add(NewHeaderTable)
NewAccordionPane.ContentContainer.Controls.Add(New LiteralControl(NewTableText))
ViewState("objSender") = sender
End Sub
Protected Sub EditRecord(ByVal sender As Object, ByVal e As EventArgs)
'Open ModalPopup to edit record
popup.Show()
pnlAddEdit.Visible = True
End Sub
End Class
The Infinities Loop articles on ViewState and Dynamic Controls should really be read by every Webforms developer: -
http://mocha.mojoskins.com/SharedFiles/Download.aspx?pageid=566&mid=786&fileid=38
http://weblogs.asp.net/infinitiesloop/TRULY-Understanding-Dynamic-Controls-_2800_Part-1_2900_
The examples are in C# but you should be able to figure out what's going on, it's the same base class library after all.
Protected Sub GridView1_RowUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewUpdateEventArgs) Handles GridView1.RowUpdating
sqlqrystrng = "UPDATE temp_zone set zone_id = #zoneid, zone_name = #zonename WHERE auto_id = #autoid"
Dim strautoid As String = GridView1.Rows(e.RowIndex).Cells(1).Text
'Dim strautoid As String = Int(GridView1.SelectedRow.Cells(0).Text.ToString())
grid_view_load()
End Sub
sqlqrystrng = "UPDATE temp_zone set zone_id = #zoneid, zone_name = #zonename WHERE auto_id = #autoid"
Dim strautoid As String = GridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Text
grid_view_load()
Dim Gridview1 As New DataTable
For i As Integer = 0 To Gridview1.Rows.Count - 1
Gridview1.Rows(i).Item(0).ToString()
Next
End Sub
I used a DataTable instead of a gridview because the project I have open is a windows service not a form app but it should work the same
<%# Page Language="VB" %>
<%# Import Namespace="System.Data" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
Protected Sub Page_Load()
If Not Page.IsPostBack Then
' Create a new table.
Dim taskTable As New DataTable("TaskList")
' Create the columns.
taskTable.Columns.Add("Id", GetType(Integer))
taskTable.Columns.Add("Description", GetType(String))
taskTable.Columns.Add("IsComplete", GetType(Boolean))
'Add data to the new table.
For i = 0 To 19
Dim tableRow = taskTable.NewRow()
tableRow("Id") = i
tableRow("Description") = "Task " + i.ToString()
tableRow("IsComplete") = False
taskTable.Rows.Add(tableRow)
Next
'Persist the table in the Session object.
Session("TaskTable") = taskTable
'Bind data to the GridView control.
BindData()
End If
End Sub
Protected Sub TaskGridView_PageIndexChanging(ByVal sender As Object, ByVal e As GridViewPageEventArgs)
TaskGridView.PageIndex = e.NewPageIndex
'Bind data to the GridView control.
BindData()
End Sub
Protected Sub TaskGridView_RowEditing(ByVal sender As Object, ByVal e As GridViewEditEventArgs)
'Set the edit index.
TaskGridView.EditIndex = e.NewEditIndex
'Bind data to the GridView control.
BindData()
End Sub
Protected Sub TaskGridView_RowCancelingEdit()
'Reset the edit index.
TaskGridView.EditIndex = -1
'Bind data to the GridView control.
BindData()
End Sub
Protected Sub TaskGridView_RowUpdating(ByVal sender As Object, ByVal e As GridViewUpdateEventArgs)
'Retrieve the table from the session object.
Dim dt = CType(Session("TaskTable"), DataTable)
'Update the values.
Dim row = TaskGridView.Rows(e.RowIndex)
dt.Rows(row.DataItemIndex)("Id") = (CType((row.Cells(1).Controls(0)), TextBox)).Text
dt.Rows(row.DataItemIndex)("Description") = (CType((row.Cells(2).Controls(0)), TextBox)).Text
dt.Rows(row.DataItemIndex)("IsComplete") = (CType((row.Cells(3).Controls(0)), CheckBox)).Checked
'Reset the edit index.
TaskGridView.EditIndex = -1
'Bind data to the GridView control.
BindData()
End Sub
Private Sub BindData()
TaskGridView.DataSource = Session("TaskTable")
TaskGridView.DataBind()
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>GridView example</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="TaskGridView" runat="server"
AutoGenerateEditButton="True"
AllowPaging="true"
OnRowEditing="TaskGridView_RowEditing"
OnRowCancelingEdit="TaskGridView_RowCancelingEdit"
OnRowUpdating="TaskGridView_RowUpdating"
OnPageIndexChanging="TaskGridView_PageIndexChanging">
</asp:GridView>
</div>
</form>
</body>
</html>
I'm trying to create a pager in a repeater control. The content is being pulled from the database and is displaying but when I click on the previous and next buttons they don't page, that is, I stay on the same content. Would anyone be able to see the error from the code below? No errors or showing so I think it is something minor but I have been banging my head against a wall trying to find it
Markup:
<asp:Repeater ID="ArtRepeater" runat="server">
<HeaderTemplate>
<h2>Items in Selected Category:</h2>
</HeaderTemplate>
<ItemTemplate>
<li>
<asp:HyperLink runat="server" ID="HyperLink"
NavigateUrl='<%# Eval("MovieID", "Default2.aspx?ArtID={0}")%>'>
<%# DataBinder.Eval(Container.DataItem, "MovieTitle")%>
</asp:HyperLink>
</li>
</ItemTemplate>
Code Behind:
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
doPaging()
End Sub
Function getTheData() As DataTable
Dim DS As New DataSet()
Dim strConnect As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source = " & _
Server.MapPath("/App_Data/MovieBoard.accdb"))
Dim objOleDBAdapter As New OleDbDataAdapter("SELECT MovieID, MovieTitle FROM Movies", strConnect)
objOleDBAdapter.Fill(DS, "Movies")
Return DS.Tables("Movies").Copy
End Function
Sub doPaging()
pagedData.DataSource = getTheData().DefaultView
pagedData.AllowPaging = True
pagedData.PageSize = 1
Try
pagedData.CurrentPageIndex = Int32.Parse(Request.QueryString("Page")).ToString()
Catch ex As Exception
pagedData.CurrentPageIndex = 0
End Try
btnPrev.Visible = (pagedData.IsFirstPage)
btnNext.Visible = (Not pagedData.IsLastPage)
pageNumber.Text = (pagedData.CurrentPageIndex + 1) & " of " & pagedData.PageCount
ArtRepeater.DataSource = pagedData
ArtRepeater.DataBind()
End Sub
After banging my head against a wall I found a solution. I forgot to connect the buttons to the repeater control. Here's a solution:
Imports System.Data
Imports System.Data.OleDb
Partial Class Default2
Inherits System.Web.UI.Page
Dim pagedData As New PagedDataSource
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
doPaging()
End Sub
Function getTheData() As DataTable
Dim DS As New DataSet()
Dim strConnect As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source = " & _
Server.MapPath("/App_Data/MovieBoard.accdb"))
Dim objOleDBAdapter As New OleDbDataAdapter("SELECT MovieID, MovieTitle FROM Movies", strConnect)
objOleDBAdapter.Fill(DS, "Movies")
Return DS.Tables("Movies").Copy
End Function
Sub doPaging()
pagedData.DataSource = getTheData().DefaultView
pagedData.AllowPaging = True
pagedData.PageSize = 1
Try
pagedData.CurrentPageIndex = Int32.Parse(Request.QueryString("Page")).ToString()
Catch ex As Exception
pagedData.CurrentPageIndex = 0
End Try
btnPrev.Visible = (Not pagedData.IsFirstPage)
btnNext.Visible = (Not pagedData.IsLastPage)
If Not pagedData.IsFirstPage Then
btnPrev.PostBackUrl = Request.CurrentExecutionFilePath + _
"?Page=" + CStr(pagedData.CurrentPageIndex - 1)
End If
If Not pagedData.IsLastPage Then
btnNext.PostBackUrl = Request.CurrentExecutionFilePath + _
"?Page=" + CStr(pagedData.CurrentPageIndex + 1)
End If
pageNumber.Text = (pagedData.CurrentPageIndex + 1) & " of " & pagedData.PageCount
ArtRepeater.DataSource = pagedData
ArtRepeater.DataBind()
I'm new to asp.net (after programming for years in classic asp). I'm trying to build a page which adds something to a string.
My code is following:
default.aspx
<body>
<form id="form1" runat="server">
<div>
<p><asp:textbox id="tb" runat="server"></asp:textbox></p>
<asp:Panel ID="tbPanel" runat="server"></asp:Panel>
</div>
</form>
</body>
Code behind:
Partial Class demo_Default
Inherits System.Web.UI.Page
Public Property gesStr As String
Set(value As String)
ViewState("gesStr") = value
End Set
Get
Dim o As Object = ViewState("gesStr")
If o Is Nothing Then
Return ""
Else
Return o
End If
End Get
End Property
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
Dim anzeigeStr As String = ""
If Page.IsPostBack Then
Else
gesStr = "1;"
End If
tb.Text = gesStr
Dim iButton As New Button
iButton.Text = "add"
iButton.CommandArgument = "1;"
AddHandler iButton.Click, AddressOf add
tbPanel.Controls.Add(iButton)
Me.anzeige()
End Sub
Private Sub add(ByVal sender As Object, ByVal e As EventArgs)
Dim myButton As Button = DirectCast(sender, Button)
Dim addString As String = myButton.CommandArgument
gesStr += addString
End Sub
Private Sub anzeige()
Dim gesArray As Array = Split(gesStr, ";")
For xLauf As Integer = 0 To UBound(gesArray) - 1
Dim anzLabel As New Label
anzLabel.Text = "<p>" & gesArray(xLauf) & "</p>"
tbPanel.Controls.Add(anzLabel)
Next
End Sub
End Class
The problem:
Pressing the button will cause a postBack, but the result of adding won't appear until the button is pressed a second time. The desired result is that the sub displays the correct array within the loop after the first time pressing the button.
Thank you so much for any help!
You need to call the function anzeige() and bind gesStr value to the textbox control each time the button is click. See the code below:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Page.IsPostBack Then
Else
gesStr = "1;"
End If
tb.Text = gesStr
Dim iButton As New Button
iButton.Text = "add"
iButton.CommandArgument = "1;"
iButton.CommandName = "1;"
AddHandler iButton.Click, AddressOf add
tbPanel.Controls.Add(iButton)
End Sub
Private Sub add(ByVal sender As Object, ByVal e As EventArgs)
Dim myButton As Button = DirectCast(sender, Button)
Dim addString As String = myButton.CommandArgument
gesStr += addString
anzeige()
End Sub
Private Sub anzeige()
Dim gesArray As Array = Split(gesStr, ";")
For xLauf As Integer = 0 To UBound(gesArray) - 1
Dim anzLabel As New Label
anzLabel.Text = "<p>" & gesArray(xLauf) & "</p>"
tbPanel.Controls.Add(anzLabel)
Next
'Bind gesStr value to the textbox control
tb.Text = gesStr
End Sub
Thanks to #Angkor Wat I achived a major step towards my goal: dynamic adding of pieces of strings to a string. But I came across another thing I cannot solve.
Here is the script:
<%# Page Language="VB" AutoEventWireup="false" CodeFile="addtostring.aspx.vb" Inherits="demo_addtostring" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<p><asp:textbox id="tb" runat="server"></asp:textbox></p>
<asp:Panel ID="tbPanel" runat="server"></asp:Panel>
</div>
</form>
</body>
</html>
This is the code behind:
Partial Class demo_addtostring
Inherits System.Web.UI.Page
Public Property gesStr As String
Set(value As String)
ViewState("gesStr") = value
End Set
Get
Dim o As Object = ViewState("gesStr")
If o Is Nothing Then
Return ""
Else
Return o
End If
End Get
End Property
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
If Page.IsPostBack Then
Else
gesStr = "1;"
End If
tb.Text = gesStr
Dim iButton As New Button
iButton.Text = "add"
iButton.CommandArgument = "1;"
iButton.CommandName = "1;"
AddHandler iButton.Click, AddressOf add
tbPanel.Controls.Add(iButton)
If Page.IsPostBack Then
Else
anzeige()
End If
End Sub
Private Sub add(ByVal sender As Object, ByVal e As EventArgs)
Dim myButton As Button = DirectCast(sender, Button)
Dim addString As String = myButton.CommandArgument
gesStr += addString
tb.Text = gesStr
anzeige()
End Sub
Private Sub anzeige()
Dim gesArray As Array = Split(gesStr, ";")
For xLauf As Integer = 0 To UBound(gesArray) - 1
Dim anzeigeDiv As New System.Web.UI.HtmlControls.HtmlGenericControl("div")
Dim anzLabel As New Label
anzLabel.Text = gesArray(xLauf)
anzeigeDiv.Controls.Add(anzLabel)
Dim iButton2 As New Button
iButton2.Text = xLauf.ToString
iButton2.ID = "test" & xLauf.ToString
iButton2.CommandArgument = "1;"
iButton2.CommandName = "1;"
AddHandler iButton2.Click, AddressOf add
anzeigeDiv.Controls.Add(iButton2)
tbPanel.Controls.Add(anzeigeDiv)
Next
End Sub
End Class
Clicking on the add-button should add "1;" to gesStr - the dynamic loop-generated buttons should do the same -.- Does anyone have an idea? I would be very thankful for help...
In order for the postback to know about the event handler from the button, the button needs to be recreated prior to the point in the lifecycle where the handler is invoked. In other words, you will always need to recreate the buttons within your Page_Load.
Here is a modification to your code which works:
<form id="form1" runat="server">
<div>
<p><asp:textbox id="tb" runat="server"></asp:textbox></p>
<br />
<asp:Button runat="server" ID="btnAdd" Text="add" CommandArgument="1;" />
<asp:Panel ID="tbPanel" runat="server"></asp:Panel>
</div>
</form>
And code-behind:
Public Property gesStr As String
Get
Dim o As Object = ViewState("gesStr")
If o Is Nothing Then
Return ""
Else
Return DirectCast(o, String)
End If
End Get
Set(value As String)
ViewState("gesStr") = value
End Set
End Property
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
gesStr = "1;"
End If
tb.Text = gesStr
End Sub
Private Sub add(ByVal sender As Object, ByVal e As CommandEventArgs) Handles btnAdd.Command
Dim addString As String = e.CommandArgument
gesStr += addString
tb.Text = gesStr
CreateNewButton(tbPanel.Controls.Count, addString.Substring(0, addString.Length - 1))
End Sub
Protected Overrides Sub CreateChildControls()
MyBase.CreateChildControls()
Dim gesArray As Array = Split(gesStr, ";")
For xLauf As Integer = 0 To UBound(gesArray) - 1
CreateNewButton(xLauf, gesArray(xLauf))
Next
End Sub
Private Sub CreateNewButton(ByVal xLauf As Integer, ByVal labelText As String)
Dim anzeigeDiv As New Panel
anzeigeDiv.ID = "div" & xLauf.ToString()
Dim anzLabel As New Label
anzLabel.Text = labelText
anzeigeDiv.Controls.Add(anzLabel)
Dim iButton2 As New Button
iButton2.Text = xLauf.ToString
iButton2.ID = "test" & xLauf.ToString()
iButton2.CommandArgument = "1;"
iButton2.CommandName = "1;"
AddHandler iButton2.Command, AddressOf add
anzeigeDiv.Controls.Add(iButton2)
tbPanel.Controls.Add(anzeigeDiv)
End Sub
I've moved the add button, which will always exist, into the aspx page, so that the dynamic panel will only contain the buttons which have been added based on gesStr value.
Dynamic controls must be re-created in every postback see this article for more information.