By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,131 Members | 1,494 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,131 IT Pros & Developers. It's quick & easy.

Progress bar on composite control

P: n/a
Hi!
I am creating a composite control the does some of it`s own data access.
I want to display a progress bar between the time the page is loaded and the
control place holder is displayed and final display of the data from the
database.
I was thinking of manually opening a second thread in the Render method, but
nothing is displayed before the render method exits anyway.

Anyone know of a good way to do this?
I have been working on this for the past 12Hs and I`m going crazy coz I
always get back to square-one where nothing is displayed until the render
method exits.

Please help!
Thank you.
Oct 16 '06 #1
Share this Question
Share on Google+
15 Replies


P: n/a
Well I have kind of found a workaround this...
Since I don`t need actual feed back and just a stupid animated gif will do
in my case.
While rendering the control I call parent.page.response.flush()
This works for an empty page...even if there are more than two controls on
the page.
But my gutt feeling tells me this will have very bad results in more complex
web pages.
Please give your thoughts and if you can think of a better way, I would love
to see it.
Thank you!
Oct 16 '06 #2

P: n/a
Hello eladla,

As for your scenario, my understanding is that your custom webcontrol will
do postback to do some server-side processing which may take some time. And
during this processing period, you want to display a progress bar on
client-page to indicate the user this processing, correct?

Based on my experience, such progress bar displaying should be done through
client-side script rather than server-side rendering code. This is because
when the page is postback, all the processing is at server-side, and
generally it is only at the end of server-side processing will the page
flush its response content out. So use server-side rendering to output
progress bar UI is not a proper way.

My suggestion is you display the progress bar before your control(the page)
is postback. In ASP.NET 2.0, the Submit Button has included a
"OnClientClick" property which can help conveniently execute some
client-script before the button's submit operation be postback. therefore
we can put the progress bar displaying script code here. There're two ways
to display a bar:

1. dynamically display a image that show a dynamic gif displaying progress
bar

2. use dhtml to display a progress bar

Here I found a web article using dhtml to create a XP WINDOWS update like
progress bar.

#WinXP Progress Bar (version 1.2)
http://www.dynamicdrive.com/dynamici...rogressbar.htm

I've modified its originall script code and create a test page to show how
to use it in our page. The test page use a Table to divide page into
several parts. And there are two button in two cells separately. When
either of the button is clicked, the page will be postback, and it will
also show a progress bar before the postback is finished and return back to
client. here is the test page's complete aspx template and codebehind
(also include the modified progressbar javascript file):

=========aspx===============
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
<script type="text/javascript">
function showprogressbar(cellid)
{
var bar2=
createBar(320,15,'white',1,'black','green',85,7,3, "alert('Hi there')",
document.getElementById("bar" + cellid));
bar2.showBar();

}
</script>

<script type="text/javascript" src="xp_progress.js"></script>

</head>
<body>
<form id="form1" runat="server">
<div>
<table style="width: 100%;height:500pt">
<tr>
<td style="width: 100px">
cell00</td>
<td style="width: 100px">
cell01<br />
<div id="bar01"></div>
<asp:Button ID="btnSubmit01" runat="server"
Text="Cell01 Button" OnClientClick="showprogressbar('01');"
OnClick="btnSubmit01_Click"/></td>
</tr>
<tr>
<td style="width: 100px">
cell10
<div id="bar10"></div>
<asp:Button ID="btnSubmit10" runat="server"
Text="Cell10 Button" OnClick="btnSubmit10_Click"
OnClientClick="showprogressbar('10');"/></td>
<td style="width: 100px">
cell11</td>
</tr>
<tr>
<td style="width: 100px">
cell20</td>
<td style="width: 100px">
cell21</td>
</tr>
</table>

</div>
</form>
</body>
</html>
======================================
===========code behind==================
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Threading;

public partial class javascript_ProgressBarPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

}
protected void btnSubmit10_Click(object sender, EventArgs e)
{
Thread.Sleep(5000);

Response.Write("<br/>btnSubmit10_Click .................");



}
protected void btnSubmit01_Click(object sender, EventArgs e)
{
Thread.Sleep(5000);

Response.Write("<br/>btnSubmit01_Click .................");
}
}

============================================

#please put the xp_progress.js file in the same folder with the test page
=========modified javascript(xp_progress.js)================

var w3c=(document.getElementById)?true:false;
var ie=(document.all)?true:false;
var N=-1;

function createBar(w,h,bgc,brdW,brdC,blkC,speed,blocks,coun t,action,
container){
if(ie||w3c){
var t='<div id="_xpbar'+(++N)+'" style="visibility:visible;
position:relative; overflow:hidden; width:'+w+'px; height:'+h+'px;
background-color:'+bgc+'; border-color:'+brdC+'; border-width:'+brdW+'px;
border-style:solid; font-size:1px;">';
t+='<span id="blocks'+N+'" style="left:-'+(h*2+1)+'px; position:absolute;
font-size:1px">';
for(i=0;i<blocks;i++){
t+='<span style="background-color:'+blkC+'; left:-'+((h*i)+i)+'px;
font-size:1px; position:absolute; width:'+h+'px; height:'+h+'px; '
t+=(ie)?'filter:alpha(opacity='+(100-i*(100/blocks))+')':'-Moz-opacity:'+((1
00-i*(100/blocks))/100);
t+='"></span>';
}
t+='</span></div>';
container.innerHTML = t;

var bA=(ie)?document.all['blocks'+N]:document.getElementById('blocks'+N);
bA.bar=(ie)?document.all['_xpbar'+N]:document.getElementById('_xpbar'+N);
bA.blocks=blocks;
bA.N=N;
bA.w=w;
bA.h=h;
bA.speed=speed;
bA.ctr=0;
bA.count=count;
bA.action=action;
bA.togglePause=togglePause;
bA.showBar=function(){
this.bar.style.visibility="visible";
}
bA.hideBar=function(){
this.bar.style.visibility="hidden";
}
bA.tid=setInterval('startBar('+N+')',speed);
return bA;
}}

function startBar(bn){
var t=(ie)?document.all['blocks'+bn]:document.getElementById('blocks'+bn);
if(parseInt(t.style.left)+t.h+1-(t.blocks*t.h+t.blocks)>t.w){
t.style.left=-(t.h*2+1)+'px';
t.ctr++;
if(t.ctr>=t.count){
eval(t.action);
t.ctr=0;
}}else t.style.left=(parseInt(t.style.left)+t.h+1)+'px';
}

function togglePause(){
if(this.tid==0){
this.tid=setInterval('startBar('+this.N+')',this.s peed);
}else{
clearInterval(this.tid);
this.tid=0;
}}

function togglePause(){
if(this.tid==0){
this.tid=setInterval('startBar('+this.N+')',this.s peed);
}else{
clearInterval(this.tid);
this.tid=0;
}}

========================================
In addition there are many other webarticle discussing on display dhtml
progress bar on web page:

#DHTML Progress Bar Widget using JavaScript and CSS

http://www.wingo.com/dhtml/ProgressBar.html

http://www.eggheadcafe.com/articles/20010610.asp

http://www.java2s.com/Code/JavaScrip...rogressbar.htm
Hope these helps. Please feel free to let me know if you have anything
unclear.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead

==================================================

Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscripti...ult.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscripti...t/default.aspx.

==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.

Oct 17 '06 #3

P: n/a
Thanks for your reply Steven.
But I don`t think you understand what I am trying to do...maybe I didn`t
explain myself well enough...

My custom control does some data access in the Render method and this
process takes time.
What I want to do is display a progress bar while the control is accessing
the data needed to fully render the control.
Oct 17 '06 #4

P: n/a
Thanks for your reply and the further explanation.

Yes, my original reply seems address another scenario different from your
case.

I think the difficulty here is that you do the long run task in render
method. At that time, the Httpresponse may buffer the output content and
flush them when the complete page response has been generated. Also, even,
we can manually flush some certain content out during the Rendering, it
will reside at the begining of the entire page's response content which is
not what we expect.

For your scenario, how long will it normally take to finish the UI
generation? If it is really a long time, I think you can consider the
following design:

** in your web control, before rendering, determine whether this is the
first time and will need to take long time for process output content. If
so, create a new thread to do long-run task and the control it self simply
return the progressbar html. And this html contains some script code that
can send AJAX request to sever-side in background.

**The AJAX request query the task status at server-side and if it get
signal that the task has finished, it call script to postback the whole
page and your control will render based on the generated content.

** Or if the generated content is also plain text (html), you can event
transfer it to client through AJAX webrequest call and display it on page
through clientscript.

How do you think of this? Please feel free to let me know if you have any
other consideration or ideas on this.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead
This posting is provided "AS IS" with no warranties, and confers no rights.

Oct 18 '06 #5

P: n/a
Just what I was thinking...
Only I decided to go on a different route....
I`m going to do the same thing...only with an updatepanel in oreder to allow
partial rendering of the page as to not require a full page refresh...

