ASP.NET AJAX issues when using UserControls - asp.net

I Have a UserControl called TenantList.ascx which contains a slightly modified GridView from DevExpress (Web.ASPxGridView). This control makes Callbacks without causing a postback which is exactly what I need.
The specific event I need to react on is CustomButtonClicked. I have made my on OnCustomButtonClicked event on the usercontrol TenantList.ascx that fires when the the GridView CustomButtonClicked event fires.
I have an eventhandler on the page where I use the UC. When I debug using VS I can see that I get into the eventhandler as I am suppose to.
My Eventhandler looks like this:
protected void uc_TenantList_CustomButtonCallback(object sender, ASPxGridViewCustomButtonCallbackEventArgs e)
{
Tenant tenant = (Tenant)uc_TenantList.GetGridView().GetRow(e.VisibleIndex);
switch (e.ButtonID)
{
case "btn_show":
ShowRow(tenant);
break;
case "btn_edit":
EditRow(tenant);
break;
case "btn_delete":
DeleteRow(tenant.Id);
break;
default:
break;
}
}
private void EditRow(Tenant tenant)
{
uc_TenantDetails.SetTenantData(cBLL.GetTenant(tenant.Id));
UpdatePanel1.Update();
}
The EditRow function get's called and the UserControl TenantDetails.ascx gets filled with data correctly. However the UpdatePanel1.Update(); is not updating the panel where my TenantDetails UserControl is in.
However if i call UpdatePanel1.Update(); from a normal control registered to the ScriptManager it updates just fine.
protected void Button1_Click(object sender, EventArgs e)
{
uc_TenantDetails.SetTenantData(cBLL.GetTenant(17));
UpdatePanel1.Update();
}
That works without a problem... I am 100% stuck and without any idea of what might be the problem here.
Any suggestion is welcome!!
Cheers
The Real Napster - In real trouble :)

Okay solved this issue
What I needed to do was to enable postback on the gridview control inside my usercontrol.
Then place the Gridview usercontrol in a updatepanel and still keep the details usercontrol in another updatepanel.
That way it all worked out. Not impressed by the solution though. Looks a bit ugly.

Make sure that your update panel is set to always update (not conditionally). You may also find the information in this articles useful:
http://www.asp.net/AJAX/Documentation/Live/overview/PartialPageRenderingOverview.aspx
http://msdn.microsoft.com/en-us/library/system.web.ui.updatepanel.update.aspx
The first link will give you some history regarding Partial Page Rendering, the second gives you some more information about the Update method.
From the documentation calling UpdatePanel.Update will cause an update panel to be re-rendered on the client after calling, but only if the UpdatePanel is set to Conditionally update. If it is set to always update this should throw an error.
If your update panel is set to always update, could it be that it is nested in another UpdatePanel which has its update mode set to conditional?

Related

Events are not working if UserControl.ascx are loaded through LoadControl(ctr)

