Dynamic controls in postback - asp.net

I'm trying to add a set of LinkButtons to the PagerRow of a GridView in an UpdatePanel. I'm using the RowCreated event to instantiate and add these. The problem I have is the click handlers are only fired the second time.
I create the LinkButtons using
Protected Sub grd_RowCreated(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
If (e.Row.RowType = DataControlRowType.Pager) Then
Dim pageSizer = New GridViewPageSizer(grdItems)
e.Row.Cells(0).Controls.AddAt(0, pageSizer)
End If
End Sub
To create the LinkButtons themselves, I'm using
Dim lnkSize = New LinkButton() With { _,
.Text = size.ToString(), _
.CommandArgument = size.ToString(), _
.ID = "pageSizer" & size
}
AddHandler lnkSize.Click, AddressOf lnkPageSize_Click ' an EventHandler which just changes pagesize based on CommandArgument
liSize.Controls.Add(lnkSize)
The GridViewPageSizer inherits HtmlGenericControl and adds an event handler for the click of each button. On every postback, the pager row is recreated, so the old buttons are replaced with a new set and their event handlers only fire on the second click. If I check for !IsPostBack, the buttons disappear after the first click. I've tried rebinding the grid after the buttons are clicked and the pagesize changes but the same thing happens. Is there a way around this?

In order for an EventHandler to trigger correctly, you need to bind it on Page Init/PreInit.
Make a session indicator and on postback, check that session on Page Init.
If that satisfies the condition, instead of recreating it on RowCreated Event, recreate the controls together with the Events on Page Init instead.
This time, events will trigger correctly.

Related

Dynamically added link button disappeared on button click leaving an empty column

The datagrid reads from several xml files, so I create the columns dynamically, and added a templatefield as the last column.
A link button is added in the templatefield using RowDataBound.
Private Sub GridItem_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridItem.RowDataBound
Try
If e.Row.RowType = DataControlRowType.DataRow Then
Dim linkb As New LinkButton
linkb.Text = "Delete"
linkb.ID = "LinkDeleteItem"
linkb.OnClientClick = "javascript:DeleteItem('" & Convert.ToString(e.Row.RowIndex) & "')"
e.Row.Cells(GridItem.Columns.Count - 1).Controls.Add(linkb)
End If
Catch ex As Exception
lblMessage.Text = ex.Message
End Try
End Sub
Everything works fine.
But when I click a button outside the gridview, to open a window to add a new item to the grid, the linkbuttons disappear. But the column is still there.
If I just close the new window without saving a new data (which will prompt the grid to rebind), the column remains empty. I had to reload the gridview for the linkbuttons to appear.
Is it because the linkbuttons are created on rowdatabound? How should I solve this?
This is happening because the OnRowDataBound event of GridView is NOT called on next postback. This happens because by default viewstate of GridView is set true i.e. EnableViewState property of Gridview is true. When ViewState is on, Gridview stores data from the same and OnRowDataBound event is not called. Also, at this point View state will not be applied for your linkButtons as they aren't created in page_load.
Try setting EnableViewState property to false for your gridview:
<asp:GridView ID="CustomersGridView"
OnRowDataBound="CustomersGridView_RowDataBound"
EnableViewState="false"
.... />
OR you can also bind your GridView in page_Load as:
protected void Page_Load(object sender, EventArgs e)
{
CustomersGrIdView.DataBind();
}
Now after every postback your OnRowDataBound event will be called and hence the LinkButtons will be available everytime.
NOTE: Setting EnableViewState property to false for gridview can be a bad practice to an extent, especially in scenarios of heavy data usages. Same goes for Binding gridview every time.
When using dynamic controls, they exist only until the next postback.ASP.NET will not re-create a dynamically added control. If you need to re-create a control next time too on postback, you should perform the control creation in the PageLoad event handler.
This will give you benefit of using view state with your dynamic control. Even though view state is normally restored before the Page.Load event, if you create a control in the handler for the PageLoad event, ASP.NET will apply any view state information that it has after the PageLoad event handler ends.

Setting control text in parent form from modal popup

I have a problem I am trying to set the parent textbox from the modal popup.
Although I found the control from the modal popup with the below code
DirectCast(Parent.Page.Form.FindControl("ContentPlaceHolder1").FindControl("myAccordion").FindControl("txtTo"), TextBox).Text = str
This is being called on button click when the user has finished selecting from the Checkboxlist.
When the parent page is shown again though the textbox is empty.
The scenario of my user control is that a user is to select from a checkbox list which is a list of emails.
When done has been clicked then it is required that the selected emails be forwarded to the parent webpage.
Then the To Textbox in this case will be filled with the emails that the user has selected.
You should provide a public property in your UserControl for the selected item in the ListBox. This makes it easy to retrieve(or set) it from the page.
You should also declare an event that you can raise from the ListBox' SelectedIndexChanged event. On this way the page is able to handle this event and set the TextBox' Text accordingly.
For example(in UserControl with ModalPopupExtender):
Public Class PopupControl
Inherits System.Web.UI.UserControl
Public Event ItemChanged(ByVal popup As PopupControl)
Public Property SelectedItem As String
Private Sub ListBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
Dim lb = DirectCast(sender, ListBox)
Me.Visible = False
Me.SelectedItem = lb.SelectedItem.ToString()
RaiseEvent ItemChanged(Me)
End Sub
End Class
In page:
Protected Sub PopupItemChanged(ByVal popup As PopupControl)Handles PopupControl1.ItemChanged
Me.txtTo.Text = popup.SelectedItem
End Sub

dynamic columns disappears after postback

I have a GridView with some BoundFields and two TemplateFields. In these two TemplateFields, I dynamically create UserControls containing a DropDownList and a TextBox, which users can modify.
When I try to get the values of the controls after a PostBack, the values in BoundFields are still there but my dynamic controls disappears. I can create them again but it won't get the user's values... How can I get these values before they're lost?
Here's some of my code:
In the RowDataBound event:
Select Case type
Case "BooleanBis"
e.Row.Cells(2).Controls.Clear()
Dim list1 As BooleanBisList = New BooleanBisList(avant, False)
e.Row.Cells(2).Controls.Add(list1)
e.Row.Cells(4).Controls.Clear()
Dim list2 As BooleanBisList = New BooleanBisList(apres, True)
e.Row.Cells(4).Controls.Add(list2)
Case "Boolean"
e.Row.Cells(2).Controls.Clear()
Dim list3 As BooleanList = New BooleanList(avant, False)
e.Row.Cells(2).Controls.Add(list3)
e.Row.Cells(4).Controls.Clear()
Dim list4 As BooleanList = New BooleanList(apres, True)
e.Row.Cells(4).Controls.Add(list4)
End Select
In my button click event, I try to get the user control :
Case "String"
temp.ChampValeurApres = DirectCast(Tableau1.Rows(i).Cells(selectedColumn).Controls(1), TextBox).Text
but i get the error that it doesn't exist.
You should create dynamic controls in RowCreated instead of RowDataBound because this event gets fired on every postback whereas RowDataBound only will fire when the GridView gets databound to it's DataSource.
Dynamically created controls must be recreated on every postback with the same ID as before, then they retain their values in the ViewState and events will fire correctly(f.e. a DropDownList's SelectedIndexChanged event).
So you should create them in RowCreated and "fill" them in RowDataBound(f.e. the DropDownList datasource/Items or a TextBox-Text).
I had been using:
EnableViewState="false"
in the GridView attributes. Removing it solved my problem!
I just did
protected void Page_Load(object sender, EventArgs e)
{
if (!(Page.IsPostBack))
{
// Put the selected items which u want to keep on postback
}
else
{
//regenerate auto created controls
}
}
and it worked as well

How do I access properties of non-fired LinkButtons in an ASP RepeaterControl?

I have a navigation bar which is dynamically populated with LinkButtons by an ASP repeaterControl.
I have no problem accessing, and setting properties for the clicked LinkButton. This I can do using the sender object from the fired LinkButton. Once a LinkButton is clicked, it is highlighted in bold.
My problem is to clear the bold property of the previously clicked linkButton when a new LinkButton ( another RepeaterItem within the same repeater) is clicked.
Any ideas on this, please? Many thanks!
ps.
I cannot access the buttons through their ID, since they all have the same ID within the repeater.
I have unique arguments on each RepeaterItem (CommandArgument), but when I try to iterate through all linkbuttons, only static linkbuttons are found, none inside the repeater. See below:
Dim c As Control
For Each c In Form1.Controls
If TypeOf c Is LinkButton Then
MsgBox(DirectCast(c, LinkButton).CommandArgument)
End If
Next c
Try this:
For each item as RepeaterItem in YourRepeaterControl.Items
Dim button as LinkButton = item.FindControl("YourLinkButtonId")
If button IsNot Nothing Then
'Do whatever you want here
End If
Next

Dynamically added linkbutton click doesn't fire (init only??) , updatepanel and triggers

When the user selects an "account" we dynamically create a linkbutton with the selected dates.
However, the linkbutton onclick handler doesn't fire when the button is clicked.
thx
Dim linkBtn As New LinkButton
linkBtn.Text = "blah"
AddHandler linkBtn.Click, AddressOf linkButtonHandler
linkBtn.ID = panelDatesRencontre.Controls.OfType(Of LinkButton).Count
panelDatesRencontre.Controls.Add(linkBtn)
ScriptManager1.RegisterAsyncPostBackControl(linkBtn)
Dim Trigger1 As New AsyncPostBackTrigger
Trigger1.ControlID = linkBtn.ID
Trigger1.EventName = "Click"
UpdatePanel2.Triggers.Add(Trigger1)
Answer: i make that in page_load, it seems to work
In order for the handler to be available it has to be recreated in the page_init section.
Otherwise you'll just get a postback without the handler executing.

Resources