ASP.NET: "Object Required" when repeating LinkButtons in an UpdatePanel - asp.net

I have an UpdatePanel which has a Repeater repeating LinkButtons. When I click a LinkButton, the page does a partial postback, then I get a javascript error: "Object required". I tried debugging the javascript, but couldn't get a call stack. If I remove the UpdatePanel, the LinkButtons do a full postback, and they disappear from the page. How can I get this UpdatePanel to work?
<ajax:UpdatePanel ID="wrapperUpdatePanel" runat="server" UpdateMode="Always">
<ContentTemplate>
<asp:Repeater ID="endpointRepeater" runat="server" OnItemDataBound="EndpointDataBound">
<HeaderTemplate>
<div class="sideTabs">
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<asp:LinkButton ID="endpointLink" runat="server" OnClick="EndpointSelected" />
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</div>
</FooterTemplate>
</asp:Repeater>
</ContentTemplate>
</ajax:UpdatePanel>
binding code:
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
this.SelectedEndpoint = Factory.Get<IEndpoint>(Enums.EndPoints.Marketing);
}
IEndpointCollection col = EndpointCollection.GetActivelySubscribingEndpointsForPart(this.Item);
if (this.Item.IsGdsnItem)
col.Add(Factory.Get<IEndpoint>(Enums.EndPoints.Gdsn));
if (col.Count > 0)
col.Insert(0, Factory.Get<IEndpoint>(Enums.EndPoints.Marketing));
this.endpointRepeater.DataSource = col;
this.endpointRepeater.DataBind();
if (this.endpointRepeater.Items.Count > 0)
{
LinkButton lb = this.endpointRepeater.Items[0].FindControl("endpointLink") as LinkButton;
this.EndpointSelected(lb, new EventArgs());
}
}
thanks,
mark

This may not be your main issue, but when including an object inside a Repeater that needs an event, you shouldn't be using that control's native events. Instead you should use the Repeater's OnCommand event.
If I were to guess, your problem is caused by the repeater not maintaining its DataBound state across PostBacks. The Linkbutton disappears from view because it is not bound to the page on every PostBack, so when the response is sent back to the client, it has nothing bound to it.
It sounds like the UpdatePanel is expecting the same (or similar) markup to be returned from the AJAX response as what is on the page already, so returning nothing for the repeater causes problems.
Try binding your repeater to the page/control in its OnInit() method. This should allow the ViewState for the repeater to be loaded on every PostBack.

Related

why a multiline textbox (inside a user control) is not holding its value after a postback?

I have a user control that have a gridview, buttons and a multi-line textbox for comments.
When the page posts back, Gridview is behaving normaly (its controls keeps their values after postback). However, the Comment textbox is always empty, no matter what I do.
protected void Page_Load(object sender, EventArgs e)
{
//This code is in the user ciontrol.
if (!IsPostBack)
{
string test = this.txtDepartmentComments.Text;
}
}
I put a break point at that line and the value is always empty. I've tried also to set the value in the code behind like:
protected void Page_Load(object sender, EventArgs e)
{
//This code is in the user ciontrol.
if (!IsPostBack)
{
this.txtDepartmentComments.Text = "Test!";
}
}
But when the page loads, the control remain empty.
Any idea why this is hapenning?
EDIT
This the ascx code (i.e. user control)
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns = "false" >
</asp:GridView>
<asp:TextBox ID="txtComments" runat="server" Columns="45" TextMode= "MultiLine"/>
<asp:Button ID="btnComplete" runat="server" Text="Completed"/>
And thid id the aspx (i.e. the parent page)
<asp:Repeater ID="rpNewHire" runat="server">
<HeaderTemplate>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<user:MyUserControl ID = "MyUserControl1" runat = "server"
DepartmentID= '<%# Eval("DepID")%>'><user:MyUserControl />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
if(!IsPostBack) is for reading values from controls after postback, you are trying to read text box value on initial load which will always be empty, remove the '!' from your condition. Also it is hard to debug your issue with out the aspx page contents, try posting the design part as well in your question.
EDIT
Your user tag is not well formatted inside repeater, it is missing closing tag and runat attribute
<user:MyUserControl runat="server" ID = "MyUserControl1" DepartmentID= '<%# Eval("DepID")%>'></user:MyUserControl>
Controls inside repeater cannot be accessed directly, you have to loop through the rows of the repeater and find your child controls and then try reading values from them, that after you bind some data to the repeater.
Check this http://msdn.microsoft.com/en-us/magazine/cc163780.aspx
Page's IsPostBack and each user controls' IsPostBack are not same.
When a user control is posted back, that particular control's IsPostBack is true, but other user controls' IsPostBack are still false.
You can use explicitly !Page.IsPostBack inside a user control to check whether its parent page is posted back or not.
if(!Page.IsPostBack){
// do something
}
Dynamically Loaded Control can not maintain values at PostBack? It is not directly related to your question, but it might be useful for you.

