这是本人第一篇博客,首先相各位博友问个好。博客注册了有好长一段时间, 一直没有时间写点什么东西。最近项目终于不像以前忙了, 想起来写点什么。
前段时间在项目遇到一个长任务显示进度条的问题。 在网上找了好久都没有找到好的控件。要么下下来bug 一堆, 要么就是用起来极端不方便。于是琢磨着自己写一个。站在各位前辈的肩上,花了2 天的时间终于让我弄出来了。
总的思路就是: 客户端使用Javascript 周期调用回调函数, 从而达到不刷新效果。

废话少说, 来看代码:
protected
override
void
OnPreRender(EventArgs e)

{
ClientScriptManager csm = this.Page.ClientScript;
string startReference = this.Page.ClientScript.GetCallbackEventReference(this, "0", "UpdateState", null);
string reference = this.Page.ClientScript.GetCallbackEventReference(this, null, "UpdateState", null);
System.Text.StringBuilder scriptBuilder = new StringBuilder();
scriptBuilder.AppendLine("var timerId;");
scriptBuilder.AppendLine(" function start()");

scriptBuilder.AppendLine("{");
scriptBuilder.AppendLine(startReference + ";");
scriptBuilder.AppendLine(" timerId = setInterval( function (){" + reference + "; }," + RefleshTimeSpan + " );");
scriptBuilder.AppendLine("}");
scriptBuilder.AppendLine("function UpdateState(arg, context)");
scriptBuilder.AppendLine("{");
scriptBuilder.AppendLine("if(arg != \"\")");
scriptBuilder.AppendLine(" {");
scriptBuilder.AppendLine("var contents = arg.split(\"],[\");");
scriptBuilder.AppendLine("var currentProgress = contents[0].substring(1);");
scriptBuilder.AppendLine("var infoText = contents[1].substring(0, contents[1].length - 1);");

scriptBuilder.AppendLine("document.getElementById(\"innerDiv\").style.width = currentProgress ;");
if (!string.IsNullOrEmpty(this.InfoProviderID))

{
scriptBuilder.AppendLine("document.getElementById('" + this.InfoProviderID + "').innerText = infoText;");
}
scriptBuilder.AppendLine("if(currentProgress >= " + this.InnerWidth + ")");
scriptBuilder.AppendLine("{");
if (!string.IsNullOrEmpty(this.InfoProviderID))

{
scriptBuilder.AppendLine("document.getElementById('" + this.InfoProviderID + "').innerText = infoText;");
}
scriptBuilder.AppendLine("document.getElementById(\"innerDiv\").style.width = " + this.InnerWidth + ";");
scriptBuilder.AppendLine("window.clearInterval(timerId);");
scriptBuilder.AppendLine("}");
scriptBuilder.AppendLine("}");
scriptBuilder.AppendLine("}");
if (!csm.IsStartupScriptRegistered("callback"))

{
csm.RegisterClientScriptBlock(this.GetType(), "callback", scriptBuilder.ToString(), true);
}
}
向客户端注册Javascript
protected
override
void
RenderContents(HtmlTextWriter output)

{
output.AddAttribute(HtmlTextWriterAttribute.Id, "innerDiv");
if (this.ProgressBackColor != Color.Empty)

{
output.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, ColorTranslator.ToHtml(ProgressBackColor));
}
if (!ControlStyle.IsEmpty)


if (!ControlStyle.Height.IsEmpty)

{
output.AddStyleAttribute(HtmlTextWriterStyle.Height, this.Height.Value.ToString());
}
}
if (!string.IsNullOrEmpty(this.ProgressBackImage))

{
output.AddStyleAttribute(HtmlTextWriterStyle.BackgroundImage, string.Format("url({0})", this.ProgressBackImage));
}
output.RenderBeginTag(HtmlTextWriterTag.Div);
output.RenderEndTag();
}
protected override HtmlTextWriterTag TagKey
{
get
{
return HtmlTextWriterTag.Div;
}
}
Render 控件
ICallbackEventHandler Members
#region ICallbackEventHandler Members

public string GetCallbackResult()

{
return string.Format("[{0}],[{1}]", currentProgress.ToString(), InfoText);
}

public void RaiseCallbackEvent(string eventArgument)

{
if (eventArgument =="0")

{
if (TaskStartDelegate != null)

{
currentProgress = 0;

Thread td = new Thread(TaskStartDelegate);
try

{
td.Start();
}
catch (Exception ex)

{
td.Abort();
throw ex;
}
}
}
}
#endregion
ICallBackEventHandler 接口实现
<
body
>
<
form id
=
"
form1
"
runat
=
"
server
"
>
<
cc1:ProgressControl ID
=
"
ProgressControl1
"
runat
=
"
server
"
Height
=
"
35px
"
Width
=
"
535px
"
ProgressBackColor
=
"
White
"
BackColor
=
"
#FF8080
"
BorderColor
=
"
#C0C0FF
"
BorderStyle
=
"
Solid
"
BorderWidth
=
"
20px
"
/>
</
form
>
<
span id
=
"
span1
"
runat
=
"
server
"
enableviewstate
=
"
false
"
>
<
script language
=
"
javascript
"
type
=
"
text/javascript
"
>
start();
</
script
>
</
span
>
</
body
>
使用Javascript 函数start() 进行调用。 本来想把调用封装成一个服务器端方法, 但是由于asp.net无法控制javascript 的注册顺序。只好通过客户端来调用。 各位如果有什么好的注意,不凡告诉我一声。
protected
void
Page_Load(
object
sender, EventArgs e)

{
this.ProgressControl1.MaxProgress = 100;
this.ProgressControl1.TaskStartDelegate = new System.Threading.ThreadStart(ProcessMethod);
this.ProgressControl1.InfoProviderID = this.span1.ID;
}

public
void
ProcessMethod()

{
for (int i = 0; i < 101; i++)

{
Thread.Sleep(100);
this.ProgressControl1.Progress = i;
this.ProgressControl1.SetInfoText("已经进行到第" + i.ToString() + "个任务");
}
}
调用页面服务器端代码。
至此, 大部分的代码都已经在这儿了。
下载控件