我们常常会用到GridView导出到Excel的功能,我之前也有一些文章做了介绍。
今天有人问我,如果Girdview模板列里使用了自定义控件,那导出的时候如何处理?
比如该自定义控件包含一个Dropdownlist和三个Label控件,其中用来在页面上显示数据的是其中一个Label控件,现在的问题是,如果不在PrepareControlForExport()中对该自定义控件进行处理,那么导出的Excel文件的对应Gridview中使用了自定义控件的列的内容全部相同(为Dropdownlist控件的第一个Item),但是对该自定义控件进行处理的话,不知道该如何才能正确的取出它的值(用来显示的label中的值),试图无法把自定义控件转换成Dropdowlist和Label中的任何一种,但强制转换的话运行到该语句会报错。
我们首先来看看在GridView导出到Excel和开源图表工具提到的导出工具中的开发,源文件可以在这里下载:Export GridView to Excel
在GridViewExportUtil.cs中,函数PrepareControlForExport是这样的:
/// <summary>
/// Replace any of the contained controls with literals
/// </summary>
/// <param name="control"></param>
private static void PrepareControlForExport(Control control)
{
for (int i = 0; i < control.Controls.Count; i++)
{
Control current = control.Controls[i];
if (current is LinkButton)
{
control.Controls.Remove(current);
control.Controls.AddAt(i, new LiteralControl((current as LinkButton).Text));
}
else if (current is ImageButton)
{
control.Controls.Remove(current);
control.Controls.AddAt(i, new LiteralControl((current as ImageButton).AlternateText));
}
else if (current is HyperLink)
{
control.Controls.Remove(current);
control.Controls.AddAt(i, new LiteralControl((current as HyperLink).Text));
}
else if (current is DropDownList)
{
control.Controls.Remove(current);
control.Controls.AddAt(i, new LiteralControl((current as DropDownList).SelectedItem.Text));
}
else if (current is CheckBox)
{
control.Controls.Remove(current);
control.Controls.AddAt(i, new LiteralControl((current as CheckBox).Checked ? "True" : "False"));
}
if (current.HasControls())
{
GridViewExportUtil.PrepareControlForExport(current);
}
}
}
这一段代码是遍历传入control的所有子control,对于每一个子control,根据子control的类型生成一个LiteralControl,并用这个LiteralControl代替当前的子control。对于LinkBtton,使用它的文本代替,对于ImagaButton,是使用它的Alternate文本代替。函数针对LinkButton, ImageButton, HyperLink, DropDwonList, CheckBox做了处理,如果当前控件不是这其中的任何一种,就判断是否有子控件,并递归调用。
回到我们之前的问题,如果GridView中有一个自定义的控件,那我们怎么办?其实解决的办法就按原思路来就可以,判断是不是自定义控件,使用某种方式把这个自定义控件中的某个希望导出的文本信息读取出,转换为一个Literal control就可以。
我们可以写一个函数来处理这种比较复杂的情况,示范代码如下:
else if (current is MyWebController)
{
control.Controls.Remove(current);
control.Controls.AddAt(i, GetLiteralController(current));
}
至于GetLiteralControler的写法,可以遍历自定义控件中的所有子控件,根据控件的特点,比如位置,ID选定一个控件,转换为Literal控件并返回。
本文是个随笔,记录了一下思路,没有进行实际检验,如果问题,还请大家指出,逐步充实。