当前位置:首页 > asp.net上传文件管理控件v3

asp.net上传文件管理控件v3

点击次数:1502  更新日期:2010-12-30
\n

上传文件管理控件v3:


\n

一、引言
v2完成了将数据绑定在dataGrid上的任务,但是dataGrid毕竟是asp.net 1.x的工具,在asp.net 2.0里面,使用是gridveiw。接下来的问题就是将datagrid上的程序移植到gridview上面。
二、更换控件
最开始的时候,我觉得这两种东西本质上来讲都是一样的,差别应该只在名称上。当然,这理论我是不怎么自信的,我自学计算机技术这么多年,“理想”在“现实”面前遇到的问题不计其数,我只能“冒蒙”(东北方言)来试一试了。
还好,只是在指定数据源上有所不同。


\n

dataGrid2.DataSource = new DataView(FileList);
dataGrid2.DataBind();


\n

GridView1.DataSource = FileList;// new GridView(FileList);
GridView1.DataBind();


\n

做到这里,大概是两天前22日的时候,所以当时太具体的情况记不清了。一开始的时候,只是把绑定的对象换了一下,然后vs编译未通过,改了一下就过去了。
这部分没有什么特别之处,所以就不罗列代码了。

三、整理代码:添加Band()方法
载入页面的时候需要获取目录的内容并且将数据绑定到GridView上,删除之后也需要重新获取和绑定,所以要把获取目录和绑定的代码封装起来。所以,我把代码整理了一下,封装到了Band()方法。


\n

四、转换CheckBoxField控件为模板
接下来的问题是,如果直接是将bool数据绑定到CheckBoxField控件,那么在进入编辑状态时,就是禁用状态,无法做到根据控件删除文件。无奈之下,只好转换成模板,结果就是CheckBoxField变成了CheckBox!最初我是直接复制网上的一代码,马上复选框就可以勾选了。然后,我尝试自己输入代码,结果调试的时候出现了错误。仔细一看,原来是单引号的问题。
复制的代码来源:
<asp:CheckBox ID=”checkbox1″ runat=”server” ToolTip=’ <%#Eval(“id”) %>’>
</asp:CheckBox>
我自己转换的模板再加上手工输入的代码
<asp:CheckBox ID=”CheckBox1″ runat=”server” ToolTip=’<%#Eval(“文件名”) %>’/>
出错的地方:
<asp:CheckBox ID=”CheckBox1″ runat=”server” ToolTip=“<%#Eval(“文件名”) %>”/>
然后,我又做了一个试验,先给CheckBoxField绑定数据,再将它转换为模板。在设计视图下,这人checkbox仍然是禁用的。可是我不死心,我觉得,不管怎么着,GridView总得给我一个能选的复选框吧?(呵呵,前面已经做出来了,所以我有信心。)进入源视图,看到的是:
<asp:TemplateField HeaderText=”选二” SortExpression=”文件名”>
<EditItemTemplate>
<asp:CheckBox ID=”CheckBox2″ runat=”server” Checked=’<%# Bind(“选择”) %>’ />
</EditItemTemplate>
<ItemTemplate>
<asp:CheckBox ID=”CheckBox2″ runat=”server” Checked=’<%# Bind(“选择”) %>’ Enabled=”False” />
</ItemTemplate>
</asp:TemplateField>
那么就是在这里了:Enabled=”False”,在HTML中,input标记有一个Disabled属性,而这里看到了Enabled(Disabled和Enabled是反义词),我觉得有门,可以试一试。在代码里修改一下Enabled=”True”,运行一下,看到的结果是成功了!
然后我再回来看一遍代码:Eval和Band是怎么回事?这好像是一个很基础的问题,可是时间长了,我都忘记辨析它们的地方是哪里了,还好,MSDN上说得很清楚。


\n

五、用哪种方式删除


\n