May only problem is, I`m not up-to-date on the mechanics of doing what you
sugest.
Could you please point me to some examples of how to start an AJAX call from
client-script and how to query it and display the data when it`s done?

Thank you.
Oct 18 '06 #6

P: n/a
Hi Eladla,

Thanks for your quick response.

For AJAX style script callback, basically speaking, they're just some
encapsulated interface for calling browser specific client components(like
the XMLHTTP COM component in IE) to send http request to server. In
ASP.NET 2.0, it has provide a new feature called "Script CallBack", this
feature let you define some functions in your page or control(implement a
certain interface) which can be called by client-side script without
postback. Here is the reference on this in MSDN:

#Implementing Client Callbacks Without Postbacks in ASP.NET Web Pages
http://msdn2.microsoft.com/en-us/library/ms178208.aspx

there are many web article demonstrate using this script callback in
ASP.NET 2.0 page.

#ASP.NET 2.0 Client Callbacks inside a User Control
http://pietschsoft.com/Blog/Post.aspx?PostID=784

#ASP.NET 2.0's Client Callback Feature
http://dotnetjunkies.com/Tutorial/E8...0EECF13D7.dcik

Script callback is just a small feature involved in ASP.NET initial release
and it is not considered the formal support of AJAX of ASP.NET. The ASP.NET
product team has already begun developing a new framework for provide AJAX
based pages in ASP.NET 2.0 application(still under beta). The project is
named "Atlas", here is a blog article from ASP.NET product manager's weblog
introducing this project:

