A user can send an alert to a group of users. The alert will comport a text and (operationally) an attached file. The problem is that, when the file gets bigger, the uploading takes longer and the UI is tied up.
This is what I'd like to do: After posting the form, I want the uploading to be done in the background, using, for instance, a new thread. The idea behind is that the user can keep working while the file is being uploaded.
I've read how threading works, I don't just see how to apply that as Threading is applied in the server-side.
Thanks for pointing me to solutions.
EDIT
I'm using ASP.NET MVC 2.O
If your talking about ASP.NET, you would first add a ScriptManager from the Toolbox (under AJAX Extensions).
Then add an AsyncFileUpload control (from AjaxToolKit).
This control has an OnClientUploadComplete event in properties. Tie it to a function, for example uploadComplete.
Your ASPX code should look something like:
<head runat="server">
<title></title>
<script type = "text/javascript">
function uploadComplete(sender) {
$get("<%=Label1.ClientID%>").style.color = "blue";
$get("<%=Label1.ClientID%>").innerHTML = "Successfully Uploaded";
}
function uploadError(sender) {
$get("<%=Label1.ClientID%>").style.color = "red";
$get("<%=Label1.ClientID%>").innerHTML = "Upload failed.";
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:Label ID="Label2" runat="server" Text="Asynchronous File Uploading"
ForeColor="#000066"></asp:Label>
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:AsyncFileUpload OnClientUploadError="uploadError"
OnClientUploadComplete="uploadComplete" runat="server"
ID="AsyncFileUpload1" Width="400px" UploaderStyle="Modern"
CompleteBackColor = "White"
UploadingBackColor="#CCDDEE" ThrobberID="inProgress"
OnUploadedComplete = "FileUploadComplete"
/>
<asp:Image ID="inProgress" runat="server" ImageUrl = "~/inProgress.gif" />
<br />
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
</form>
</body>
Your codebehind file (.cs) should look something like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class AjaxUploadFile : System.Web.UI.Page
{
protected void FileUploadComplete(object sender, EventArgs e)
{
string savePath = #"F:\BLOG\Projects\InsertData\UploadedFiles\";
string filename = AsyncFileUpload1.FileName;
if (AsyncFileUpload1.HasFile)
{
savePath += filename;
AsyncFileUpload1.SaveAs(savePath);
}
}
}
This should give you the async file uploading functionality you want. You can get the AjaxToolKit from http://www.asp.net/ajaxlibrary/AjaxControlToolkitSampleSite/
Related
Before I start - I know how the postback works, I know that page will update only when it is fully rendered, I just want to make sure, that there is no solution for my case to make minor updates to page.
Problem definition. I have ASP.NET project and a WCF service. WCF service contains few functions which return some string as result (e.g. was there mistake or did it go well). On the ASP.NET website I have a button, which fires sequence of actions. These actions are calls of functions from the WCF service. With usual postback (it is called ones I press the button), page will reload only when results for all functions are received as it should be (it takes quite much time). All results are added to a textbox.
Question. Is there any way really to add a result to the textbox asynchronously? I mean, really, using AJAX/something else, I do not care. I can not believe that this problem is unsolved in the ASP.NET. I just need a user to see progress - results of fired functions before the whole sequence is fired.
I spent few hours and I did not find any clue except UpdatePanel but I could not use it to solve the case. Do you have any ideas?
protected void Button1_Click(object sender, EventArgs e)
{
textBox1.text += wcf.function1();
textBox1.text += wcf.function2();
textBox1.text += wcf.function3();
//only now the page updates.
}
Demo using ajax and generic handlers. This example was made in MonoDevelop but you can pass to Visual Studio without changing the code.
The folders and files:
/*
DemoGenericHandler
|
|---Default.aspx
|---Default.aspx.cs
|
|---GenericHandlers
| |
| |---MyHandler.ashx
| |---MyHandler.ashx.cs
|
|---web.config
*/
This is the code for Default.aspx
<%# Page Language="C#" Inherits="DemoGenericHandler.Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head runat="server">
<title>Default</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var $button1 = $("#<%= Button1.ClientID %>");
var $txt1 = $("#<%= textBox1.ClientID %>");
var $txt2 = $("#<%= textBox2.ClientID %>");
var $txt3 = $("#<%= textBox3.ClientID %>");
var $progressBar = $("#progressBar");
$button1.click(function(e){
//avoid postback
e.preventDefault();
//show progress bar
$progressBar.fadeIn('fast');
//ajax-post
$.post("<%= ResolveClientUrl("~/") %>GenericHandlers/MyHandler.ashx",
{data:"requestFromDefaultPage"},
function(jsonInstance){
if(jsonInstance)
{
$txt1.val(jsonInstance.Value1);
$txt2.val(jsonInstance.Value2);
$txt3.val(jsonInstance.Value3);
}
//hide progressbar
$progressBar.fadeOut('fast');
});//ajax-post
});//click
});
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:Button id="Button1" runat="server" Text="Call Ajax!" OnClick="Button1_Click" />
<img src="http://casa-vivebien.com/contents/media/progressbar.gif" id="progressBar" title="" style="display:none;" />
<br />
<asp:TextBox ID="textBox1" runat="server"></asp:TextBox>
<asp:TextBox ID="textBox2" runat="server"></asp:TextBox>
<asp:TextBox ID="textBox3" runat="server"></asp:TextBox>
</form>
</body>
</html>
This is the code-behind:
using System;
using System.Web;
using System.Web.UI;
namespace DemoGenericHandler
{
public partial class Default : System.Web.UI.Page
{
protected void Button1_Click(object sender, EventArgs e)
{
//textBox1.Text += wcf.function1();
//textBox1.Text += wcf.function2();
//textBox1.Text += wcf.function3();
//only now the page updates.
}
}
}
Code behind of the generic handler (*.ashx.cs):
using System;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Threading;
namespace DemoGenericHandler
{
public class MyHandler : System.Web.IHttpHandler
{
public virtual bool IsReusable {
get {
return false;
}
}
public virtual void ProcessRequest (HttpContext context)
{
//if you need get the value sent from client (ajax-post)
//string valueSendByClient = context.Request.Form["data"] ?? string.Empty;
//you must use a library like JSON.NET (newtonsoft) to serialize an object
//here for simplicity i'll build the json object in a string variable:
string jsonObj = "{\"Value1\": \"1\",\"Value2\": \"2\",\"Value3\": \"3\"}";
//await 5 seconds: (imitates the time that your wcf services take)
Thread.Sleep(5000);
//send the result to the client
context.Response.ContentType = "text/json";
context.Response.Write(jsonObj);
}
}
}
A capture:
I have a very simple ASP.NET page that uploads an Excel workbook, then processes it. It uses AJAXFILEUPLOAD from the AJAX toolkit on ASP.NET... Here's the markup:
<%# Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"
CodeBehind="ImportWorkbook.aspx.cs" Inherits="Timesheet.ImportWorkbook" %>
<asp:Content ID="Content1" runat="server" ContentPlaceHolderID="HeaderContentPlaceHolder">
<h1 class="topContent">
Upload CPAS Timesheet Workbooks
</h1>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="RightContentPlaceHolder" runat="server">
<br />
<br />
<asp:HiddenField ID="tbTSID" runat="server" />
<asp:HiddenField ID="tbWorkbookPath" runat="server" />
<ajaxToolkit:AjaxFileUpload ID="AjaxFileUpload1" runat="server" AllowedFileTypes="xls,xlsx,xlsm"
CssClass="dropdown" MaximumNumberOfFiles="1" OnUploadComplete="AjaxFileUpload1_UploadComplete" />
<br />
<br />
<asp:Panel ID="ProcessChoices" runat="server" >
<br />
<br />
<p>
Select how you want this workbook processed:</p>
<br />
<asp:RadioButtonList ID="rbChoices" runat="server" BorderStyle="Groove" BorderWidth="2px"
BorderColor="Black" BackColor="Teal" Font-Names="Tahoma" Font-Size="10pt" ForeColor="White"
Width="40%">
<asp:ListItem Value="True" Selected="True">  Replace ALL Items in the Timesheet</asp:ListItem>
<asp:ListItem Value="False">  Add Items from this Workbook to the Existing Timesheet Items</asp:ListItem>
</asp:RadioButtonList>
<br />
<br />
<asp:Button ID="btnValidate" runat="server" Text="Validate and Process"
BackColor="#B92217" ForeColor="White" BorderColor="#7C1810"
BorderStyle="Groove" Font-Names="Tahoma" onclick="btnValidate_Click" />
</asp:Panel>
</asp:Content>
<asp:Content ID="Content4" ContentPlaceHolderID="BottomSpanContentPlaceHolder" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
</asp:Content>
The master page and css pages are trivial, formatting only.
Here's the codebehind:
using System;
using System.IO;
using TimesheetUtilites;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using AjaxControlToolkit;
namespace Timesheet
{
public partial class ImportWorkbook : System.Web.UI.Page
{
private const string HDriveLocation= "H:\\mtv\\secure\\Construction\\Access\\CPAS WorkArea\\TimesheetUploads\\";
private string strWorkbookPath;
private int currTSID;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (Request.QueryString["ID"] != null)
{
tbTSID.Value = Request.QueryString["ID"]; // Storing the Timesheet ID in a hidden Textbox
}
}
else
{
if (!string.IsNullOrEmpty(tbWorkbookPath.Value))
{
ProcessChoices.Enabled = true;
}
}
int.TryParse(tbTSID.Value, out currTSID);
strWorkbookPath = tbWorkbookPath.Value;
}
protected void AjaxFileUpload1_UploadComplete(object sender, AjaxFileUploadEventArgs e)
{
strWorkbookPath = HDriveLocation + Path.GetFileName(e.FileName);
tbWorkbookPath.Value = strWorkbookPath;
AjaxFileUpload1.SaveAs(strWorkbookPath);
ProcessChoices.Enabled = true;
}
protected void btnValidate_Click(object sender, EventArgs e)
{
bool processOption;
bool.TryParse(rbChoices.SelectedValue, out processOption);
strWorkbookPath = tbWorkbookPath.Value;
TimesheetUtilites.ImportTimesheet imp = new ImportTimesheet(currTSID, strWorkbookPath, processOption);
}
}
}
My issue is simple. Although the event handler "AjaxFileUpload1_UploadComplete" works fine, and uploads the file in an instant, when I fire the "btnValidate_Click" event, the "tbWorkbookPath.Value" has become an empty string, and the "ProcessChoices.Enabled" propety doesn't change. Needless to say, the "Upload Complete" event handler is the only opportunity I have to capture this file path, so I'm at a loss what I'm doing wrong.
I posted on ASP.NET and go NO answers. Can anyone give me an idea where to start?
This is information you should be storing in your page's ViewState so that it persists between postbacks and resets on page initialization. Change your private string member to something like the following:
private string strWorkbookPath {
get {
return this.ViewState["strWorkbookPath"];
}
set {
this.ViewState["strWorkbookPath"] = value;
}
}
If you need a primer on what the ViewState is, check out this article on MSDN: Saving Web Forms Page Values Using View State. It's a bit dated but still communicates the basics of how ViewState operates currently.
Put a hidden field with runat="server" attribute on your page and use the below script:
<script type="text/javascript">
function uploadComplete(sender, args) {
var filename = args.get_fileName();
$("#hiddden_field_id").val(filename);
}
</script>
Now you should be getting the image name in your events.
I think you should try storing that value in session rather than a hidden field as the page is not reloaded and it was an ajax call. So when the button is clicked for validation, it is actually another request made but the value of the hidden field in this page object and the hidden field is still empty. Once your job is done for that value in session, remove it from there or set it to some different value.
Please See The Simple Example Below For Understanding My situation.
(Attention To Comments Inside Codes)
Master Page (ASPX) :
<%# Master Language="C#" AutoEventWireup="true" CodeBehind="Site1.master.cs" Inherits="NiceFileExplorer.Site1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
<span runat="server" id="SummaryContainer">
<asp:Label ID="lblDownload_Count_By_UserID_Today_Title" runat="server" Text="Count :"
ToolTip="Your Download Count-Today" CssClass="lblTitleInStatistics_Master"></asp:Label>
<asp:Label ID="lblDownload_Count_By_UserID_Today" runat="server" Text="<%# Download_Count_By_UserID_Today() %>"
CssClass="lblCountInStatistics_Master" ToolTip="Your Download Count-Today"></asp:Label>
<span style="color: white;"> | </span>
<asp:Label ID="lblDownload_Size_By_UserID_Today_Title" runat="server" Text="Size :"
ToolTip="Your Download Size-Today" CssClass="lblTitleInStatistics_Master"></asp:Label>
<asp:Label ID="lblDownload_Size_By_UserID_Today" runat="server" Text="<%# Download_Size_By_UserID_Today() %>"
CssClass="lblCountInStatistics_Master" ToolTip="Your Download Size-Today"></asp:Label>
</span>
</div>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server" ViewStateMode="Inherit" ClientIDMode="Static">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
as you see i set ClientIDMode="Static".
Master Page (CodeBehind) :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace NiceFileExplorer
{
public partial class Site1 : System.Web.UI.MasterPage
{
protected void Page_Load(object sender, EventArgs e)
{
SummaryContainer.DataBind();
}
protected string Download_Count_By_UserID_Today()
{
//Read New Count From DataBase
//return Count;
return "Test";
}
protected string Download_Size_By_UserID_Today()
{
//Read New Size From DataBase
//return Size;
return "Test";
}
}
}
Content Page (ASPX) :
<%# Page Title="" Language="C#" MasterPageFile="~/Site1.Master" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="NiceFileExplorer.WebForm1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
Conntent Page
</asp:Content>
Content Page (CodeBehind) :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace NiceFileExplorer
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
MyMethod();
}
private void MyMethod()
{
//Add New Downloaded File Info To DataBase(); -> For Getting Count And Size Of Them Per Day
//Here I Wand To Access Master Page Controls And Update Count And Size Lables
//So, I Tried Codes Below Without Any Results -> How Can I Fix This ?
var SummaryContainer = (System.Web.UI.HtmlControls.HtmlGenericControl)Page.Master.FindControl("SummaryContainer");
SummaryContainer.DataBind();
SummaryContainer.InnerHtml = "<h2>Hello World</h2>";
//After Update Those Lables Failed, I test the codes Below With Null Execption Error -> How Can I Fix This ?
var lblDownload_Count_By_UserID_Today_Title = (Label)Page.Master.FindControl("lblDownload_Count_By_UserID_Today_Title");
lblDownload_Count_By_UserID_Today_Title.Text = "test";
DwonloadFile();
}
private void DwonloadFile()
{
//A Class (Method) That Shows Download Window To My Users, So Page_Load Of Master Will Never Fire...
//And This Is The Reason That I want to update count & size lables from content page
}
}
}
i want to DataBind SummaryContainer(a span) from content page's code-behind.
so i tried the codes below :
var SummaryContainer = (System.Web.UI.HtmlControls.HtmlGenericControl)Page.Master.FindControl("SummaryContainer");
SummaryContainer.DataBind():
but i can not see new results.
After That Fail I tried to find a label's text(that label is inside Master) from content page code behind for test like below : var
lblDownload_Count_By_UserID_Today_Title = (Label)Page.Master.FindControl("lblDownload_Count_By_UserID_Today_Title");
lblDownload_Count_By_UserID_Today_Title.Text = "test";
but i have System.NullReferenceException ERROR :
Object reference not set to an instance of an object.
how can i fix that error and force that span to show me new results?
thanks in advance
In a project I used an interface on the masterpage:
((IMasterPage)Page.Master).MyProperty = "test";
But in your case, personally instead of putting all that on the master page, I'd put your SummaryContainer into a UserControl, and have another ContentPlaceHolder.
Then the Page_Load method will be able to access the properties, and on future pages you could have different summary info by filling that first PlaceHolder with a different UserControl.
Also debugging stupid errors, is the Null exception being thrown at .Master.FindControl or at lbl.Text?
I'm unable to debug it for myself right now, but would it be due to the page life cycle, namely that Content Page Load comes before Master Page Load?
I have GUI for data acceptance.
I need to pass all the parameters of the form on click of a submit button to a function declared in C#.
Please help.
Using .Net us have too types of submit tags, one starting with <asp: and the other starting with <input. the <input html tag can call javascript and if you add the runat="server" attribute, you will enable it to also have C# code behind the button.
First of all, you will need to create an aspx page (say submission.aspx) that will receive the POST submission of your form. In that page, you can include your .cs file that contains the method/function you want to pass the data to.
Next, you want to submit you submit your data to submission.aspx. To do that, you will need to have a form which will submit its data to submission.aspx.
<form action='submission.aspx' method='POST' id='data-submission'>
<!-- stuff here -->
</form>
If you want to perform ajax submission, you can use jquery and use this code:
$('#data-submission').submit(function(evt){
var $form = $(this);
var url = $form.attr('action');
$.post(url, $form.serialize(), function(){alert('submission complete!);});
});
I wonder if all that helped you.
PS: I haven't used .NET for web programming in a long time now.. but what I've written here in this answer hold universally true for any web programming language/framework.
If your using asp.net you just need to double click the button(if it is an asp button) and it should make a click event.
In the click event you could get your other controls like
default.aspx code
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</div>
</form>
</body>
</html>
Codebehind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
// you can declare it as a field variable so the entire code behind can use it
private Passengerdetails myClass;
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
// create an instance of the class.
myClass = new Passengerdetails ();
// stick textbox1 contents in the property called test.
myClass.PassengerName = TextBox1.Text;
int a = Convert.ToInt32(TextBox1.Text);
int b = Convert.ToInt32(TextBox2.Text);
int sum = Add(a, b);
// do something with it like return it to a lbl.
Label1.Text = sum.ToString();
}
private int Add(int a, int b)
{
return a + b;
}
}
Edit. You just make a class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for passengerdetails
/// </summary>
public class Passengerdetails
{
public Passengerdetails ()
{
public string PassengerName{ get; set; }
}
}
I'm having trouble dynamically adding controls inside an update panel with partial postbacks. I've read many articles on dynamic controls and I understand how to add and maintain them with postbacks but most of that information doesn't apply and won't work for partial postbacks. I can't find any useful information about adding and maintaining them with UpdatePanels. I'd like to do this without creating a web service if it's possible. Does anyone have any ideas or references to some helpful information?
This is, I think, one of the common pitfalls for asp.net programmers but isn't actually that hard to get it right when you know what is going on (always remember your viewstate!).
the following piece of code explains how things can be done. It's a simple page where a user can click on a menu which will trigger an action that will add a user control to the page inside the updatepanel.
(This code is borrowed from here, and has lots more of information concerning this topic)
<%# Page Language="C#" AutoEventWireup="true" CodeFile="SampleMenu1.aspx.cs" Inherits="SampleMenuPage1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Sample Menu</title>
</head>
<body>
<form id="form1" runat="server">
<asp:Menu ID="Menu1" runat="server" OnMenuItemClick="Menu1_MenuItemClick">
<Items>
<asp:MenuItem Text="File">
<asp:MenuItem Text="Load Control1"></asp:MenuItem>
<asp:MenuItem Text="Load Control2"></asp:MenuItem>
<asp:MenuItem Text="Load Control3"></asp:MenuItem>
</asp:MenuItem>
</Items>
</asp:Menu>
<br />
<br />
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Menu1" />
</Triggers>
</asp:UpdatePanel>
</form>
</body>
</html>
and
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class PlainSampleMenuPage : System.Web.UI.Page
{
private const string BASE_PATH = "~/DynamicControlLoading/";
private string LastLoadedControl
{
get
{
return ViewState["LastLoaded"] as string;
}
set
{
ViewState["LastLoaded"] = value;
}
}
private void LoadUserControl()
{
string controlPath = LastLoadedControl;
if (!string.IsNullOrEmpty(controlPath))
{
PlaceHolder1.Controls.Clear();
UserControl uc = (UserControl)LoadControl(controlPath);
PlaceHolder1.Controls.Add(uc);
}
}
protected void Page_Load(object sender, EventArgs e)
{
LoadUserControl();
}
protected void Menu1_MenuItemClick(object sender, MenuEventArgs e)
{
MenuItem menu = e.Item;
string controlPath = string.Empty;
switch (menu.Text)
{
case "Load Control2":
controlPath = BASE_PATH + "SampleControl2.ascx";
break;
case "Load Control3":
controlPath = BASE_PATH + "SampleControl3.ascx";
break;
default:
controlPath = BASE_PATH + "SampleControl1.ascx";
break;
}
LastLoadedControl = controlPath;
LoadUserControl();
}
}
for the code behind.
That's basically it. You can clearly see that the viewstate is being kept with LastLoadedControl while the controls themselves are dynamically added to the page (inside the updatePanel (actually inside the placeHolder inside the updatePanel) when the user clicks on a menu item, which will send an asynchronous postback to the server.
More information can also be found here:
http://aspnet.4guysfromrolla.com/articles/081402-1.aspx
http://aspnet.4guysfromrolla.com/articles/082102-1.aspx
and of course on the website that holds the example code I used here.
I encountered the problem that using the method mentioned above, LoadUserControl() is called twice when handling an event. I've read through some other articles and would like to show you my modification:
1) Use LoadViewstate instead of Page_Load to load the user control:
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
if (!string.IsNullOrEmpty(CurrentUserControl))
LoadDataTypeEditorControl(CurrentUserControl, panelFVE);
}
2) Don't forget to set the control id when loading the usercontrol:
private void LoadDataTypeEditorControl(string userControlName, Control containerControl)
{
using (UserControl myControl = (UserControl) LoadControl(userControlName))
{
containerControl.Controls.Clear();
string userControlID = userControlName.Split('.')[0];
myControl.ID = userControlID.Replace("/", "").Replace("~", "");
containerControl.Controls.Add(myControl);
}
this.CurrentUserControl = userControlName;
}
Try this:
Literal literal = new Literal();
literal.Text = "<script type='text/javascript' src='http://www.googleadservices.com/pagead/conversion.js'>";
UpdatePanel1.ContentTemplateContainer.Controls.Add(literal);
You can replace the content of literal with any HTML content you want...