Based on a choice of "Other" in a dropdown I want to add a label and textbox to a <p> tag. I have added runat=server in the <p> tag.
Protected Sub deptDdl_SelectedIndexChanged(sender As Object, e As System.EventArgs) Handles deptDdl.SelectedIndexChanged
'If the user chooses other for the department type add
'a label and textbox to allow them to fill in a department not listed
If deptDdl.SelectedValue.ToString = "Other" Then
Dim deptLbl As Label = New Label
deptLbl.Text = "Enter the Department Name"
Dim deptTb As TextBox = New TextBox
deptTb.MaxLength = 20
Page.FindControl("m_ContentPlaceHolder1_deptPtag").Controls.AddAt(2, deptLbl)
Page.FindControl("m_ContentPlaceHolder1_deptPtag").Controls.AddAt(3, deptTb)
End If
End Sub
I keep getting an unhandled exception stating Object reference not set to an instance of an object.
What am I missing?
If your <p>-tag is runat=server you should be able to reference it in the codebehind -file directly. Give it an ID deptPtag, then this should be autogenerated in the designer.vb-file:
Protected WithEvents deptPtag As Global.System.Web.UI.HtmlControls.HtmlGenericControl
But you also have to ensure that your dynamic controls are recreated on every postback(latest in Page_Load, events are too late for reloading the ViewState). Otherwise you won't be able to read deptTb.Text or handle it's TextChanged-event.
The ID must be the same on every postback to correctly load the ViewState.
My answer on this question explains your NullReferenceException.
It's a special behaviour of FindControl from within a MasterPage's content-page.
Related
how to create as many textbox at runtime on button click. And also what will be the id's of textboxes created at runtime and send the value of textbox to next page through session
please someone help me. I've stucked at this point for many days but could not solve it.
thanks
prasanna
To create a textbox at runtime you set it up in your Page_Init like this:
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
' Create dynamic controls here.
TextBox1 = New TextBox()
TextBox1.ID = "TextBox1"
TextBox1.Style("Position") = "Absolute"
TextBox1.Style("Top") = "25px"
TextBox1.Style("Left") = "100px"
Form1.Controls.Add(TextBox1)
TextBox2 = New TextBox()
TextBox2.ID = "TextBox2"
TextBox2.Style("Position") = "Absolute"
TextBox2.Style("Top") = "60px"
TextBox2.Style("Left") = "100px"
Form1.Controls.Add(TextBox2)
End Sub
Creating dynamic controls in ASP.Net can be a little tricky. The reason is any control created after the Page_Init will not be stored in the View State. This means for controls created after the Page_Init, on the page post back the data entered into the control will be lost. Furthermore events will not be fire for the those controls.
A good three part article can be found here
https://web.archive.org/web/20211020131055/https://www.4guysfromrolla.com/articles/081402-1.aspx
The Repeater control in the following test case contains two runat="server" DIVs. Each one of them gets a TextBox appened to them through the ItemCreated event of the Repeater. Both of the have AutoPostBack=True, and TextChanged event wired to txt_TextChanged. However, only the TextBox from the first level properly points to the event on the postBack of the page. The second level TextBox also causes the postBack to occur, but its value does not persist in the VIEWSTATE as well as the event does not fire.
Here's a direct link to the test case in a .zip file (uploaded to my personal website), as well as all the code needed. The project is built in VS2010 using .NET Framework 4, but the problem also exists in 1.1, 2, and 3.5.
Anybody has any ideas on what is wrong and how to make this work?
ASPX
<asp:Repeater ID="rep" runat="server">
<ItemTemplate>
<!-- first level works -->
<div id="divOutside" runat="server">
<!-- second level doesn't work -->
<div id="divInside" runat="server"></div>
</div>
</ItemTemplate>
</asp:Repeater>
Code-Behind
Public Class WebForm1
Inherits System.Web.UI.Page
Private Sub WebForm1_Init(sender As Object, e As System.EventArgs) Handles Me.Init
If Not IsPostBack Then
Dim Table As New DataTable()
Table.Columns.Add("Column1")
Dim Row As DataRow = Table.NewRow()
Row("Column1") = ""
Table.Rows.Add(Row)
rep.DataSource = Table
rep.DataBind()
End If
End Sub
Private Sub repTest_ItemCreated(sender As Object, e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rep.ItemCreated
' outside
Dim divOutside As HtmlGenericControl = DirectCast(e.Item.FindControl("divOutside"), HtmlGenericControl)
Dim txtInput As New TextBox
With txtInput
.ID = "txtInputOutside"
.AutoPostBack = True
.Text = "Event gets called, value persists accross postBack."
.Width = 400
End With
AddHandler txtInput.TextChanged, AddressOf txt_TextChanged
divOutside.Controls.Add(txtInput)
' inside
Dim divInside As HtmlGenericControl = DirectCast(e.Item.FindControl("divInside"), HtmlGenericControl)
txtInput = New TextBox
With txtInput
.ID = "txtInputInside"
.AutoPostBack = True
.Text = "Event NOT called, value is lost during postBack."
.Width = 400
End With
AddHandler txtInput.TextChanged, AddressOf txt_TextChanged
divInside.Controls.Add(txtInput)
End Sub
Protected Sub txt_TextChanged(sender As Object, e As EventArgs)
End Sub
End Class
Is there any reason why the textboxes have to be added to the divs dynamically? why not just put them in the aspx page with the repeater then on itemdatabound enable/disable or do whatever you need to do. That should work fine.
By the way, if you were to use panels instead of divs your on the fly approach will work.
Here's a link to Microsoft Connect, where I reported this is an official bug:
https://connect.microsoft.com/VisualStudio/feedback/details/652655/asp-net-bug-in-event-linking-of-2nd-level-dynamic-controls
It contains 2 PARTIAL workarounds that work in the uploaded files section, if anybody is interested or encounters the same problem, as well as details to what I found in the Workarounds tab.
To keep it short, it is the order of getting references to the containers and the order the TextBoxes are appended to their appropriate containers which either causes the issue or works as expected.
But, not to forget the most important point, the only reason the first-level TextBox is there in the first place is to showcase what I want as functionality. If the first-level TextBox does not get appended at all, then both workarounds fail to provide any sort of fix. Please keep that in mind when reviewing that problem - finding a workaround that revolves around changing the order of the items is not an actual solution or a fully working workaround!
Thanks everyone for the input!
I have GridView control in my asp.net page with auto generated fields
there is only footer template is present under asp:TemplateField.
I can bind this gridview with any of databae table as depend on user
selection. Now want to add new record in database so I have added text
boxes on footer template cells at runtime depend on number of columns
on table. But when I accessing these text boxes from footer template
on gridview_RowCommand event its not retriving textbox control.
this is the code:
SGridView.ShowFooter = True
For i As Integer = 0 To ctrList.Count
Dim ctr As Control = CType(ctrList.Item(i), Control)
SGridView.FooterRow.Cells(i + 1).Controls.Add(ctr)
Next
the ctrList contain Controls textBox, checkbox dropdowlist ect.
there is all ok
but when i wont to get the text or value or checked value of controls i can't cast the controls in rowcommand event
Here is the code:
If e.CommandName = "Add" Then
Dim ctrList As ControlCollection = SGridView.FooterRow.Controls
For Each ctr As Control In ctrList
If TypeOf ctr Is TextBox Then
Dim name As TextBox = CType(ctr, TextBox)
Dim val As String = name.Text
End If
Next
End If
this excample is for the textBox control.
Plese suggest me how can I get footer control textboxes. So that I can
save data in database.
When you are dealing with Dynamic controls you have to keep a close eye on the .net page lifecycle.
Control data is bound in the Load event, so your not able to access postback data in that event when your doing your conrol generation in the Load event too. I usualy try to create dynamic controls in the Init of the page, and do any values processing on the LoadComplete or PreRender event so I can make sure they have recieved their values from the postback before you try to read them.
Take a look at the full description of the ASP.NET page lifecycle events and whats going on. This should help you navigate the creation and use of Dynamic generated controls.
Try to create your Controls in the Grdiview's RowCreated Event which will be raised on every Postback.
Private Sub Grid1_RowCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles Grid1.RowCreated
Select Case e.Row.RowType
Case DataControlRowType.Footer
'add controls to row
End Select
End Sub
I have a custom control that inherits from .NET's CompositeControl class. This control overrides the CreateChildControls in order to build its child controls dynamically. I need the page to post back after a couple different javascript events occur on the client side.
In order to accomplish this, I create two hidden controls on the page so I can set their values with javascript, submit the page, and read the values out on server side. Here's is the code I use to create these two hiddens:
Protected Overrides Sub CreateChildControls()
hdEventName = New HiddenField()
Controls.Add(hdEventName)
hdEventName.ID = "hdEventName"
hdEventArgs = New HiddenField()
Controls.Add(hdEventArgs)
hdEventArgs.ID = "hdEventValue"
' other controls
' ...
End Sub
When a javascript event occurs I set the value attribute of the two hiddens and submit the page, like so:
hdEventName.value = 'EventName';
hdEventArgs.value = 'arg1,arg2';
document.forms[0].submit();
In the OnLoad method of my control, I attempt to check the Value property of the hdEventName and hdEventArgs controls, but it is always empty. However, Page.Request.Form(hdEventName.UniqueID) and Page.Request.Form(hdEventArgs.UniqueID) return correct values. The actual HTML in the markup also shows correct values after the page posts back.
Why is the Value property of the HtmlInputHiddens disconnected from the actual value that appears on the client?
Update
It appears that a control's properties get loaded from the form sometime after OnLoad occurs. Thus I was able to solve my problem by either moving the code that checks the two hidden fields into the OnPreRender method, or adding the following method to my code -
Private Sub Event_Handler(ByVal sender As Object, ByVal e As EventArgs)
Handles hdEventName.ValueChanged
' do stuff with hiddens
' ...
' reset the values back
hdEventName.Value = String.Empty
hdEventArgs.Value = String.Empty
End Sub
when the page posts back there's nothing to link the variable hdEventName to the control you previously created. what you're doing is akin to having an integer declared at the class level and setting it to 5 when you're creating child controls. there's nothing to maintain that value in that variable across postbacks.
if you want to get a reference to the control you created previously, you'd have to use
hdEventName = CType(Page.FindControl("hdEventName") , HiddenField)
(i'm guessing at this) or Request if you're only concerned with the value.
It appears that a control's properties get loaded from the form sometime after OnLoad occurs. Thus I was able to solve my problem by either moving the code that checks the two hidden fields into the OnPreRender method, or adding the following method to my code -
Private Sub Event_Handler(ByVal sender As Object, ByVal e As EventArgs)
Handles hdEventName.ValueChanged
' do stuff with hiddens
' ...
' reset the values back
hdEventName.Value = String.Empty
hdEventArgs.Value = String.Empty
End Sub
I have LinkButton and HiddenField in a list view. I want to get the hidden value from HiddenField, so I can store it in Session and when a LinkButton is clicked it transfer the hidden value ( stored in Session) to another page. But I get this error message "Object reference not set to an instance of an object." Here's the function:
Protected Sub lvTimeSheet_ItemCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewCommandEventArgs) Handles lvTimeSheet.ItemCommand
Dim id As HiddenField = TryCast(e.Item.FindControl("hfTimeSheetId"), HiddenField)
Dim myId As String = id.Value.ToString
Session("myId") = myId
Server.Transfer("Destination.aspx")
End Sub
The mark-up
</asp:LinkButton><asp:HiddenField ID="hfTimeSheetId1" runat="server" Value='<%# Eval("hfTimeSheetId") %>' />
Every time the LinkButton is clicked, it causes error with above error message. Thank you for any input.
My guess would be that the FindControl isn't finding the hfTimeSheetId control within the row. Do you have it designated as a managed control (i.e. runat="server")?
Also, it might help if you provided the ASPX code to see how you're defining the controls.
The FindControl is returning null, hense the exception. Try changing it to:
Dim id As HiddenField = TryCast(e.Item.FindControl("hfTimeSheetId1"), HiddenField)