一、数据绑定控件-DataList以及UpdatePanel嵌套DataList效果和使用
-
DataList支持自定义数据格式,并可以添加自己的样式,可以以table重复数据项,也可以flow重复数据项,最后生成的数据显示方式不同,根据自己的需求设置,设置他的RepeatLayout属性即可。
-
DataList不支持数据的增删改查,需要自己在.aspx.cs代码的EditCommand、DeleteCommand、CancelCommand、UpdateCommand方法中自定义代码进行数据的增删改。
-
如何触发DataList的EditCommand、DeleteCommand、CancelCommand、UpdateCommand方法呢?
如下.aspx页面代码所示<asp:LinkButton ID=“lEdit” runat=“server” CommandName=“Edit / Delete / Cancel / Update”>(操作名称)</asp:LinkButton>,为button或者LinkButton添加CommandName属性==(Edit / Delete / Cancel / Update)==就可以触发对应的方法,当CommandName为其他属性时执行ItemCommand方法 -
这是我写的商品管理页面,进行了简单的布局,每一项有删改查的功能。
-
DataList aspx页面代码,我们这里用到了UpdarePanel .NET中的扩展控件实现DataList 数据的局部刷新,这里将DataList 放在UpdarePanel 的ContentTemplate中,当我们修改某一项的值后,确定修改并返回后就不会刷新整个页面,这样可以让页面锚点不回到顶部,达到Ajax局部刷新的效果,注意:UpdarePanel 控件前面需要加一个ScriptManager控件来维持页面除UpdarePanel以外其他部分的状态。
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:DataList ID="dlShopProduct" runat="server" OnDeleteCommand="dlShopProduct_DeleteCommand" OnUpdateCommand="dlShopProduct_UpdateCommand" OnItemCommand="dlShopProduct_ItemCommand" OnEditCommand="dlShopProduct_EditCommand" OnCancelCommand="dlShopProduct_CancelCommand">
<HeaderTemplate>
<tr>
<th width="10%"></th>
<th width="10%">商品ID</th>
<th width="10%">商品分类</th>
<th width="15%">商品图片</th>
<th width="10%">商品标题</th>
<th width="15%">商品描述</th>
<th width="10%">商品单价</th>
<th width="10%">商品库存</th>
<th width="10%">操作</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<label></label>
</td>
<td><%# Eval("ProductId") %></td>
<td><%# Eval("CategoryName") %></td>
<td><img src='<%# Eval("Image") %> ' height="90" /></td>
<td><%# Eval("Title") %></td>
<td><%# Eval("Descn") %></td>
<td>¥<%# Eval("Price") %></td>
<td><%# Eval("Stock") %></td>
<td>
<asp:LinkButton ID="lEdit" runat="server" CommandName="Edit">
编辑</asp:LinkButton>
<asp:LinkButton ID="lbtDelete" runat="server" CommandName="Delete" CommandArgument='<%#Eval("ProductID") %>'>
<span class="delete-button glyphicon glyphicon-remove-sign"></span></asp:LinkButton>
</td>
</tr>
</ItemTemplate>
<EditItemTemplate>
<tr>
<td>
<label></label>
</td>
<td>
<%# Eval("ProductId") %>
</td>
<td>
<asp:DropDownList ID="ddlCategory" runat="server">
<asp:ListItem>课本</asp:ListItem>
<asp:ListItem>考研</asp:ListItem>
<asp:ListItem>日用品</asp:ListItem>
<asp:ListItem>化妆</asp:ListItem>
<asp:ListItem>电子设备</asp:ListItem>
<asp:ListItem>外语相关</asp:ListItem>
<asp:ListItem>其它</asp:ListItem>
</asp:DropDownList>
</td>
<td>
<div class="form-group" style="display:inline-block;">
<div class="col-sm-8">
<img id="PImage" style="cursor: pointer;" class="cover-radius" src='<%# Eval("Image") %>' height="90" />
<%--<asp:FileUpload ID="FileUpload1" runat="server" accept=".jpg,.png"
style="position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; opacity: 0; cursor: pointer;"/>--%>
<input id="picture_upload" name="file" type="file" onchange="showInputPic('PImage',this)" accept=".jpg,.png"
style="position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; opacity: 0; cursor: pointer;"/>
<small class="help-block cover-tips" style="color: #dd4b39;display: none;">请上传图片</small>
</div>
</div>
</td>
<td><asp:TextBox ID="txtTitle" runat="server" Text='<%# Eval("Title") %>'></asp:TextBox></td>
<td><asp:TextBox ID="txtDescn" runat="server" Text='<%# Eval("Descn") %>' TextMode="MultiLine"></asp:TextBox></td>
<td><asp:TextBox ID="txtPrice" runat="server" Text='<%# Eval("Price") %>' Width="80"></asp:TextBox></td>
<td><asp:TextBox ID="txtStock" runat="server" Text='<%# Eval("Stock") %>' Width="50"></asp:TextBox></td>
<td>
<asp:LinkButton ID="LinkUpdate" OnClientClick="upload_cover('picture_upload');" runat="server" CommandName="Update" CommandArgument='<%# Eval("ProductId") %>'>
确定</span></asp:LinkButton>
<asp:LinkButton ID="lbtCancel" runat="server" CommandName="Cancel">
取消</span></asp:LinkButton>
</td>
</tr>
</EditItemTemplate>
<FooterTemplate>
</FooterTemplate>
</asp:DataList>
</ContentTemplate>
</asp:UpdatePanel>
<table>
<tr><td></td></tr>
<tr>
<td>
<label>商品上新:</label>
</td>
<td>
<asp:DropDownList ID="ddlCategory1" runat="server">
<asp:ListItem>课本</asp:ListItem>
<asp:ListItem>考研</asp:ListItem>
<asp:ListItem>日用品</asp:ListItem>
<asp:ListItem>化妆</asp:ListItem>
<asp:ListItem>电子设备</asp:ListItem>
<asp:ListItem>外语相关</asp:ListItem>
<asp:ListItem>其它</asp:ListItem>
</asp:DropDownList>
</td>
<td>
<div class="form-group" style="display:inline-block;">
<div class="col-sm-8">
<img id="PImage1" style="cursor: pointer;" class="cover-radius" src='Images/default.jpg' height="90" />
<input id="picture_upload1" name="file" type="file" onchange="showInputPic('PImage1',this)" accept=".jpg,.png"
style="position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; opacity: 0; cursor: pointer;"/>
<small class="help-block cover-tips" style="color: #dd4b39;display: none;">请上传图片</small>
</div>
</div>
</td>
<td><asp:TextBox ID="txtTitle1" runat="server" Text=''></asp:TextBox></td>
<td><asp:TextBox ID="txtDescn1" runat="server" Text='' TextMode="MultiLine"></asp:TextBox></td>
<td><asp:TextBox ID="txtPrice1" runat="server" Text='' Width="80"></asp:TextBox></td>
<td><asp:TextBox ID="txtStock1" runat="server" Text='' Width="50"></asp:TextBox></td>
<td>
<asp:Button ID="btnAddPro" OnClientClick="upload_cover('picture_upload1')" OnClick="btnAddPro_Click" CssClass="btn btn-primary" runat="server" Text="添加商品" />
</td>
</tr>
</table>
</div>
</form>
二、DataList 方法的使用,实现数据的增删改查,图片上传还有后面,请继续阅读
6. 废话不多说上代码:
private ProductService ps = new ProductService();//商品操作服务
private CategoryService cs = new CategoryService();//分类操作服务
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)//在页面首次加载非IsPostBack时绑定需要显示的数据,
//笔者碰到了进入编辑后点击确定后端获取不到输入框的输入值,
//原因就是在因为没有加if(!IsPostBack)判断
//直接绑定数据导致输入框的值在点击CommandNme="Update"
//的按钮后被执行Page_Load方法,再次绑定数据对TextBox进行了初始化
bind();
}
private void bind()//自定义数据绑定方法
{
dlShopProduct.DataSource = ps.getProductbyShop("1");
dlShopProduct.DataBind();
}
protected void dlShopProduct_DeleteCommand(object source, DataListCommandEventArgs e)
{
if (e.CommandName == "Delete")
{
ps.deleteProductbyShop(e.CommandArgument.ToString());//商品删除的方法
bind();
}
}
protected void dlShopProduct_UpdateCommand(object source, DataListCommandEventArgs e)
{
try
{
string productId = e.CommandArgument.ToString(); ///获取更新行的ProductId
//动态生成的控件获取方式:(e.Item.FindControl("[控件ID]") as [控件类型])
string categoryName = (e.Item.FindControl("ddlCategory") as DropDownList).SelectedValue;
string image = "";
if (Session["ImagePath"] != null)
image = Session["ImagePath"].ToString();///图片路径是通过.net一般处理程序也就是.ashx保存到Session
else
image = ps.getOneProductByPId(productId).Image;///没有上传图片时图片图片不改变
string title = (e.Item.FindControl("txtTitle") as TextBox).Text;
string descn = (e.Item.FindControl("txtDescn") as TextBox).Text;
decimal price = decimal.Parse((e.Item.FindControl("txtPrice") as TextBox).Text);
int stock = int.Parse((e.Item.FindControl("txtStock") as TextBox).Text);
///商品信息的修改
if (productId != null && title != null && descn != null && price >= 0 && stock >= 0)
ps.updateProductbyShop(productId, cs.getCategoryId(categoryName), title, descn, image, price, stock, "1", 0);
}
catch
{
Response.Write("<script>alert('修改失败,请重试!');</script>");
}
Session.Remove("ImagePath");///保存完后清空图片路径Session
this.dlShopProduct.EditItemIndex = -1;///隐藏编辑项
//重新绑定数据
bind();
}
protected void dlShopProduct_ItemCommand(object source, DataListCommandEventArgs e)
{
}
protected void dlShopProduct_EditCommand(object source, DataListCommandEventArgs e)
{
this.dlShopProduct.EditItemIndex = e.Item.ItemIndex; //设置编辑的索引行,将编辑行替换当前行
if (e.CommandName == "Edit")
{
///商品分类绑定到下拉列表
DropDownList ddlCategory = (DropDownList)e.Item.FindControl("ddlCategory");
if (cs.getCategoryNames().Count > 0 && ddlCategory != null)
{
ddlCategory.DataSource = cs.getCategoryNames();
ddlCategory.DataTextField = ddlCategory.DataValueField = "CategoryName";
ddlCategory.DataBind();
}
}
//重新绑定数据源
bind();
}
protected void dlShopProduct_CancelCommand(object source, DataListCommandEventArgs e)
{
DropDownList ddlCategory = (DropDownList)e.Item.FindControl("ddlCategory");
if (cs.getCategoryNames().Count > 0 && ddlCategory != null)
{
ddlCategory.DataSource = cs.getCategoryNames();
ddlCategory.DataTextField=ddlCategory.DataValueField = "CategoryName";
ddlCategory.DataBind();
}
if (e.CommandName == "Cancel")
{
this.dlShopProduct.EditItemIndex = -1;///隐藏编辑项
bind();
}
}
- 解决点击CommandName="Update"按钮后,无法获取TextBox输入的值的问题
就是添加 if(!IsPostBack) 判断后再绑定数据,原因是点击CommandNme=“Update”
的按钮后被执行Page_Load方法,如果没有if(!IsPostBack) 判断,会再次对DataLIst绑定数据对TextBox进行了初始化,当然就获取不到输入的修改值了。
这个确实要注意,一般在Page_Load中绑定数据都是要进行if(!IsPostBack)判断。
if(!IsPostBack)//在页面首次加载非IsPostBack时绑定需要显示的数据,
//笔者碰到了进入编辑后点击确定后端获取不到输入框的输入值,
//原因就是在因为没有加if(!IsPostBack)判断
//直接绑定数据,导致输入框的值在点击CommandNme="Update"
//的按钮后,执行Page_Load方法,再次绑定数据对TextBox进行了初始化
bind();
- 实现DataList数据的添加功能,这里图片上传功能改在后面,请继续阅读:
(1) 实现效果:
(2) aspx页面代码如下
<table>
<tr><td></td></tr>
<tr>
<td>
<label>商品上新:</label>
</td>
<td>
<asp:DropDownList ID="ddlCategory1" runat="server">
<asp:ListItem>课本</asp:ListItem>
<asp:ListItem>考研</asp:ListItem>
<asp:ListItem>日用品</asp:ListItem>
<asp:ListItem>化妆</asp:ListItem>
<asp:ListItem>电子设备</asp:ListItem>
<asp:ListItem>外语相关</asp:ListItem>
<asp:ListItem>其它</asp:ListItem>
</asp:DropDownList>
</td>
<td>
<div class="form-group" style="display:inline-block;">
<div class="col-sm-8">
<img id="PImage1" style="cursor: pointer;" class="cover-radius" src='Images/default.jpg' height="90" />
<input id="picture_upload1" name="file" type="file" onchange="showInputPic('PImage1',this)" accept=".jpg,.png"
style="position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; opacity: 0; cursor: pointer;"/>
<small class="help-block cover-tips" style="color: #dd4b39;display: none;">请上传图片</small>
</div>
</div>
</td>
<td><asp:TextBox ID="txtTitle1" runat="server" Text=''></asp:TextBox></td>
<td><asp:TextBox ID="txtDescn1" runat="server" Text='' TextMode="MultiLine"></asp:TextBox></td>
<td><asp:TextBox ID="txtPrice1" runat="server" Text='' Width="80"></asp:TextBox></td>
<td><asp:TextBox ID="txtStock1" runat="server" Text='' Width="50"></asp:TextBox></td>
<td>
<asp:Button ID="btnAddPro" OnClientClick="upload_cover('picture_upload1')" OnClick="btnAddPro_Click" CssClass="btn btn-primary" runat="server" Text="添加商品" />
</td>
</tr>
</table>
(3).cs中的处理逻辑
protected void btnAddPro_Click(object sender, EventArgs e)
{
try {
string categoryName = ddlCategory1.SelectedValue;
string image = "";
if (Session["ImagePath"] != null)
image = Session["ImagePath"].ToString();
else
image = "Images/default.jpg";
string title = txtTitle1.Text;
string descn = txtDescn1.Text;
decimal price = decimal.Parse(txtPrice1.Text);
int stock = int.Parse(txtStock1.Text);
if (title != null && descn != null && price >= 0 && stock >= 0)
ps.insertProductbyShop(cs.getCategoryId(categoryName), title, descn, image, price, stock, "1", 0);
} catch {
Response.Write("<script>alert('添加失败,请重试!');</script>");
//重新绑定数据
}
txtTitle1.Text = txtDescn1.Text = txtPrice1.Text = txtStock1.Text = "";
Session.Remove("ImagePath");
bind();
}
三、Ajax实现文件(图片)上传解决放在UpdatePanel中的FileUpload控件不能实现文件上传的问题,解决一般处理程序ashx无法读写session的问题
- 这里我截取了商品添加部分的aspx代码,注意:这里需要引入bootstrap.css和Jquery.js
<div class="form-group" style="display:inline-block;">
<div class="col-sm-8">
<img id="PImage1" style="cursor: pointer;" class="cover-radius" src='Images/default.jpg' height="90" />
<input id="picture_upload1" name="file" type="file" onchange="showInputPic('PImage1',this)" accept=".jpg,.png"
style="position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; opacity: 0; cursor: pointer;"/>
<small class="help-block cover-tips" style="color: #dd4b39;display: none;">请上传图片</small>
</div>
</div>
- js :Ajax部分代码:
<script type="text/javascript">
function upload_cover(obj)//ajax文件上传
{
var fileUpload = $("#"+obj).get(0);//获取文件上传input框
var files = fileUpload.files;
var data = new FormData(); //FormData数据类型用来上传文件
for (var i = 0; i < files.length; i++) {
data.append(files[i].name, files[i]);
}
$.ajax({
url: "uploadFile.ashx",
type: "POST",
data: data,
contentType: false,
processData: false,
success: function (result) {
//alert(result);
},
error: function (err) {
alert("上传失败!")
}
});
return true;
}
function showInputPic(obj,thisobj)//预览上传的图片
{
$("#"+obj).attr("src",URL.createObjectURL($(thisobj)[0].files[0]));
}
</script>
- ASP.NET一般处理程序uploadFile.ashx代码,Session将生成的文件名和路径保存到session中在以便在修改商品信息时使用。
这里笔者一开始遇到了无法获取到Session的读写权限的问题,通过查阅资料:
处理程序类
继承IRequiresSessionState接口,拥有Session的读写权限
继承IReadOnlySessionState接口,拥有Session的只读权限
<%@ WebHandler Language="C#" Class="uploadFile" %>
using System;
using System.Web;
using System.IO;
using System.Security.Cryptography;
using System.Web.SessionState;
//继承IRequiresSessionState接口,拥有Session的读写权限
//继承IReadOnlySessionState接口,拥有Session的只读权限
public class uploadFile : IHttpHandler ,IRequiresSessionState{
public void ProcessRequest (HttpContext context) {
if (context.Request.Files.Count > 0)
{
HttpFileCollection files = context.Request.Files;
string filePath = "~/ProductImg/";//保存的文件夹
string fileName = generateImageId();//根据时间戳生成的文件名
string fileEextension = Path.GetExtension(files[0].FileName);//图片后缀名
MD5 md5Hasher = new MD5CryptoServiceProvider();
for (int i = 0; i < files.Count; i++)
{
HttpPostedFile file = files[i];
context.Session["ImagePath"] = "../ProductImg/" + fileName + fileEextension;
string fname = context.Server.MapPath(filePath + fileName+ fileEextension);
file.SaveAs(fname);
}
context.Response.ContentType = "text/plain";
context.Response.Write("图片已上传到服务器!");
}
}
public string generateImageId()//为图片统一命名
{
//获取当前时间戳 13位数
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
string temp = Convert.ToInt64(ts.TotalMilliseconds).ToString();
//加上3位随机数组成用户Id
Random r = new Random();
string rd = r.Next(100, 1000).ToString();
return temp + rd;
}
/// <summary>
/// 获取文件大小
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
private string GetFileSize(long bytes)
{
long kblength = 1024;
long mbLength = 1024 * 1024;
if (bytes < kblength)
return bytes.ToString() + "B";
if (bytes < mbLength)
return decimal.Round(decimal.Divide(bytes, kblength), 2).ToString() + "KB";
else
return decimal.Round(decimal.Divide(bytes, mbLength), 2).ToString() + "MB";
}
public bool IsReusable {
get {
return false;
}
}
}
四、关于UpdatePanel局部刷新回调js方法的问题
- 需要在在加载UpdatePanel后回调整个页面的js方法来修改某些内容或者遍历UpdatePanel内的元素,只需要在页面加入以下代码
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(这里是回调的方法名);