其实写到这里的时候,v4的框架已经出来,本来打算v2和v3只是简略的写一下,做一个简略的过渡就行了,但是在查找资料的过程中,看到数种结合CheckBox删除的例子。于是忍不住,尝试一下,所以,这一系列文章的写作时间跨度有点长,这个V3本身的也就罗嗦了。
删除的方式,主要有三种:
第一种:添加按钮,在按钮的事件中判断复选框是否已经勾选,再根据复选框的属性删除。这是我首先测试并且成功的一种方法。后面我会介绍这个过程。
第二种:也需要添加按钮,在按钮的事件中判断复选框,不同的时,第二种方法需要从DataKey获取值。
第三种:增加删除列,单行删除。因为这个GridView使用的原始数据是文件对象数组,不是数据库,不能执行Sql的删除语句,所以在v3里是不能实现的。所以,才逼我出了v4,在v4里将会结合强大ObjcetDataSource,将数组模拟成数据库,让GridView能使用智能任务面板上的”删除“功能。使数组数据源看起更像数据库一些。
ObjectDateSource,还有一种方式实现删除的,那就是CommandField控件。到底哪一种,在v4里面见分晓。


\n

六、使用CheckBox的属性获取值
给CheckBox添加ToolTip属性后,浏览器看到的代码是:
<span title=”不能停下的节奏-月亮.mp3″><input id=”ListUpload_v3_1_GridView1_ctl07_CheckBox1″ type=”checkbox” name=”ListUpload_v3_1GridView1ctl07CheckBox1″ /></span>
也就是说ToolTip属性在浏览器那里被转换成了title。这个是我在这个方案测试通过之后才发现的。目前我对Asp.net了解的实在是太浅了,所以我不禁怀疑,<span>标记也能传递值?可是我毕竟测试通过了呀!
1、添加按钮和按钮的事件。按钮的ID是DelFileBt,事件是:DelFileBt_Click
2、添加用来显示调试信息的lable,ID是ResultMsg2。(先前添加了一个TextBox,ID是ResultMsg1但是测试的时候,没有结果所以这个顺序排到2)
3、处理DelFileBt_Click事件
protected void DelFileBt_Click(object sender, EventArgs e)
{

if (IsPostBack)//这个东西搞不懂什么时候用,什么时候不用。
{
ResultMsg2.Text = “”;//一开始没加这个,以前选中的项目就会反复出现

for (int i = 0; i < GridView1.Rows.Count; i++)
{
CheckBox cbx = GridView1.Rows[i].FindControl(“CheckBox1″) as CheckBox;
if (cbx.Checked)
{
ResultMsg2.Text += “<br/> i:” + i + ” ” + cbx.ToolTip;//调试信息:显示被选中的文件
DelFile(cbx.ToolTip);//执行删除
}


\n

}
}
}

七、从DataKey获取值
这个方法最初的思想是希望使用其它数据列的值,但是在实际调试的过程中发现,使用Cells获取的是单元格对象,而不是我想象中的Fields。这里费了很大的力气,也让我再次体会,asp.net很多地方不能像asp那么简单直接。
最后是翻书加上看MSDN,采用了的DataKey对象。


\n

