下面又是一篇转译自外国网站的控件开发文章:
文章主要介绍了一个用来显示图片的自定义控件,当然在DATAGRID或其它的列表控件中显示图片有很多方式,但以下这种方式让你的代码看起来更清淅,执行效率会更高.它不用在调用另一个网页,对每一个图片进行数据库查询处,它只是在绑定过程中就处理了来自数据库的数据.
以下是控件源码:
using System.Collections.Specialized;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.WebControls;
using System.Reflection ;
using System.ComponentModel;
namespace PAB.WebControls
{
public enum ImageType
{
Gif,
Jpeg
}
public enum Persistence
{
Cache,
Session
}
[Designer("PAB.WebControls.ImageControlDesigner"),
ToolboxDataAttribute("<{0}:ImageControl Runat=\"server\"></{0}:ImageControl>")]
public class ImageControl : Control
{
protected string ImageUrl;
private ImageType imageType;
[Description("Image Type")]
[Category("Data")]
[DefaultValue("Gif")]
[Browsable(true)]
public ImageType ImageType
{
get
{
return imageType;
}
set
{
imageType=value;
}
}
private Persistence persistenceType;
[Description("Cache or Session Persistence")]
[Category("Data")]
[DefaultValue("Cache")]
[Browsable(true)]
public Persistence PersistenceType
{
get
{
return persistenceType;
}
set
{
persistenceType=value;
}
}
private Bitmap _bitmap;
[Browsable(false)]
public Bitmap Bitmap
{
get
{
if(this.PersistenceType==Persistence.Session )
return (Bitmap)Context.Session[String.Concat(CreateUniqueIDString(), "Bitmap")];
else
return (Bitmap)Context.Cache[String.Concat(CreateUniqueIDString(), "Bitmap")];
}
set
{
if(this.PersistenceType==Persistence.Session)
Context.Session[String.Concat(CreateUniqueIDString(), "Bitmap")] = value;
else
Context.Cache[String.Concat(CreateUniqueIDString(), "Bitmap")] = value;
}
}
private string CreateUniqueIDString()
{
string idStr=String.Empty;
string tmpId=String.Empty;
if( this.PersistenceType ==Persistence.Session )
{
idStr = "__" +Context.Session.SessionID.ToString() +"_";
}
else
{
if(Context.Cache["idStr"]==null)
{
tmpId=Guid.NewGuid().ToString();
Context.Cache["idStr"]=tmpId;
}
idStr= "__"+Context.Cache["idStr"].ToString() +"_";
}
idStr = String.Concat(idStr, UniqueID);
idStr = String.Concat(idStr, "_");
idStr = String.Concat(idStr, Page.ToString());
idStr = String.Concat(idStr, "_");
return idStr;
}
private void ImageControl_Init(EventArgs e)
{
HttpRequest httpRequest = Context.Request;
HttpResponse httpResponse = Context.Response;
if (httpRequest.Params[String.Concat("ImageControl_", UniqueID)] != null)
{
httpResponse.Clear();
if(this.ImageType==ImageType.Gif)
{
httpResponse.ContentType = "Image/Gif";
Bitmap.Save(httpResponse.OutputStream,ImageFormat.Gif );
}
else
{
httpResponse.ContentType = "Image/Jpeg";
Bitmap.Save(httpResponse.OutputStream, ImageFormat.Jpeg);
}
httpResponse.End();
}
string str = httpRequest.Url.ToString();
if (str.IndexOf("?") == -1)
{
ImageUrl = String.Concat(str, "?ImageControl_", UniqueID, "=1");
}
else
{
ImageUrl = String.Concat(str, "&ImageControl_", UniqueID, "=1");
}
}
protected override void OnInit(EventArgs e)
{
ImageControl_Init(e);
}
protected override void Render(HtmlTextWriter output)
{
output.Write("<img id={0} src={1}>", this.UniqueID,ImageUrl );
}
}
public class ImageControlDesigner: System.Web.UI.Design.ControlDesigner
{
public ImageControlDesigner(){}
public override string GetDesignTimeHtml()
{
return GetEmptyDesignTimeHtml ();
}
protected override string GetEmptyDesignTimeHtml()
{
return CreatePlaceHolderDesignTimeHtml( "<div>[Image is set at runtime. Place
control inside Table TD or DIV for absolute positioning.]</div>");
}
}
}
下面就是具体的应用了:
下面是写到绑定DG控件的HTML代码:
runat ="server" AutoGenerateColumns ="False" >
< Columns >
< asp:BoundColumn DataField ="name" HeaderText ="Name" ></ asp:BoundColumn >
< asp:TemplateColumn HeaderText ="Image" >
< ItemTemplate >
< cc1:ImageControl id ="ImageControl1" Runat ="server" ></ cc1:ImageControl >
</ ItemTemplate >
< EditItemTemplate >
< asp:TextBox id ="TextBox1" runat ="server" ></ asp:TextBox >
</ EditItemTemplate >
</ asp:TemplateColumn >
</ Columns >
</ asp:DataGrid >
{
SqlConnection cn;
cn = new SqlConnection
("DATABASE=northwind;SERVER=localhost;UID=sa;");
String cmdText = "SELECT top 4 lastname as name, photo as image FROM Employees";
SqlDataAdapter da = new SqlDataAdapter(cmdText,cn);
DataSet ds=new DataSet();
da.Fill(ds);
DataTable tbl = ds.Tables[0];
DataGrid1.DataSource=tbl;
DataGrid1.DataBind();
}
{
MemoryStream ms=null;
PAB.WebControls.ImageControl ctrl=null;
byte[] b=null;
if ( e.Item.ItemType == ListItemType.AlternatingItem ||
e.Item.ItemType == ListItemType.Item)
{
b = (byte[])(DataBinder.Eval(e.Item.DataItem, "image"));
ms = new MemoryStream();
// 78 is the size of the OLE header for Northwind images, need to strip it off
int offset = 78;
ms.Write(b, offset, b.Length-offset);
ctrl = (PAB.WebControls.ImageControl)e.Item.FindControl("ImageControl1");
ctrl.Bitmap=(Bitmap)System.Drawing.Image.FromStream(ms);
}
}
We need a MemoryStream for this operation. If the item being databound is a regular data display row, we cast the Item.DataItem "image" DataRowView Column to a byte array. In this particular case, Images in the Northwind Employees table were designed from MS Access, which expects a 78 byte OLE header, which we'll strip off. We write the rest of the array into our MemoryStream. Finally, we cast the e.Item.FindControl("ImageControl1") to an instance of my PAB.WebControls.ImageControl, assign the Image to it's Bitmap property, and -- voila! here's what we get:
在这个操作过程当中,我们需要MemoryStream流,如果被绑定的列是普通列的话,我们要把这个列转化为"IMAGE"格式的列.在MS ACCESS数据库中,有前78字节的OLE HEADER,这是自动加上去的,我们要把它去掉,把余下的写入到我们的MemoryStream流当中.
原文章出处和执行结果:请参见!