#Atlas Project
http://weblogs.asp.net/scottgu/archi...28/416185.aspx

Also, you can find plenty of resources and information on this in the
official home site of ATLAS:

http://atlas.asp.net/Default.aspx?tabid=47

Hope this helps. Please feel free to let me know if there is anything else
we can help.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead
This posting is provided "AS IS" with no warranties, and confers no rights.

Oct 18 '06 #7

P: n/a
Interesting...Thank you.

Do you know of any samples using ATLAS`s updateprogress control to do this?
Oct 18 '06 #8

P: n/a
I have decided to go the updatepanel router.

What I want to do is:

1. Load the page with an animated gif inside the panel and something like:
“Please hold…” or something…
2. Call the server to run some code, access the DB, call a few methods
inside a DLL and return with the results
3. Put the results into controls that will berendered inside the update panel
4. update the update panel
I am a little stuck on this…

How do I call the method on the server?

How do I put the values inside the controls to be updated to the panel and
how do I update the panel?

I would be very thankful if you could point me to some samples, if you know
of any.
Oct 18 '06 #9

P: n/a
Hi Eladla,

As for sample applications, so far what I can find is the quickstart
samples on the official site, you can also download them there:

#Sample Applications
http://atlas.asp.net/default.aspx?tabid=47&subtabid=471

As for the updatePanel router, do you mean using the UpdatePanel in the
ATLAS package? I've ever played with it in some CTP version of the ATLAS,
and updatePanel is just a container which can make ASP.NET control act as
normal but without postback the page(for example, click button...). And it
seems dynamically emitting client-script in ATLAS updatepanel not quite
convenient.

From your description, you just want to call a server-side function in your
webcontrol (at client-side), it is not necessary to use ATLAS updatepanel,
you can use its webservice interface to call server-side function and
return some value (like html fragment ) to update your control content at
client-side.

Also, this can be done through the scriptcallback I mentioned ealier and
since script callback is built-in feature in ASP.NET 2.0, you can use it
without additional configuration or add-on installation. ATLAS is an
application level solution, each page use ATLAS featuer need to add a
scriptmanager in page and you also need to add many configuration setting
in web.config. Therefore, for webcontrol developing, it seems be too
expensive. How do you think?

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead
This posting is provided "AS IS" with no warranties, and confers no rights.

Oct 19 '06 #10

P: n/a
My only problem with callbacks is that I need to get an image as a BLOB from
the
DB and put it in an image tag and I think that would be a problem for
callbacks.

I was thinking of maybe using pagemethod calls from javascript....my
question is:
Can I call pagemethods from other pages?
If so, How is this done?
If not, what other way do I have of calling a server method and updating
properties in a server page?

Oct 19 '06 #11

P: n/a
Hi Eladla,

If the data of the image is retrieved from database, how did you originally
to render it through <imgelement in your control(without using AJAX
solution)? As far as I know, you need to have a separate httphandler or
page which return this image stream, however, this is not quite reasonable
for a webcontrol's code implementation.

If you do plan to use a separate handler or page to return the image data,
you can just use clientscript to set the <imgelement's "src" attribute at
client-side. Is this workable?

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead
This posting is provided "AS IS" with no warranties, and confers no rights.

Oct 20 '06 #12

P: n/a
I actually feel like I`m going wrong about the whole thing...
Let me retrace what I want to do exactly:
I have a composite control that does some data access that might just take
some time.
What I want to do is render an animated gif at first then start the process
and when it is done do a postback just on the control itself.

