ASP.NET (WinForms) WebAdaptor - can't fire PostBack event? - asp.net

When using a Web Adapter class (inherited from WebControlAdapter) to render an asp:RadioButton control as I want, via the
Protected Overrides Sub RenderContents(ByVal output As HtmlTextWriter)
sub, it all works fine, even the AutoPostBack (if I call it) - but, on PostBack, the control's CheckedChanged event isn't being fired. Any ideas as to why will be gratefully received!
Imports System.Web.UI.WebControls.Adapters
Public Class myRadio
Inherits WebControlAdapter
Protected Overrides Sub RenderBeginTag(ByVal writer As System.Web.UI.HtmlTextWriter)
' MyBase.RenderBeginTag(writer)
End Sub
Protected Overrides Sub RenderEndTag(ByVal writer As System.Web.UI.HtmlTextWriter)
' MyBase.RenderEndTag(writer)
End Sub
Protected Overrides Sub RenderContents(ByVal output As HtmlTextWriter)
Dim ctrl As RadioButton = CType(Me.Control, RadioButton)
Dim sb As New StringBuilder
Dim cntxt As HttpContext = HttpContext.Current
Try
sb.Append("<label><input class=""")
sb.Append(ctrl.CssClass)
sb.Append(""" type=""radio""")
sb.Append(" name=""")
sb.Append(ctrl.GroupName)
sb.Append("""")
sb.Append(" value=""")
sb.Append(ctrl.Text)
sb.Append("""")
sb.Append(" id=""")
sb.Append(ctrl.ID)
sb.Append("""")
If ctrl.Checked Then sb.Append(" checked=""checked"" ")
If ctrl.AutoPostBack Then
sb.Append(" onclick=""javascript:setTimeout('__doPostBack(\'" & ctrl.ID & "\',\'\')', 0)"" ")
End If
sb.Append("> ")
sb.Append(ctrl.Text)
sb.Append("</label>")
Catch ex As Exception
sb = New StringBuilder
sb.Append("Error building Control:<br />")
sb.Append(ex.Message)
End Try
output.Write(sb.ToString)
End Sub
End Class

Related

ASP VB Stuck on Dynamic Controls, Viewstate, and Postback. Could really use some help to get back on track

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.

ASP.NET LinkButton in GridView causing full postback

This one is REALLY driving me nuts. I've read, and tried, most of the workarounds but still it posts back!!
All the markup is generated dynamically from code-behind and inserted into a page that is part of a Master Page, from the init event.
There are a series of nested tabs, the tab content for the most part is data in a GridView. Each Gridview is set in it's own update panel. Every time a LinkButton in the GridView is clicked there is a full postback causing the tabs to reset (any button outside of the GridView and in the UpdatePanel doesn't cause a full postback.
LinkButtons are generated like this
Dim Select_Field As New CommandField
With Select_Field
.HeaderText = "View Transactions"
.SelectText = "View Transactions"
.ShowSelectButton = True
End With
GV.Columns.Add(Select_Field)
Registering with ToolKitScriptManager
Private Sub AssessmentsMain_RowDataBound(sender As Object, e As GridViewRowEventArgs)
Try
If e.Row.RowType = DataControlRowType.DataRow Then
Dim vID As Integer = Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, "ID"))
Dim LB As LinkButton = CType(e.Row.Cells(4).Controls(0), LinkButton)
LB.ID = "AssMain_" & vID
AjaxControlToolkit.ToolkitScriptManager.GetCurrent(Me).RegisterAsyncPostBackControl(LB)
End If
Catch ex As Exception
Dim vError As New SendError
vError.MailError("840", PageName, ex)
ShowError()
End Try
End Sub
and the generated markup for one row is like this
<tr class="GridView" style="color:#333333;background-color:#F7F6F3;">
<td>10</td>
<td>Adam White</td>
<td>4224 Res Road</td>
<td align="right">$6,850.65</td>
<td>
<a id="ctl00_ContentPlaceHolder1_AssessmentsMainGV_ctl02_AssMain_10" href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$AssessmentsMainGV','Select$0')" style="color:#333333;">View Transactions</a>
The GridView class
Public Class HAS_Gridview
Inherits GridView
Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
MyBase.OnInit(e)
CellPadding = 4
GridLines = WebControls.GridLines.None
ForeColor = Drawing.ColorTranslator.FromHtml("#333333")
ClientIDMode = UI.ClientIDMode.AutoID
With MyBase.FooterStyle
.BackColor = Drawing.ColorTranslator.FromHtml("#E2DED6")
.Font.Bold = True
.ForeColor = Color.White
End With
RowStyle.BackColor = Drawing.ColorTranslator.FromHtml("#F7F6F3")
RowStyle.ForeColor = Drawing.ColorTranslator.FromHtml("#333333")
PagerStyle.HorizontalAlign = WebControls.HorizontalAlign.Center
PagerStyle.ForeColor = Color.Black
PagerStyle.BackColor = Drawing.ColorTranslator.FromHtml("#E2DED6")
With MyBase.SelectedRowStyle
.BackColor = Drawing.ColorTranslator.FromHtml("#E2DED6")
.Font.Bold = True
.ForeColor = Drawing.ColorTranslator.FromHtml("#333333")
End With
With MyBase.HeaderStyle
.BackColor = Drawing.ColorTranslator.FromHtml("#E2DED6")
.Font.Bold = True
.ForeColor = Color.Black
.CssClass = "GridView"
End With
EditRowStyle.BackColor = Drawing.ColorTranslator.FromHtml("#999999")
With MyBase.AlternatingRowStyle
.BackColor = Color.White
.ForeColor = Drawing.ColorTranslator.FromHtml("#284775")
.CssClass = "GridView"
End With
With MyBase.RowStyle
.CssClass = "GridView"
End With
End Sub
End Class
Have you tried adding trigger programmatically instead of registering in AjaxControlToolkit:
Dim trigger As New AsyncPostBackTrigger()
trigger.ControlID = LB.ID
trigger.EventName = "Click"
MyUpdatePanel.Triggers.Add(trigger)
It looks like the postback is caused by href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$AssessmentsMainGV','Select$0')" in the generated markup for the anchor tag.
Try to define your own _doPostBack.
If you haven't checked post a and post b already, they offer a couple of ways to do that.
In the end the only way I could get this to work was
Create a class for a LinkButton Template
Public Class LinkButtonTemplate
Implements ITemplate
Private m_ColumnName As String
Event LinkButtonItem_Clicked(sender As LinkButton, e As EventArgs)
Public Property ColumnName() As String
Get
Return m_ColumnName
End Get
Set(ByVal value As String)
m_ColumnName = value
End Set
End Property
Public Sub New()
End Sub
Public Sub New(ByVal ColumnName As String)
Me.ColumnName = ColumnName
End Sub
Public Sub InstantiateIn(container As Control) Implements ITemplate.InstantiateIn
Dim LB As New LinkButton()
With LB
.ID = "LB_" & ColumnName
.Text = ColumnName
.OnClientClick = "LinkButtonClick(this);"
End With
container.Controls.Add(LB)
End Sub
End Class
Add this javascript so that it would post the ID to a hidden field and click a hidden button
Private Sub LoadLinkButtonClick()
Try
Dim SB As New StringBuilder
SB.Append("function LinkButtonClick(LinkButton){ ")
SB.Append("setTimeout(function() { ")
SB.Append("$get('" & GridViewLBClicked.ClientID & "').click(); ")
SB.Append(" }, 300); ")
SB.Append("var sendingID = LinkButton.id; ")
SB.Append("document.getElementById('" & HiddenField1.ClientID & "').value = sendingID; ")
SB.Append("} ")
ScriptManager.RegisterStartupScript(Me, Me.GetType(), "LoadLinkButton", SB.ToString, True)
Catch ex As Exception
Dim vError As New SendError
vError.MailError("1229", PageName, ex)
End Try
End Sub
On the RowDataBound event capture the ID we need and add it to the LinkButton ID (so now we know both the sending GridView and the selected row)
Private Sub AssessmentsMain_RowDataBound(sender As Object, e As GridViewRowEventArgs)
Try
If e.Row.RowType = DataControlRowType.DataRow Then
Dim vID As Integer = Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, "ID"))
Dim LB As LinkButton = CType(e.Row.Cells(4).Controls(0), LinkButton)
LB.ID = "AssMain_" & vID
End If
Catch ex As Exception
Dim vError As New SendError
vError.MailError("840", PageName, ex)
ShowError()
End Try
End Sub
From the hidden button click we can recover all the data we need to make the async postback
Private Sub RaiseLinkButton_Click(sender As Object, e As EventArgs)
Try
Dim vFunction As New Functions
Dim vValue As String = HiddenField1.Value
Dim vSplit = vValue.Split("_")
Dim i As Integer = 0
For Count As Integer = 0 To vSplit.Length - 1
i += 1
Next
Dim DGName As String = vSplit(i - 2)
Select Case DGName
Case "AssMain"
Dim MV As MultiView = vFunction.FindControlRecursive(BodyMain, "AssessmentMultiView")
Dim GV As CustomControl.HAS_Gridview = vFunction.FindControlRecursive(BodyMain, "AssessmentDetailGV")
With GV
.DataSource = AssessmentsDetail_ReturnDataSet()
.DataBind()
.PageIndex = 0
End With
MV.ActiveViewIndex = 1
Dim vPanel As UpdatePanel = vFunction.FindControlRecursive(BodyMain, "AssessmentUpdatePanel")
vPanel.Update()
End Select
Catch ex As Exception
Dim vError As New SendError
vError.MailError("953", PageName, ex)
ShowError()
End Try
End Sub

Object reference not set to an instance of an object in ASP(vb)

I came across to this code that creates control dynamically. I tried it. However, whenever I run it, Object reference not set to an instance of an object error pops out and points out to a certain line in the code( i put ---> on the line). I'm a newbie in this programming language. I don't know what to do.
Here's the code I got:
Imports System.Collections.Generic
'Imports System.Data.Odbc
Partial Public Class main
Inherits System.Web.UI.Page
Private controlCounter As Integer = 0
Private myControlList As List(Of String)
Protected Overrides Sub LoadViewState(ByVal savedState As Object)
MyBase.LoadViewState(savedState)
myControlList = DirectCast(ViewState("myControlList"), List(Of String))
For Each ctlID As String In myControlList
controlCounter += 1
Dim hyper As New HyperLink()
hyper.ID = ctlID
Dim lineBreak As New LiteralControl("<br />")
PlaceHolder1.Controls.Add(hyper)
PlaceHolder1.Controls.Add(lineBreak)
Next
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
If Not IsPostBack Then
myControlList = New List(Of String)()
ViewState("myControlList") = myControlList
End If
End Sub
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
controlCounter += 1
Dim hyper As New HyperLink()
hyper.Text = "a new text Box"
hyper.ID = "hyperlink" + controlCounter.ToString()
Dim lineBreak As New LiteralControl("<br />")
PlaceHolder1.Controls.Add(hyper)
PlaceHolder1.Controls.Add(lineBreak)
--> myControlList.Add(hyper.ID)
ViewState("myControlList") = myControlList
End Sub
End Class
please help me out. Thanks.
A button click initiates a postback, and you only set myControlList to a thing if the request is not a post back, so it's nothing.
If you're wanting to create the list on page load, and then only keep adding to it with subsequent clicks, say, then you'll need to shove myControlList into the Session, or something, after creating it, then on button click retrieve it again, add to it, and re-set it in the Session.
To do this add and getting from the Session stuff, do,
Session("someDistinctKey") = myControlList;
myControlList = CType(Session("someDisctintKey"), List(Of String))
respectively.

jQuery and reloading server control

I am new to jQuery and have some questions. I have created a server web control (it implements a webControl) and wanted to know how to refresh the control when an event fires. In other words:
I have a server control that has a drop-down list.
When the user makes a selection, I want to cause a partial post back and reload the control (to set some public properties values that can be read by the page consuming the control).
Can this be done just by using jQuery or would I still need to update the panels?
Here is my server control:
<Assembly: WebResource("com.myControls.WebControls.miniActiveDirectorySearchStyle.css", "text/css", PerformSubstitution:=True)>
Namespace com.myControls.WebControls
< _
System.Drawing.ToolboxBitmap(GetType(Button), "myControls.WebControls.ActiveDirectorySearch.bmp"), ToolboxData("<{0}:miniActiveDirectorySearch ID='miniActiveDirectorySearch{0}' runat=""server""> </{0}:miniActiveDirectorySearch>"), _ ClientCssResource("com.myControls.WebControls.miniActiveDirectorySearchStyle.css")> _
Public Class miniActiveDirectorySearch
Inherits WebControl
Public ddlValue As New TextBox
Public ddlText As New TextBox
Private tblMainLayout As HtmlTable
Private divControlContainer As New HtmlGenericControl()
Private modalExtender As New ModalPopupExtender()
Private tbSearchUser As New TextBox
''' <summary>
'''X Offset for modal dialog
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
<Description("Mouser Over Highlight Color")> Public Property mouseOverColor As String = "#9db3d9"
''' <summary>
'''X Offset for modal dialog
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
<Description("Drop Down List Width")> Public Property ddlWidth As String = "100"
Private Sub attachWebResources()
Dim styleLink As String = "<link rel='stylesheet' text='text/css' href='{0}' />"
Dim location As String = Page.ClientScript.GetWebResourceUrl(Me.[GetType](), "myControls.WebControls.miniActiveDirectorySearchStyle.css")
Dim styleInclude As New LiteralControl([String].Format(styleLink, location))
DirectCast(Page.Header, HtmlControls.HtmlHead).Controls.Add(styleInclude)
ScriptManager.RegisterClientScriptResource(Me, Me.GetType, "com.myControls.ActiveDirectory.WebControls.jquery-1.4.1.min.js")
ScriptManager.RegisterClientScriptResource(Me, Me.GetType, "com.myControls.ActiveDirectory.WebControls.miniActiveDirectorySearch.js")
End Sub
Protected Overrides Sub CreateChildControls()
createDynamicControls()
MyBase.CreateChildControls()
End Sub
Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
attachWebResources()
MyBase.OnInit(e)
End Sub
Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
MyBase.OnLoad(e)
End Sub
Private Sub createDynamicControls()
Controls.Clear()
Try
tblMainLayout = buildMaintable()
Controls.Add(tblMainLayout)
Catch ex As Exception
Throw New ApplicationException("Exception Occurred Creating Control.", ex.InnerException)
End Try
End Sub
Private Function buildMaintable() As HtmlTable
tblMainLayout = New HtmlTable
Dim divImage As New HtmlGenericControl("div")
ddlText = New TextBox
ddlValue = New TextBox
With ddlText
.ID = "ddlText"
End With
With ddlValue
.ID = "ddlValue"
End With
With divControlContainer
.ID = Me.UniqueID & "_divSearchResults"
.Attributes.Add("onClick", "hideMe(this)")
End With
With divImage
.ID = Me.UniqueID & "_ImageDiv"
End With
With tblMainLayout
.CellPadding = 0
.CellSpacing = 0
.Style.Add("border-collapse", "collapse")
Dim tr As New HtmlTableRow
With tr
Dim td As New HtmlTableCell
With td
With tbSearchUser
.ID = Me.UniqueID & "_tbSearchName"
.Attributes.Add("onKeyPress", "searchKeyPress(event, this.id, '" & divControlContainer.UniqueID & "', '" & mouseOverColor & "','" & ddlText.ID & "','" & ddlValue.ID & "')")
.Attributes.Add("onmouseover", "document.getElementById('" & divImage.ID & "').className='DivSearchMouseOverMini', tbMouseOver(this)")
.Attributes.Add("OnmouseOut", "document.getElementById('" & divImage.ID & "').className='divSearchDefaultMini',tbMouseOut(this)")
.Width = ddlWidth
.Attributes.Add("onClick", "showSearchResults('" & divControlContainer.UniqueID & "')")
.CssClass = "tbSearchDefault"
End With
.Controls.Add(tbSearchUser)
.Controls.Add(ddlText)
.Controls.Add(ddlValue)
End With
.Controls.Add(td)
td = New HtmlTableCell
With td
With divImage
.Attributes.Add("class", "divSearchDefaultMini")
.Attributes.Add("onmouseover", "this.className='DivSearchMouseOverMini',document.getElementById('" & tbSearchUser.ID & "').className='tbSearchMouseOver'")
.Attributes.Add("onmouseout", "this.className='divSearchDefaultMini', document.getElementById('" & tbSearchUser.ID & "').className='tbSearchDefault'")
.Attributes.Add("onClick", "showSearchResults('" & divControlContainer.UniqueID & "')")
End With
.Controls.Add(divImage)
End With
.Controls.Add(td)
End With
.Controls.Add(tr)
tr = New HtmlTableRow
With tr
Dim td As New HtmlTableCell
With td
.ColSpan = 2
.Controls.Add(divControlContainer)
End With
.Controls.Add(td)
End With
.Controls.Add(tr)
End With
Return tblMainLayout
End Function
End Class
This code creates a server control with a textbox and styles to mimick a dropdown list. This way, I can add some functionality to the drop down list. I would like to cause a partial post back when the user makes a change to the "dropdown list" or textbox. All my jQuery is done in another file that is added as a web resource.
Why not use an ajax call to the server page, which won't cause an actual post-back. Grab what you need and update it on the client in the response. Or, you can fire your server code to do that as well.
jQuery ajax is really easy to use. Just declare a static Webmethod on the server to handle whatever your request is supposed to accomplish.

ASP.NET VB Listbox DataBind Not Working

In my user control, I have a text boxes that I used to create a new membership user. Each listbox has a datasource set to membership.getallusers() to fill the listbox. When the listbox index is changed, it populates the text boxes to allow editing. What I want to accomplish is: have each user listbox refresh to show the new user that gets created. Even though I call databind() after successfully creating the user, it doesn't update. On the form load I check if listbox.items.count < 1, then call databind(), which does work correctly. Any ideas?
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
If ListBox3.Items.Count < 1 Then
For Each item As MembershipUser In Membership.GetAllUsers(0, Membership.GetAllUsers.Count + 1, Membership.GetAllUsers.Count)
ListBox3.Items.Add(item.UserName)
Next
Label1.Text = ListBox3.Items.Count
username = ListBox3.Items(0).ToString
Else
ListBox1.DataBind()
ListBox3.DataBind()
End If
user = Membership.GetUser
ListBox1.DataSource = Membership.GetAllUsers
ListBox1.DataBind()
ListBox2.DataSource = Roles.GetAllRoles
ListBox2.DataBind()
' ListBox3.DataSource = Membership.GetAllUsers
'ListBox3.DataBind()
End Sub
Protected Sub ListBox3_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox3.SelectedIndexChanged
txtUsername.Text = user.UserName
txtEmail.Text = user.Email
txtQuestion.Text = user.PasswordQuestion
End Sub
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try'Creates a new user
Dim status As System.Web.Security.MembershipCreateStatus
Membership.CreateUser(txtUsername.Text, txtPassword.Text, txtEmail.Text, txtQuestion.Text, txtAnswer.Text, True, status)
Label1.Text = "User " & txtUsername.Text & " was created"
'ListBox3.Items.Clear()
ListBox1.DataBind()
'ListBox3.DataBind()
Catch ex As Exception
Label1.Text = "Error:" & ex.Message
End Try
End Sub
You need to set the datasource again before you do the databind, like so:
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try'Creates a new user
Dim status As System.Web.Security.MembershipCreateStatus
Membership.CreateUser(txtUsername.Text, txtPassword.Text, txtEmail.Text, txtQuestion.Text, txtAnswer.Text, True, status)
Label1.Text = "User " & txtUsername.Text & " was created"
'ListBox3.Items.Clear()
ListBox1.DataSource = Membership.GetAllUsers() ' Necessary because the DB has changed
ListBox1.DataBind()
'ListBox3.DataBind()
Catch ex As Exception
Label1.Text = "Error:" & ex.Message
End Try
End Sub
When you call databind, you might think that that's the moment the Listbox will call the method you gave it as a datasource, but that's not the case. The moment you assign the datasource, the data is retrieved. When you actually call the Databind-method, the Listbox will create the necessary internal controls

Resources