我们知道,
Microsoft Visual Stadio (2008) 自带的
AJAX Extensions在实现页面的局部提交及(服务器端)数据回调及显示上,效果不错(除了文本输入需要通过别的方式增加键弹起,按下等客户端事件的监听及由此触发服务端事件,在此不做讨论)!
先来张截图
首先,我们来做一个简单的 用户控件,以用于在父级页面内调用并实现上传功能!
基本的设想是(功能描述)
A 能接收用户父级页面的配置
上传信息 msg
B 能接收用户父级页面对控件内上传按钮的绑定(也可以将上传核心代码放置于控件,不绑定,但这样会减少用户使用该控件的自由度。并且,这样做的优势是:无需知道父级页面上传文件中进行怎样的事件处理,将上传的文件存在服务器什么目录下等等)
C 控件被父级页面引用后
Msg 内显示用户定义的上传前信息
FileUpload 内部上传文件地址发生变化,将信息显示于 Msg 内
点击上传按钮, Msg 内显示用户的上传中信息,同时按照绑定的父级页面内该按钮事件执行相应上传操作。
上传结束,应由父级页面将该控件内部 Msg 信息改变为结束信息
atep 1,新建用户空间页面 UP.ascx
atep 2,在该页面设计视图下从工具箱内中拖一个 FileUpload ,一个 Button ,再进入代码方式下添加一个 DIV 用于标识上传信息
<asp:FileUpload ID="FileUp" runat="server" Height="24px" />
<asp:Button ID="UPing" runat="server" Text=" 上传 " Width="73px" Height="24px" />
<div id="Msg" runat="server" ></div>
atep 3,为使其上传提交不影响父级页面其他界面元素状态,现将其添加于 UpdatePanel
<asp:UpdatePanel ID="UpdatePanel1" runat="server" RenderMode="Block"UpdateMode="Conditional">
<ContentTemplate>
<asp:FileUpload ID="FileUp" runat="server" Height="24px" />
<asp:Button ID="UPing" runat="server" Text=" 上传 " Width="73px" Height="24px" />
<div id="Msg" runat="server" >等待上传...</div>
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="UPing" />
</Triggers>
</asp:UpdatePanel>
然后, 进入UP.ascx的代码(UP.ascx.cs)进行代码编写(以下CODE必须在实现了 System.Web.UI.UserControl 接口的类中,一般默认的 UP.ascx.cs 即可)
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//这里 Msg.ClientID 很重要,要是直接引用,在父级页面Msg的ID可能会成这个样子 UP1_Msg ,其中UP1是父级页面内引用该控件的ID
//这里的js要考虑在浏览器中解析正确,就必须考虑转义符 \
string js = "javascript:document.getElementById('" + Msg.ClientID + "').innerHTML = '上传中...(可以在这里放置动画图片 或者 iframe 调用其他页面(aspx)实现上传进度的检测以及上传事件的处理)';";
UPing.Attributes.Add("onclick", js);
}
}
/// <summary>
/// 用户单击事件绑定
/// </summary>
public event EventHandler onClick
{
add
{
UPing.Click += value;
//UPing.Text = "事件已经加载" + DateTime.Now.ToString() + value.Method.ToString();
}
remove
{
UPing.Click -= value;
//UPing.Text = "事件已经卸载" + DateTime.Now.ToString();
}
}
/// <summary>
/// 消息
/// </summary>
public string msg
{
get
{
//获取
return Msg.InnerHtml.ToString();
}
set
{
//设置
Msg.InnerHtml = value;
}
}
/// <summary>
/// FileUpload (组件的公开)
/// </summary>
public FileUpload FileUpload
{
get
{
//获取
return FileUp;
}
set
{
//设置
FileUp = value;
}
}
OK!控件就这样了!
下面创建“ 无刷上传.aspx” 引用控件,注意被颜色标注部分
紫色是当前无刷上传的核心
MaintainScrollPositionOnPostback="true"
分别放置于不同区域,以区别其使用状态
<uc1:UP ID="UP1" runat="server" />和 <uc1:UP ID="UP2" runat="server" />
代码开始--------------------------------------------->
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="无刷上传.aspx.cs" Inherits=" MyLove" MaintainScrollPositionOnPostback="true" Debug="true"%>
<%@ Register src="UP.ascx" tagname="UP" tagprefix="uc1" %>
<!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:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div style="height:500px; background:#CCFFCC;">我是为了看看上传数据提交后,有啥变化没有</div>
<uc1:UP ID="UP1" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server" RenderMode="Block" UpdateMode="Conditional">
<ContentTemplate>
<uc1:UP ID="UP2" runat="server" />
</ContentTemplate>
<Triggers>
<asp: PostBackTrigger ControlID="UP2" />
</Triggers>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
代码结束---------------------------------------------<
无刷上传.aspx.cs 部分
public partial class MyLove : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
UP1.onClick += new EventHandler(UP1_UPing_Click);//注册动作(事件,使用代理)
UP2.onClick += new EventHandler(UP2_UPing_Click);
}
/// <summary>
/// 上传保存事件1(就是平时按钮用的)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void UP1_UPing_Click(object sender, EventArgs e)
{
if (UP1.FileUpload.HasFile)
{
long L1 = UP1.FileUpload.FileContent.Length / 1024;//字节流
int L2 = UP1.FileUpload.PostedFile.ContentLength / 1024;//字节长度
string FileName = UP1.FileUpload.FileName;
UP1.msg = "实例化为:UP1" + DateTime.Now.ToString() + "<br/>上传字节流长度是:" + L1.ToString() + "KBit" + "<br/>上传文件大小是(千字节):" + L2.ToString() + "KB.";
//保存
UP1.FileUpload.SaveAs(Server.MapPath(@"~/temp/") + FileName);
}
else
{
UP1.msg = "不要忽悠我,没文件啊!" + DateTime.Now.ToString();
}
}
/// <summary>
/// 上传保存事件2
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void UP2_UPing_Click(object sender, EventArgs e)
{
if (UP2.FileUpload.HasFile)
{
string FileName = UP2.FileUpload.FileName;
UP2.msg = "实例化为:UP2 " + DateTime.Now.ToString() + "<br/>上传的文件名是:" + FileName;
//保存
UP2.FileUpload.PostedFile.SaveAs(Server.MapPath(@"~/temp/") + FileName);
}
else
{
UP2.msg = "你就接着忽悠吧 ~ " + DateTime.Now.ToString();
}
}
}
至此,基于ScriptManager-UpdatePanel的无刷新上传就这样实现了,当然了,这里还存在一点点小问题,就是两个实例化后的控件上传事件会清除对方FileUpload内选定文件,看来,还得考虑动态控件。
先来张截图
首先,我们来做一个简单的 用户控件,以用于在父级页面内调用并实现上传功能!
基本的设想是(功能描述)
A 能接收用户父级页面的配置
上传信息 msg
B 能接收用户父级页面对控件内上传按钮的绑定(也可以将上传核心代码放置于控件,不绑定,但这样会减少用户使用该控件的自由度。并且,这样做的优势是:无需知道父级页面上传文件中进行怎样的事件处理,将上传的文件存在服务器什么目录下等等)
C 控件被父级页面引用后
Msg 内显示用户定义的上传前信息
FileUpload 内部上传文件地址发生变化,将信息显示于 Msg 内
点击上传按钮, Msg 内显示用户的上传中信息,同时按照绑定的父级页面内该按钮事件执行相应上传操作。
上传结束,应由父级页面将该控件内部 Msg 信息改变为结束信息
atep 1,新建用户空间页面 UP.ascx
atep 2,在该页面设计视图下从工具箱内中拖一个 FileUpload ,一个 Button ,再进入代码方式下添加一个 DIV 用于标识上传信息
<asp:FileUpload ID="FileUp" runat="server" Height="24px" />
<asp:Button ID="UPing" runat="server" Text=" 上传 " Width="73px" Height="24px" />
<div id="Msg" runat="server" ></div>
atep 3,为使其上传提交不影响父级页面其他界面元素状态,现将其添加于 UpdatePanel
<asp:UpdatePanel ID="UpdatePanel1" runat="server" RenderMode="Block"UpdateMode="Conditional">
<ContentTemplate>
<asp:FileUpload ID="FileUp" runat="server" Height="24px" />
<asp:Button ID="UPing" runat="server" Text=" 上传 " Width="73px" Height="24px" />
<div id="Msg" runat="server" >等待上传...</div>
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="UPing" />
</Triggers>
</asp:UpdatePanel>
然后, 进入UP.ascx的代码(UP.ascx.cs)进行代码编写(以下CODE必须在实现了 System.Web.UI.UserControl 接口的类中,一般默认的 UP.ascx.cs 即可)
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//这里 Msg.ClientID 很重要,要是直接引用,在父级页面Msg的ID可能会成这个样子 UP1_Msg ,其中UP1是父级页面内引用该控件的ID
//这里的js要考虑在浏览器中解析正确,就必须考虑转义符 \
string js = "javascript:document.getElementById('" + Msg.ClientID + "').innerHTML = '上传中...(可以在这里放置动画图片 或者 iframe 调用其他页面(aspx)实现上传进度的检测以及上传事件的处理)';";
UPing.Attributes.Add("onclick", js);
}
}
/// <summary>
/// 用户单击事件绑定
/// </summary>
public event EventHandler onClick
{
add
{
UPing.Click += value;
//UPing.Text = "事件已经加载" + DateTime.Now.ToString() + value.Method.ToString();
}
remove
{
UPing.Click -= value;
//UPing.Text = "事件已经卸载" + DateTime.Now.ToString();
}
}
/// <summary>
/// 消息
/// </summary>
public string msg
{
get
{
//获取
return Msg.InnerHtml.ToString();
}
set
{
//设置
Msg.InnerHtml = value;
}
}
/// <summary>
/// FileUpload (组件的公开)
/// </summary>
public FileUpload FileUpload
{
get
{
//获取
return FileUp;
}
set
{
//设置
FileUp = value;
}
}
OK!控件就这样了!
下面创建“ 无刷上传.aspx” 引用控件,注意被颜色标注部分
紫色是当前无刷上传的核心
MaintainScrollPositionOnPostback="true"
分别放置于不同区域,以区别其使用状态
<uc1:UP ID="UP1" runat="server" />和 <uc1:UP ID="UP2" runat="server" />
代码开始--------------------------------------------->
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="无刷上传.aspx.cs" Inherits=" MyLove" MaintainScrollPositionOnPostback="true" Debug="true"%>
<%@ Register src="UP.ascx" tagname="UP" tagprefix="uc1" %>
<!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:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div style="height:500px; background:#CCFFCC;">我是为了看看上传数据提交后,有啥变化没有</div>
<uc1:UP ID="UP1" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server" RenderMode="Block" UpdateMode="Conditional">
<ContentTemplate>
<uc1:UP ID="UP2" runat="server" />
</ContentTemplate>
<Triggers>
<asp: PostBackTrigger ControlID="UP2" />
</Triggers>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
代码结束---------------------------------------------<
无刷上传.aspx.cs 部分
public partial class MyLove : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
UP1.onClick += new EventHandler(UP1_UPing_Click);//注册动作(事件,使用代理)
UP2.onClick += new EventHandler(UP2_UPing_Click);
}
/// <summary>
/// 上传保存事件1(就是平时按钮用的)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void UP1_UPing_Click(object sender, EventArgs e)
{
if (UP1.FileUpload.HasFile)
{
long L1 = UP1.FileUpload.FileContent.Length / 1024;//字节流
int L2 = UP1.FileUpload.PostedFile.ContentLength / 1024;//字节长度
string FileName = UP1.FileUpload.FileName;
UP1.msg = "实例化为:UP1" + DateTime.Now.ToString() + "<br/>上传字节流长度是:" + L1.ToString() + "KBit" + "<br/>上传文件大小是(千字节):" + L2.ToString() + "KB.";
//保存
UP1.FileUpload.SaveAs(Server.MapPath(@"~/temp/") + FileName);
}
else
{
UP1.msg = "不要忽悠我,没文件啊!" + DateTime.Now.ToString();
}
}
/// <summary>
/// 上传保存事件2
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void UP2_UPing_Click(object sender, EventArgs e)
{
if (UP2.FileUpload.HasFile)
{
string FileName = UP2.FileUpload.FileName;
UP2.msg = "实例化为:UP2 " + DateTime.Now.ToString() + "<br/>上传的文件名是:" + FileName;
//保存
UP2.FileUpload.PostedFile.SaveAs(Server.MapPath(@"~/temp/") + FileName);
}
else
{
UP2.msg = "你就接着忽悠吧 ~ " + DateTime.Now.ToString();
}
}
}
至此,基于ScriptManager-UpdatePanel的无刷新上传就这样实现了,当然了,这里还存在一点点小问题,就是两个实例化后的控件上传事件会清除对方FileUpload内选定文件,看来,还得考虑动态控件。