Why do my dynamically added controls loose their values after Postback?

To ask my question I have created an aspx file containing a Button and a DataList with an SqlDataSource:
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
<asp:DataList ID="DataList1" runat="server" DataKeyField="a"
DataSourceID="SqlDataSource1" >
<ItemTemplate>
a:
<asp:Label ID="aLabel" runat="server" Text='<%# Eval("a") %>' />
<br />
b:
<asp:Label ID="bLabel" runat="server" Text='<%# Eval("b") %>' />
<br />
</ItemTemplate>
</asp:DataList>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:probaConnectionString %>"
SelectCommand="SELECT [a], [b] FROM [PROBA_TABLE]"></asp:SqlDataSource>
In my code behind I add TextBoxes to the Items of the DataList. I add to every Item a TextBox in the Page_Load, and another TextBox in the Button Click eventhandler as well.
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
foreach (DataListItem item in DataList1.Items)
{
item.Controls.Add(new TextBox());
}
}
}
protected void Button1_Click(object sender, EventArgs e)
{
foreach (DataListItem item in DataList1.Items)
{
item.Controls.Add(new TextBox());
}
}
}
}
This works fine except one thing. When I click the Button, the TextBoxes which were created in the Page_Load keep their Text value, but the TextBoxes which were created in the Button1_Click lose their Text values. My real problem is more complicated than this, but I think solving this would help me a lot.
Each control that should receive data from page ViewState should be instantiated in Init or Load event handlers, because ViewState is persisted to controls BEFORE Click, Change and the rest control events (those events are triggered when ViewState changes are detected, so ViewState must be read before Click event is fired).
So the process should look like:
OnInit (static controls get created)
Static control content is deserialized from ViewState
OnLoad (create dynamic controls, in your case textboxes that you created in last Postback)
Dynamic control content is deserialized from ViewState
Click, Change and other events are fired according to changes detected comparing POST data and ViewState data
Suggestions:
You can use hidden fields to save additional status information, and then in OnLoad you can read that info to recreate dynamically created controls.
Also, you should explicitly set ID property of your textboxes so that values can be properly persisted back, don't rely on ASP.Net.
the http by default is stateless that means after your request is processed the server keeps no data or info of the request
but the values in the form need to be persisted in special cases when there is an error
suppose you fill up a long form and then post it back to the server only to get an error message and all the filled up values are gone. wouldn't that be annoying
so what asp.net does behind the scenes that it keeps a string in the page hidden that has information about all the server controls and their ids
so when you post a form back the Page class is created and the values that are posted back and binded in the specific controls because the Page class is being created in every request the pageLoad event is run and controls created in the PageLoad are then present values corresponding to their ids are put into them unlike the controls that are being created on button click till the button_click event is run that viewstate has already been deseralized and values are filled into them

Reacting to Button commands inside a Web Usercontrol in a ASP.NET Repeater

I have an ASP.NET repeater, whose ItemTemplate is a WebUsercontrol named ProviderControl.
<asp:Repeater ID="rep" runat="server" OnItemDataBound="rep_ItemDataBound">
<ItemTemplate>
<custom:ProviderControl ID="row" runat="server" />
</ItemTemplate>
</asp:Repeater>
I am populating the custom control with data in the ItemDataBound event.
Inside the provider control I have two buttons that I want to be able to react to on the containing Page.
I know there are Commands, and Command arguments, but how would I do that?
Or is there an easier way than using Commands?
You have to handle ItemCommand event of "Repeater".
protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)
{
Button btn = e.CommandSource as Button;
Response.Write(btn.ID);
}
The best way would be to provide custom events in your UserControl for each button-click event. The UserControl will raise and the page can handle them.
http://www.codeproject.com/Articles/8797/Mastering-Page-UserControl-Communication#4.3