Any ideas? Maybe some similar samples.
Oct 22 '06 #13

P: n/a
Hi Eladla,

Thanks for your followup.

Well, I think this can be done. And I'll prefer using the existing script
callback function in ASP.NET 2.0. My implementation on this will like below:

** In Render method(or createchildcontrols code) determine whether the
certain data is generated (e.g. from cache) , if not exists, render an
animated gif first and start process to do long run data generating task.
Else, render the normal content based on the generated data.

**suppose we've rendered the animated gif above, After render to client,
use script callback to check whether data is generated, if true, postback
the page and let our control render the normal content

Since this scriptcallback is a new one in ASP.NET 2.0, I haven't found
exact samples on this, only some general article introducing the usage of
it. If you feel necessary, I can try creating a simple control demonstrate
the above code logic.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead
This posting is provided "AS IS" with no warranties, and confers no rights.
Oct 24 '06 #14

P: n/a
I would love to see a sample, if you find the time to whip one up for me.
I`m really new to the subject and I can`t even get a picture of the
procedure in my mind.

Thank you.
Oct 24 '06 #15

P: n/a
Hello Eladla,

I've just created a sample web control which has the following code logic:

** in the createchildcontrols function check whether cached data is
available, if not render a ring image (dynamic gif) display waiting UI

** at client-side, use script callback to poll the data generation status
from server, if data has been generated, postback the page

** at server-side createchildcontrols function, render the normal UI.

