由于HtmlHelper通过硬编码的方式来输出html,这样生成的内容和样式如果不是在开发人员协助似乎很难调整。下面通过匿名函数来实现HtmlHelper生成的关键内容委托给Aspx的html内容来完成,这样即使是不懂程序的美工也能够很好的调整样式和输出内容的格式。
以下是一个Grid的HtmlHelper的调用:
<div>
<%
System.Collections.Generic.List<User> users = new System.Collections.Generic.List<User>();
users.Add(new User("henry1", "aaaa"));
users.Add(new User("henry2", "aaaa"));
users.Add(new User("henry3", "aaaa"));
users.Add(new User("henry4", "aaaa"));
HtmlHelper.Grid<User>(users, "",
new Column<User>{
Caption= "用户名",
ItemField="Name",
ItemBlock= delegate(ItemArgs<User> e)
{%>
<a href="?<%=e.Source.Name %>"><%=e.Source.Name%></a>
<% }
},
new Column<User>{
Caption="邮件",
ItemField="Mail",
ItemBlock=delegate(ItemArgs<User> e) {%>
<input value="<%=e.Source.Mail %>" style="width: 315px" />
<% }
},
new Column<User>{
Caption="操作",
ItemBlock=delegate(ItemArgs<User> e) {%>
<a href="javascript:if(confirm('是否要删除<%=e.Source.Name %>用户'))
{alert('<%=e.Source.Name %>用户已经删除')}">删除</a>
<% }
}
);
%>
</div>
代码里可以看到用户名和邮件这两列的数据信息最终通过html描述来完成,而并不是通过硬编码的方式在代码中写死。
Grid的HtmlHelper的实现代码如下:
public class HtmlHelper
{
public static void Grid<T>(IList<T> source,string css, params Column<T>[] cols)
{
HttpResponse response = HttpContext.Current.Response;
Html32TextWriter writer = new Html32TextWriter(response.Output);
writer.WriteBeginTag("Table");
writer.WriteAttribute("class", css);
writer.Write(">");
writer.WriteBeginTag("Tr");
writer.Write(">");
foreach(Column<T> col in cols)
{
writer.WriteBeginTag("Td");
writer.WriteAttribute("Class", col.HeadCss);
writer.Write(">");
if (col.HeadBlock == null)
{
writer.Write(col.Caption);
}
else
{
writer.Write("");
col.HeadBlock(col);
}
writer.WriteEndTag("Td");
}
writer.WriteEndTag("Tr");
ItemArgs<T> e;
int index = 0;
foreach (T item in source)
{
writer.WriteBeginTag("Tr");
writer.Write(">");
foreach (Column<T> col in cols)
{
writer.WriteBeginTag("Td");
writer.WriteAttribute("Class", col.ItemCss);
writer.Write(">");
if (col.ItemBlock == null)
{
writer.Write(col.Value(item));
}
else
{
writer.Write("");
e = new ItemArgs<T>(item, index,col);
col.ItemBlock(e);
}
writer.WriteEndTag("Td");
}
writer.WriteEndTag("Tr");
index++;
}
writer.WriteEndTag("Table");
}
}
public class Column<T>
{
public Column(string caption, string itemfield)
{
Caption = caption;
ItemField = itemfield;
}
public Column(string caption, string itemfield,int width)
{
Caption = caption;
ItemField = itemfield;
Width = width;
}
public Column(string caption, string itemfield,
Action<Column<T>> head,
Action<ItemArgs<T>> item)
{
Caption = caption;
ItemField = itemfield;
HeadBlock = head;
ItemBlock = item;
}
public Column(string caption, string itemfield,int width,
Action<Column<T>> head,
Action<ItemArgs<T>> item)
{
Caption = caption;
ItemField = itemfield;
HeadBlock = head;
ItemBlock = item;
Width = width;
}
private int mWidth;
public int Width
{
get
{
return mWidth;
}
set
{
mWidth = value;
}
}
private string mCaption;
public string Caption
{
get
{
return mCaption;
}
set
{
mCaption = value;
}
}
private string mItemField;
public string ItemField
{
get
{
return mItemField;
}
set
{
mItemField = value;
}
}
private string mHeadCss="GridHead";
public string HeadCss
{
get
{
return mHeadCss;
}
set
{
mHeadCss = value;
}
}
private string mItemCss="GridItem";
public string ItemCss
{
get
{
return mItemCss;
}
set
{
mItemCss = value;
}
}
private Action<ItemArgs<T>> mItemBlock;
public Action<ItemArgs<T>> ItemBlock
{
get
{
return mItemBlock;
}
set
{
mItemBlock = value;
}
}
private Action<Column<T>> mHeadBlock;
public Action<Column<T>> HeadBlock
{
get
{
return mHeadBlock;
}
set
{
mHeadBlock = value;
}
}
protected PropertyInfo mProperty;
public object Value(object source)
{
if (ItemField == null || ItemField == "")
return null;
if (mProperty == null)
{
mProperty = typeof(T).GetProperty(ItemField, BindingFlags.Public | BindingFlags.Instance);
}
return mProperty.GetValue(source, null);
}
}
public class ItemArgs<T> : EventArgs
{
public ItemArgs(T source,int index,Column<T> col)
{
mSource = source;
mIndex = index;
mColumn = col;
}
private T mSource;
public T Source
{
get
{
return mSource;
}
}
private int mIndex;
public int Index
{
get
{
return mIndex;
}
}
private Column<T> mColumn;
public Column<T> Column
{
get
{
return mColumn;
}
}
}