1、添加按钮和按钮的事件。按钮的ID是DelFileBt2,事件是:DelFileBt2_Click
2、添加用来显示调试信息的lable,ID是ResultMsg3。
3、为GridView添加DataKeyNames,我这个控件,在删除的时候,只有文件名是有用的,所以只需要文件名一项即可。实际上经过测试,可以使用多项。
多项的时候,是这个样子的:DataKeyNames=”文件名,上传日期”
4、处理DelFileBt2_Click事件
protected void DelFileBt2_Click(object sender, EventArgs e)
{
ResultMsg3.Text = “”;
for (int i = 0; i < GridView1.Rows.Count; i++)
{
CheckBox cbx = GridView1.Rows[i].FindControl(“CheckBox1″) as CheckBox;
if (cbx.Checked)
{
GridView1.SelectedIndex = i;//SelectedIndex是个可取写的索引,可以通过它来设置哪一行被选中,再获取该行的DataKey


\n

ResultMsg3.Text += “<br/> i:” + i; // +” ” + GridView1.Rows[i].Cells[1].ID + ” :” + GridView1.Rows[i].DataItem;//.DataKeys[0].Value;// GridView1.Rows[i].FindControl(“文件名”).Text;
//经过测试,上面注释这几个都是失败的,它们返回的都是值。
//DataKeys[0].Value开始的时候也是返回空值,原因是那时没有给GridView指定DataKeyNames

ResultMsg3.Text += GridView1.SelectedDataKey.Value;//默认指向一行中一系列DataKey中的第一个,
//SelectedDataKey.Value相当于SelectedDataKey.Values[0]

ResultMsg3.Text += ” DateKey.Values:” + GridView1.SelectedDataKey.Values[1];//可以获取任意某个SelectDatakey的值


\n

ResultMsg3.Text += ” @@@” + GridView1.DataKeys[i].Value;//这个是最简洁的用法,有它根本不必使用选中行,“GridView1.SelectedIndex”这上下两行,都用不上,最终我决定用它了。
DelFile(GridView1.DataKeys[i].Value);//执行删除


}
GridView1.SelectedIndex = -1;//取消选中行,如果没有这个,就会在页面上显示出最后一行已经是选中的状态。
}
}


\n


八、另一种循环和另一种获取值的办法
在查找资料的时候,看到百度知道的另一种循环方式。它循环的是DataGrid对象中包含的DataGridItem集合。
查看MSDN,GridView对象没有这样的Item集合,却找到GridViewRow集合,凭个人经验来看,这两个似乎是差不多的。
在写代码的时候,忽然发现,其实这和前面循环Rows,是一样的,那么还要不要继续呢?我一直不死心,一直希望能够找到直接获取列值的方法。于是我便做了下去。
要查看DataGridItem类的时候(MSDN),看到MSDN上用DataBoundLiteralControl获取列上面包含的控件,最后终于用这个办法获取到了列的值。
今天有一个项目(asp)追得比较紧,所以具体的我就不多说了,下面是代码(我这边加到了DelFileBt2_Click里面):
/*
* 我前面用的是循环GridView1.Rows集合
* 下面测试一下在网上看到的另外一种循环
* 网上代码采用的是asp.net 1.x 的DataGrid对象和DataGridItem对象
* 现在我用的是GridView对象和GridViewRow对象
*
*/
ResultMsg3.Text += “<hr/>下面开始测试另一种循环:<br/>”;
foreach (GridViewRow r in GridView1.Rows)
{
//MSDN有一种用法selectRow.Cells[2].Controls[0];,我也许可以试一下。


\n


//
//经过测试,下面三种用法均无法获得值
//
ResultMsg3.Text += “<br/>DataItem:” + r.DataItem;
ResultMsg3.Text += ” r.Cells[5].Text:” + r.Cells[5].Text;
ResultMsg3.Text += ” r.Cells[1].Text:” + r.Cells[1].Text;


\n


/*
* 目前找到的唯一的一种能直接获取列内值的用法
* 但是要求采用下面的方法
*
* <asp:TemplateField HeaderText=”测试列” Visible=”False”>
* <ItemTemplate>
* <%#Eval(“文件名”)%>
* </ItemTemplate>
* </asp:TemplateField>
* 通过观察发现,浏览器显示的时候,直接在<td></td>里面放置文本。是否可以扩展Eval()实际更多功能,暂时没有研究。
* 如果数据列的表现形式不符台前台显示的要求,比如说需要制作链接功能。
* 可以像上面那样,通过设置Visible=”False”,在前台不显示这一列。
*
*
*/
DataBoundLiteralControl filename = (DataBoundLiteralControl)r.Cells[5].Controls[0];
ResultMsg3.Text += ” filename.Tex:” + filename.Text;


\n

}


\n

——————下面是有关DataBoundLiteralControl 类 的资料(MSDN):
DataBoundLiteralControl 类
保留数据绑定表达式和静态文本。无法继承此类。