I find this as a funny little problem. I think the reason lies behind the life-cycle of page-object/events-generation, but the question is how I come around the problem?
In Default.aspx there exist some funny controls but also a
<asp:PlaceHolder runat="server" id="phUserContent"></asp:PlaceHolder>
This placeholder is empty until runtime. Code behind are, in some circumstances, loading UserControls into it. Like this
Control ctr = LoadControl("~/UserControl/Note.ascx");
phUserContent.Controls.Add(ctr);
This Note.ascx contains some interesting controls and finally a LinkButton that fires an event. The LinkButton-code are very easy and gramatically correct,
<asp:LinkButton runat="server" ID="lbUpdate" OnClick="lbUpdate_Click" Text="Update"></asp:LinkButton>
In the Code behind for the ascx I have the code for the event,
protected void lbUpdate_Click(object sender, EventArgs e)
{ ... }
As I wroted, the postback occurs, the page are regenerated as I would suspect - but without the lbUpdate_Click event to be executed. A break-point is of course tried.
I'm looking for two possible scenarios. One is that I missed something really easy (you know, like wroted in wrong code behind file) or that I missed an important part of the Page Generation Cycle.
I'm mostly into the second, like this (i just think here..)
1. Page (ascx) got it's changes
2. Submit was clicked
3. Ascx was re-generated
4. Events was cleared but was exist and doesnt cast error.
5. After reload, initial content was reloaded
The effect would be that the compiler can't see the breakpoint and the values was never saved due to a "execution of an empty event". But this is just a amateours guess, please advice me.
[UPDATE AS PER ANSWER]
This is how I was solved it, based on the acepted answer below.
List<Control> ctr;
public User()
{
ctr = new List<Control>();
}
protected void Page_PreInit(object sender, EventArgs e)
{
ctr.Add(LoadControl("~/UserControl/Note.ascx"));
}
protected void Page_Load(object sender, EventArgs e)
{
ctr.ForEach(d => phUserContent.Controls.Add(d));
}
Shortly..
1. The class got a list of Controls
2. In Page_PreInit (before creation) add UC (u can have X of them here)
3. In Page_Load (where all ctr are created) add each UC to the PH.
Which also make the events in the UC also working, no magic and no dumb complications :-)
It's a lifecycle issue.
Remember, every page request creates a new Page object, and new instances of all the controls on it. If you are dynamically creating a control, then it has to be done in the exact same manner on every postback. If you want the new control to fire an event, then it has to have the same id as the old one, and have the event hooked up to it before control events are processed in the lifecycle.
If you're creating the control dynamically at a point in the page lifecycle that occurs after ViewState is handled, then you'll have to manage your own state as well. In other words, if you're not dynamically creating the control during the PreInit phase, then you'll have to manually deal with restoring state.

Viewstate Disabled - Dropdown box not returning values

In an effort to speed up my site, I am trying to disable the viewstate as I don't think I am using it everywhere. I have a master page setup with user controls loaded (using LoadControl) in default.aspx. My typical page setup would be:
Main.master -> Default.aspx -> ControlWrapper.ascx -> MyControl.ascx
I have put EnableViewState="false" in my Default.aspx page. Now when I try and read a value from a DropDownList in MyControl.ascx it comes back blank when the form is posted. First all, why is this? I thought I should still be able to read the value from the drop down list?
I then tried enabling the ViewState on that control and it didn't work.
I also tried enabling the viewstate on the Page_Init event of MyControl.ascx using Page.EnableViewState = True; but that didn't help either.
I guess I am misunderstanding the viewstate somewhat, can someone point me in the right direction please?
p.s I don't know if this information is relevant but I am adding the contents of the DropDownList dynamically in the Page_Load event. (Thinking about it, could this be the issues - Will test this now).
Thanks.
With viewstate turned off, the values you are loading in Page_Load are no longer in the list when you post back (until you reload them obviously). If you want to work without viewstate, you will need to set the selected item from the value in Request.Form.
protected void Page_Load(object sender, System.EventArgs e)
{
ddlItems.Items.Add(new ListItem("test1", "test1"));
ddlItems.Items.Add(new ListItem("test2", "test2"));
ddlItems.Items.Add(new ListItem("test3", "test3"));
if (Page.IsPostBack)
ddlItems.SelectedValue = Request.Form["ddlItems"];
}
When you've set ViewState to false the dropdown needs to get populated before page load - which means you probably should do it at page init. Something like this:
protected void Page_Init(object sender, System.EventArgs e)
{
ddlItems.Items.Add(new ListItem("test1", "test1"));
ddlItems.Items.Add(new ListItem("test2", "test2"));
ddlItems.Items.Add(new ListItem("test3", "test3"));
}
Then you should be able to read the value at load:
protected void Page_Load(object sender, System.EventArgs e)
{
someTextBox = ddlItems.SelectedValue;
}
A bit of background:
On this page: Microsofts page cycle
At the image with the page cycle there is the methods "ProcessPostData" and "LoadPostData" firing in between Init and Load. The post data for the drop down contains the selected value - but not the possible values, so when it loads the post data it is essential that the possible values are already there (or it won't be able to set the selected value). Also before the post data has been loaded the selected value has not been set.
If viewstate is enabled it saves and retrieves the possible values in between postbacks.
I will assume you're using .NET 4. View State is the method that the ASP.NET page framework uses to preserve page and control values between round trips.
The reason it didn't work for you when View State was turned off is because that control was rendered again when you performed a PostBack to the server, meaning you lost your selected value.
The reason it didn't work for you when View State was off for the page, but on for the control is because in order for that to work, the following conditions must be met:
The EnableViewState property for the page is set to true.
The EnableViewState property for the control is set to true.
The ViewStateMode property for the control is set to Enabled or inherits the Enabled setting.
ASP .NET View State Overview
When you did EnableViewState = false; on a page then you should not expect DropdownList.SelectedValue after postback.
It will be good if you Enable/Disable ViewState on particular controls rather than disabling whole view state by specifying it on page directive.

How to disable auto data bind of ASP.NET page?

How can I prevent ASP.NET page from automatically binding data controls on the page? I want to increase performance and I want to do binding of each data control based on my own order.
Simple, don't setup data binding on the controls in the designer.
You would then have to bind the controls inside the code behind part of the page with code.
Not quite what the OP asked for but it is also possible to cancel the Select operation on the Datasource control by adding an event handler to the Selecting event.
public void DataSource_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)
{
if (CancelSelect())
{
e.Cancel=true;
return;
}
}

