分享:DataGrid,动态模板列,ITemplate
终于解决了一个问题,写出来大家分享。
在使用DataGrid捕获数据时很可能会遇到这样一种情况:数据列是根据数据库记录变化的,为了解决这个问题必须使DataGrid的列是根据数据库中的记录动态创建。有两个方法可以解决:
一是将数据读到DataTable中,由DataGrid根据DataTable自动创建列,并使用按钮列来使行进入编辑状态。这是一个简单的办法。但是有一个问题:数据输入比较麻烦,用户要点击edit按钮,才能使一行进入编辑状态(出现文本框)输入数据,并且由于每次进入编辑状态实际上都要postback回服务器端,效率也不好。
因此在这种情况下,一般希望使用模板列来实现。因此第二各方法就是动态构造模板列。
动态构造模板列首先要实现Itemplate接口,一个只使用文本框作为模板的实现可以如下:
public class CTemplateCol:ITemplate
{
private string colname;
TextBox l;
public CTemplateCol(string cname)
{
colname=cname;
}
//must implement following method
public void InstantiateIn(Control container)
{
l = new TextBox();
l.ID=colname;
l.CssClass="boxs";
l.Width=60;
l.DataBinding +=
new EventHandler(this.OnDataBinding);
container.Controls.Add(l);
}
public void OnDataBinding(object sender, EventArgs e)
{
TextBox l = (TextBox) sender;
DataGridItem container =
(DataGridItem) l.NamingContainer;
l.Text =
((DataRowView)
container.DataItem)[colname].ToString();
}
}
在我的项目里,单击button1,会根据用户选择的日期和报表动态构造一个DataGrid相关代码如下:
foreach(String typename in typesList)
{
dtb.Columns.Add(typename);
TemplateColumn tc1=new TemplateColumn();
tc1.ItemTemplate=new CTemplateCol(typename);
tc1.HeaderText=typename;
DataGrid1.Columns.Add(tc1);
}
然后只要绑定好datasource调用databind就可以完成显示了。
用户在页面上输入了数据后单击button2,就会将数据传回来。开始困扰我的地方在于在button2的事件里面检测datagrid是检测不到动态创建的模板列的,只有几个固定的列存在。后来我查到应该在页面回传时再次创建动态模板列,而且必须在page_load事件中完成这个工作,于是我在page_load事件中加入了以下代码:
String sourcectrl=Request.Form["Button2"];
if(sourcectrl=="提交数据")
{
DataTable dtb=(DataTable)ViewState["UpdateTable"];//以前的数据
ArrayList types=(ArrayList)ViewState["TypeList"];//列名
if((dtb!=null)&&(types!=null))
{
foreach(String typename in types)
{
TemplateColumn tc1=new TemplateColumn();
tc1.ItemTemplate=new CTemplateCol(typename); tc1.HeaderText=typename;
DataGrid1.Columns.Add(tc1);
}
DataGrid1.DataSource=dtb;
DataGrid1.DataBind();
}
}
保证在button2点击后造成的postback中重新构造动态模板列,有趣的是使用了以前存入viewstate的datatable的数据来初始化DataGrid的数据源并绑定了数据,表面看来这回覆盖掉用户在网页上输入的数据,但实际上这是正确的选择,否则反而得不到用户输入的数据。
而在button2的click事件中则可以接收用户输入:
int i=-1;
foreach (DataGridItem dgi in DataGrid1.Items)
{
i++;
TextBox t;
foreach(String typename in types)
{
t=null;
for(int j=0;j<dgi.Cells.Count;j++)
{
t=(TextBox)dgi.Cells[j].FindControl(typename);
if(t!=null)break;
}
if(t!=null)
{
try
{
if(t.Text!="")dtb.Rows[i][typename]=Convert.ToDouble(t.Text);
}
catch(Exception)
{
Label2.Text="数据输入错误!";
Label2.Visible=true;
return;
}
}
}
用户输入的新的数据就保存到datatable中了;
以上就是整个处理过程,与大家分享,如果大家有更好的方法,请一起讨论