\n

DataBoundLiteralControl firstNameLiteral = (DataBoundLiteralControl)selectRow.Cells[2].Controls[0];
String firstName = firstNameLiteral.Text;
——————-资料结束


\n


九、删除文件DelFile


\n

protected bool DelFile(string strFilename)
{

string filePath;//获取文件路径
if (strDir.EndsWith(“/”))//查看路径是不是以/结尾的
{
filePath = Server.MapPath(strDir + strFilename);
}
else
{

filePath= Server.MapPath(strDir + “/” + strFilename);
}
Response.Write(filePath);
FileInfo oFile = new FileInfo(filePath);


\n

if (oFile.Exists)//判断文件是否存在
{
oFile.Delete();
Band();//重新绑定,要不然被删除的文件仍然会显示。
return true;
}
else
{
Response.Write(“对不起您操作的文件” + strFilename + “不存在。”);
return false;
}

}


\n

十、v3后记
没想到后在v3这里使用这么长的时间。当然付出就会有收获,所以从v3这里收获也不少。
现在想想v3遇到的这么多问题,我稍微有点担心,v4的删除会顺利吗?


\n

::::::::::::::::::::::::::
错误和调试心得:
①CheckBoxField,只能绑定Bool型的数据列,它只用来表示数据列中的Bool型的结果。如果绑定string int类型的数据就会出错。
在默认的显示状态下是禁用的,只有编辑列的时候能勾选或者取消勾选,也就是说,平常用处不大。
②在asp.net服务器控件绑定的时候,属性里的格式是xxxx=’<%# Eval(“ssss”) %>’ 。注意,外面用的单引号,否则会出错。在vs2005的代码状态下看到的是单引号,IIS传送给客户端浏览器却是双引号。
③查看MSDN,得知Eval 用来绑定只读的数据,Band则是支持读写的。下面是MSDN原话:Eval 方法是静态(只读)方法,该方法采用数据字段的值作为参数并将其作为字符串返回。Bind 方法支持读/写功能,可以检索数据绑定控件的值并将任何更改提交回数据库。
也就是在“ItemTemplate”里用哪种都行,在“EditItemTemplate”里只能用Band。


\n


<%@ Control Language=”C#” ClassName=”ListUpload_v3″ %>
<%@ Import Namespace=”System.IO” %>
<%@ Import namespace=”System.Data” %>


\n

<script runat=”server”>
/**//****************************************************************
**上传文件管理控件
**文件名:ListUpload_v3.ascx 
**Copyrigth(c) 2008-2010 *************** 柳城别日 xpnew.cnblogs.com
**文件编号:
**创建人:柳城别日
**日期:2008年5月22日
**修改人:柳城别日
**日期:2008年5月24日
* 描述:用来管理上传文件,支持列表、删除
**/


\n

//


\n

/**//* class ListUpload2
{
}
*
*
* */
// 类内部初始化
private string _strDir = @”~/Upload/”;


public string strDir//通过这个属性,可以设置控件所要管理的目录
{
get
{
return _strDir;
}
set
{
_strDir = value;
}
}


\n

protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
//绑定


\n

Band();
}
}
public void Band()
{
DataTable FileList = new DataTable();
//FileList为声明一个表


\n

DataRow FileItem;
//表示Table中行的数据


\n


FileList.Columns.Add(new DataColumn(“选择”, typeof(bool)));
FileList.Columns.Add(new DataColumn(“文件名”, typeof(string)));
FileList.Columns.Add(new DataColumn(“大小(字节)”, typeof(Int32)));
FileList.Columns.Add(new DataColumn(“上传日期”, typeof(DateTime)));
//Columns为取值该表列的集合,
//Add.为该表添加到列的集合 DataColumn为列框架
//前面是列头的标题,后面表示该列的数据类型—-这是别人的注释
//我认为前面不单单是标题那么简单,在v4里后详细地说明


\n


string dirPath = Server.MapPath(strDir);
DirectoryInfo Dir = new DirectoryInfo(dirPath);
FileInfo[] arrFiles = Dir.GetFiles();


\n

foreach (FileInfo f in arrFiles)
{
FileItem = FileList.NewRow();
//创建与该表具有相同框架新的数据行
FileItem[0] = false;
FileItem[1] = f.Name;
FileItem[2] = f.Length;
FileItem[3] = f.LastWriteTime;
//为数据行添加数值


\n

FileList.Rows.Add(FileItem);
//把获得数值的指定的行加到该表的集合


\n

}


\n

GridView1.DataSource = FileList;// new GridView(FileList);
GridView1.DataBind();


\n

}