DropDownList's SelectedIndexChanged event not firing

I have a DropDownList object in my web page. When I click on it and select a different value, nothing happens, even though I have a function wired up to the SelectedIndexChanged event.
First, the actual object's HTML code:
<asp:DropDownList ID="logList" runat="server"
onselectedindexchanged="itemSelected">
</asp:DropDownList>
And this is that function, itemSelected:
protected void itemSelected(object sender, EventArgs e)
{
Response.Write("Getting clicked; " + sender.GetType().ToString());
FileInfo selectedfile;
Response.Write("<script>alert('Hello')</script>");
foreach (FileInfo file in logs)
{
if (file.Name == logList.Items[logList.SelectedIndex].Text)
{
Response.Write("<script>alert('Hello')</script>");
}
}
}
None of the Responses appear, and that portion of JavaScript is never run. I've tried this on the latest 3.6 version of Firefox, as well as Internet Explorer 8. This is being served from a Windows Server 2003 R2 machine, running ASP.NET with the .NET Framework version 4.
Set DropDownList AutoPostBack property to true.
Eg:
<asp:DropDownList ID="logList" runat="server" AutoPostBack="True"
onselectedindexchanged="itemSelected">
</asp:DropDownList>
try setting AutoPostBack="True" on the DropDownList.
I know its bit older post, but still i would like to add up something to the answers above.
There might be some situation where in, the "value" of more than one items in the dropdown list is duplicated/same. So, make sure that you have no repeated values in the list items to trigger this "onselectedindexchanged" event
Add property ViewStateMode="Enabled" and EnableViewState="true"
And AutoPostBack="true" in drop DropDownList
Also make sure the page is valid.
You can check this in the browsers developer tools (F12)
In the Console tab select the correct Target/Frame and check for the [Page_IsValid] property
If the page is not valid the form will not submit and therefore not fire the event.
For me answer was aspx page attribute, i added Async="true" to page attributes and this solved my problem.
<%# Page Language="C#" MasterPageFile="~/MasterPage/Reports.Master".....
AutoEventWireup="true" Async="true" %>
This is the structure of my update panel
<div>
<asp:UpdatePanel ID="updt" runat="server">
<ContentTemplate>
<asp:DropDownList ID="id" runat="server" AutoPostBack="true" onselectedindexchanged="your server side function" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
Instead of what you have written, you can write it directly in the SelectedIndexChanged event of the dropdownlist control, e.g.
protected void ddlleavetype_SelectedIndexChanged(object sender, EventArgs e)
{
//code goes here
}

LoginView inside FormView control is not databinding on PostBack

I have a fairly simple form:
<asp:FormView>
<EditItemTemplate>
<asp:LoginView>
<RoleGroups>
<asp:RoleGroup roles="Blah">
<ContentTemplate>
<!-- Databound Controls using Bind/Eval -->
</ContentTemplate>
</asp:RoleGroup>
</RoleGroups>
</asp:LoginView>
<!-- Databound Controls -->
</EditItemTemplate>
</asp:FormView>
<asp:LinqDataSource OnUpdating="MyDataSource_Updating" />
I handle my LinqDataSource OnUpdating event and do some work handling some M:N fields. That all works.
However, once the update is finished (and I call e.Cancel = true), the LoginView control does not databind its children... so they are all blank. The FormView's viewstate is still fine, as all the rest of the controls outside of the LoginView appear fine. I even handle the FormView_DataBound event and a Trace shows that the FormView is being databound on postback.
Why then is the LoginView not keeping its ViewState/being databound? Here's a sample code snippet showing the flow:
protected void MyDataSource_Updating(object s, LinqDataSourceUpdateEventArgs e)
{
try
{
Controller.DoSomething(newData);
// attempts to databind again here fail
// frmView.DataBind();
// MyDataSource.DataBind();
// LoginView.DataBind();
}
catch { // blah }
finally
{
e.Cancel = true;
}
}
I fixed this by reverting to the age old method of databinding everything myself and axing the LoginView.
Ok, i don't know if you need help at this time, but the contaiter that you need to catch is de FormItem, in this case you cant do this
<%# DataBinder.Eval(((FormItem)Container.Parent).DataItem,"YOUR FIELD") %>
Sorry for my english.
Bye.

Resources