Refresh the page after a postback action in asp.net

I have command button added in my asp.net grids. After performing an action using that button, we refresh the grid to reflect the new data. (basically this action duplicates the grid row).
Now when user refresh the page using F5, an alert message is displayed (to resend the information to server) if we select "retry", the action is repeated automatically.
I know this is a common problem in asp.net, how can we best handle this?
Search for GET after POST - http://en.wikipedia.org/wiki/Post/Redirect/Get - basically, redirect to the current page after you're finished processing your event.
Something like:
Response.Redirect(Request.RawUrl)
If you think you don't need postback paradigm, you might want to look at ASP.NET MVC.
The problem is that asp.net buttons perform form posts when you push a button. If you replace the button with a link your problem should go away. You can also use a button that performs a javascript function that sets the document.location to the address of your page.
If I well understood, you simply have to check if you are in a post-back situation before populating your grid.
Assuming you do that on Page_Load, simply surround the operation with post-back test like this:
private void Page_Load(object sender, EventArgs e)
{
if(!this.IsPostBack)
{
// populate grid
}
}
You need to call response.Redirect(Request.Url.ToString());
or you can wrap the grid with updatepanel and after every command bind the datasource to grid
Inside your <asp:Repeater> tag put this:
EnableViewState="false"
This will cause your control to refresh every time the page loads, no matter if it's a postback or not.
for example:
if you click on 'button' system will catch the event 'button_click'.
if you refresh the page, system will re execute again the same event.
to don t have this problem, in your event insert :
on your event
private void button_click(object sender, System.EventArgs e)
{
button.Enabled =false;
button.Enabled =true;
}
is what you meant?

How to create a MaskedEditExtender on the fly?

I want to create a number of masked edit extenders from codebehind. Something like:
private MaskedEditExtender m_maskedEditExtender;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
m_maskedEditExtender = new MaskedEditExtender()
{
BehaviorID = "clientName"
};
m_maskedEditExtender.Mask = "999999999";
this.Controls.Add(m_maskedEditExtender);
}
protected override void Render(HtmlTextWriter writer)
{
m_maskedEditExtender.RenderControl(writer);
}
When I do this, I get a NullReferenceException on OnLoad of MaskedEditExtender. What is the correct way of doing that? Please note that putting the extender into a repeater-like control and using DataBind does not work for me.
Edit: I do not have an update panel. Turns out I also need to specify a target control on serverside.
See ASP.NET Page Life Cycle Overview if this is in a Page subclass. If you scroll down to the event list, that page advises you to use the PreInit event to create any dynamic controls. It's necessary to do that early to ensure that ASP.NET cleanly loads ViewState at the right stage, among other things.
If you are doing this in a web user control or custom control, though, override CreateChildControls and do this in there.
Post a more complete code example if that doesn't help.
Your example is not providing a TargetControlID.
Do you have an updatePanel on the page? I had problems dynamically creating extenders as they weren't being added to the updatePanel content.
I also think you have to do somethin with the ScriptManager (registering the extender) but I could be mistaken (I don't have access to the code I did dynamic extenders at the moment).
Provide the proper TargetControlID value to MaskedEditExtender

Resources