\n

protected void DelFileBt_Click(object sender, EventArgs e)
{

if (IsPostBack)
{
ResultMsg2.Text = “”;

for (int i = 0; i < GridView1.Rows.Count; i++)
{
CheckBox cbx = GridView1.Rows[i].FindControl(“CheckBox1″) as CheckBox;
if (cbx.Checked)
{
ResultMsg2.Text += “<br/> i:” + i + ” ” + cbx.ToolTip;
}


\n

}
}
}


\n

protected void DelFileBt2_Click(object sender, EventArgs e)
{
ResultMsg3.Text = “”;
for (int i = 0; i < GridView1.Rows.Count; i++)
{
CheckBox cbx = GridView1.Rows[i].FindControl(“CheckBox1″) as CheckBox;
if (cbx.Checked)
{
GridView1.SelectedIndex = i;//SelectedIndex是个可取写的索引,可以通过它来设置哪一行被选中,再获取该行的DataKey


\n

ResultMsg3.Text += “<br/> i:” + i; // +” ” + GridView1.Rows[i].Cells[1].ID + ” :” + GridView1.Rows[i].DataItem;//.DataKeys[0].Value;// GridView1.Rows[i].FindControl(“文件名”).Text;
//经过测试,上面注释这几个都是失败的,它们返回的都是值。
//DataKeys[0].Value开始的时候也是返回空值,原因是那时没有给GridView指定DataKeyNames

ResultMsg3.Text += GridView1.SelectedDataKey.Value;//默认指向一行中一系列DataKey中的第一个,
//SelectedDataKey.Value相当于SelectedDataKey.Values[0]

ResultMsg3.Text += ” DateKey.Values:” + GridView1.SelectedDataKey.Values[1];//可以获取任意某个SelectDatakey的值


\n

ResultMsg3.Text += ” @@@” + GridView1.DataKeys[i].Value;
DelFile(GridView1.DataKeys[i].Value.ToString());//执行删除


}
GridView1.SelectedIndex = -1;
}


\n

/**//*
* 我前面用的是循环GridView1.Rows集合
* 下面测试一下在网上看到的另外一种循环
* 网上代码采用的是asp.net 1.x 的DataGrid对象和DataGridItem对象
* 现在我用的是GridView对象和GridViewRow对象
*
*/
ResultMsg3.Text += “<hr/>下面开始测试另一种循环:<br/>”;
foreach (GridViewRow r in GridView1.Rows)
{
//MSDN有一种用法selectRow.Cells[2].Controls[0];,我也许可以试一下。


\n


//
//经过测试,下面三种用法均无法获得值
//
ResultMsg3.Text += “<br/>DataItem:” + r.DataItem;
ResultMsg3.Text += ” r.Cells[5].Text:” + r.Cells[5].Text;
ResultMsg3.Text += ” r.Cells[1].Text:” + r.Cells[1].Text;


\n


/**//*
* 目前找到的唯一的一种能直接获取列内值的用法
* 但是要求采用下面的方法
*
* <asp:TemplateField HeaderText=”测试列” Visible=”False”>
* <ItemTemplate>
* <%#Eval(“文件名”)%>
* </ItemTemplate>
* </asp:TemplateField>
* 通过观察发现,浏览器显示的时候,直接在<td></td>里面放置文本。是否可以扩展Eval()实际更多功能,暂时没有研究。
* 如果数据列的表现形式不符台前台显示的要求,比如说需要制作链接功能。
* 可以像上面那样,通过设置Visible=”False”,在前台不显示这一列。
*
*
*/
DataBoundLiteralControl filename = (DataBoundLiteralControl)r.Cells[5].Controls[0];
ResultMsg3.Text += ” filename.Tex:” + filename.Text;


\n

}
}