Below(at bottom) is the complete control's code, however, since I've used
some embeded resource(such as embeded dynamic gif) in the control, it will
be better you get the complete control project from I. I've sent you a
email with the zipped project, you can refer to it more detailedly.

If you have any problem get it , please feel free to let me know.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead
This posting is provided "AS IS" with no warranties, and confers no rights.

===================CONTROL CODE=========================
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.Design;
using System.Web.Caching;
using System.Drawing;
using System.Threading;
using System.ComponentModel.Design;
[assembly: WebResource("UrlCopySiteLib.ring.gif", "image/gif")]

namespace UrlCopySiteLib
{

[Designer(typeof(CallbackControlDesigner), typeof(IDesigner))]
[DefaultProperty("Text")]
[ToolboxData("<{0}:CallbackControl
runat=server></{0}:CallbackControl>")]
public class CallbackControl : WebControl, ICallbackEventHandler
{
public const string DATA_KEY = "CallbackControl_Data";
private string _returndata;
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
public string Text
{
get
{
String s = (String)ViewState["Text"];
return ((s == null) ? String.Empty : s);
}

set
{
ViewState["Text"] = value;
}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
String cbReference =
Page.ClientScript.GetCallbackEventReference(this,
"arg", "ReceiveServerData", "context");

String callbackScript;
callbackScript = "function CallServer(arg, context)" +
"{ " + cbReference + "} " +
"function ReceiveServerData(rValue, context)" +
"{if(rValue == 'true'){document.forms[0].submit();} }";

Page.ClientScript.RegisterClientScriptBlock(this.G etType(),
"CallServer", callbackScript, true);

}

protected override void CreateChildControls()
{
Controls.Clear();
Table tb = new Table();
tb.ID = "tbMain";
Controls.Add(tb);
tb.Rows.Add(new TableRow());
TableCell tc = new TableCell();
tb.Rows[0].Cells.Add(tc);
tc.HorizontalAlign = HorizontalAlign.Center;
tc.VerticalAlign = VerticalAlign.Top;


if (Context.Cache[DATA_KEY] == null)
{
GenerateData();

string timerScript =
"window.setInterval(function(){CallServer(\"check_ data_generation\",
\"ctx\");}, 2000); ";
Page.ClientScript.RegisterStartupScript(this.GetTy pe(),
"timerScript", timerScript, true);
string imgurl =
Page.ClientScript.GetWebResourceUrl(this.GetType() ,
"UrlCopySiteLib.ring.gif");

LiteralControl lc1 = new LiteralControl();
lc1.Text = "<br/>Please wait for data
generation.....<br/><img src=\"" + imgurl + "\" />";

tc.Controls.Add(lc1);

}
else
{
LiteralControl lc2 = new LiteralControl();

lc2.Text = "Display with generated data....";

tc.Controls.Add(lc2);

}
}

private void GenerateData()
{
Thread thread = new Thread(new
ParameterizedThreadStart(Thread_Proc));

thread.Start(Context);

}
private void Thread_Proc(object ctx)
{
HttpContext context = ctx as HttpContext;

Thread.Sleep(10 * 1000);

context.Cache.Insert(DATA_KEY, "Hello World", null,
Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(1));

}

#region ICallbackEventHandler Members

public string GetCallbackResult()
{
return _returndata;
}

public void RaiseCallbackEvent(string eventArgument)
{
if (eventArgument == "check_data_generation")
{
_returndata = IsDataReady();
}
}

private string IsDataReady()
{
if (Context.Cache[DATA_KEY] != null)
{
return "true";
}

return "false";
}

#endregion
}
public class CallbackControlDesigner : ControlDesigner
{
public override string GetDesignTimeHtml()
{
return "<font size='20'>CallbackControl+DesignTimeHtml</font>";
}
}
}
==================================

Oct 25 '06 #16

This discussion thread is closed

Replies have been disabled for this discussion.