\n

protected bool DelFile(string strFilename)
{

string filePath;//获取文件路径
if (strDir.EndsWith(“/”))//查看路径是不是以/结尾的
{
filePath = Server.MapPath(strDir + strFilename);
}
else
{

filePath= Server.MapPath(strDir + “/” + strFilename);
}
Response.Write(filePath);
FileInfo oFile = new FileInfo(filePath);


\n

if (oFile.Exists)//判断文件是否存在
{
oFile.Delete();
Band();//重新绑定,要不然被删除的文件仍然会显示。
return true;
}
else
{
Response.Write(“对不起您操作的文件” + strFilename + “不存在。”);
return false;
}

}


\n


</script>


\n

&nbsp;<asp:GridView ID=”GridView1″ runat=”server” CellPadding=”4″ ForeColor=”#333333″
GridLines=”None” AutoGenerateColumns=”False” DataKeyNames=”文件名,上传日期”>
<FooterStyle BackColor=”#1C5E55″ Font-Bold=”True” ForeColor=”White” />
<Columns>
<asp:TemplateField HeaderText=”选”>
<EditItemTemplate>
<asp:CheckBox ID=”CheckBox1″ runat=”server” ToolTip=’<%#Eval(“文件名”) %>’/>
</EditItemTemplate>
<ItemTemplate>
<asp:CheckBox ID=”CheckBox1″ runat=”server” ToolTip=’<%#Eval(“文件名”) %>’/>
</ItemTemplate>
</asp:TemplateField>
<asp:HyperLinkField DataNavigateUrlFormatString=”upload/{0}” DataTextField=”文件名” DataNavigateUrlFields=”文件名” NavigateUrl=”upload/” Target=”_blank” />
<asp:BoundField DataField=”大小(字节)” />
<asp:BoundField DataField=”上传日期” />
<asp:TemplateField HeaderText=”选二” SortExpression=”文件名”>
<EditItemTemplate>
<asp:CheckBox ID=”CheckBox2″ runat=”server” Checked=’<%# Bind(“选择”) %>’ />
</EditItemTemplate>
<ItemTemplate>
<asp:CheckBox ID=”CheckBox2″ runat=”server” Checked=’<%# Bind(“选择”) %>’ Enabled=”True” />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText=”测试列” Visible=”False”>
<ItemTemplate>
<%#Eval(“文件名”)%>
</ItemTemplate>
</asp:TemplateField>


\n

</Columns>
<RowStyle BackColor=”#E3EAEB” />
<EditRowStyle BackColor=”#7C6F57″ />
<SelectedRowStyle BackColor=”#C5BBAF” Font-Bold=”True” ForeColor=”#333333″ />
<PagerStyle BackColor=”#666666″ ForeColor=”White” HorizontalAlign=”Center” />
<HeaderStyle BackColor=”#1C5E55″ Font-Bold=”True” ForeColor=”White” />
<AlternatingRowStyle BackColor=”White” />
</asp:GridView>
<br />
<asp:Button ID=”DelFileBt” runat=”server” onClick=”DelFileBt_Click” Text=”删除” />&nbsp;&nbsp;
<asp:Label ID=”ResultMsg2″ runat=”server” Text=”Label”></asp:Label>
<br />
<asp:Button ID=”DelFileBt2″ runat=”server” onClick=”DelFileBt2_Click” Text=”删除” />
<asp:Label ID=”ResultMsg3″ runat=”server” Text=”Label”></asp:Label>

上一篇:asp.net上传文件管理控件v2

来源:http://www.cnblogs.com/xpnew

\n