DataGrid 动态列

datagrid|动态

模版控件能让用户几乎不用花费任何时间就创建出复杂的用户界面. Asp.net有很多控件都使用了模版技术(DataGrid就是一个例子). 而这些控件都工作得很好, 通常, 模版可以被保存为ascx文件以增加复用性. 很有可能, 事前你是不知道你的控件是怎么布局的, 而且你需要动态的添加一些模版以应付不同的事件.

使用模版的另一个优势,就是它们能动态的添加到你的控件里面去. 这样的话, 你可以事先设计好模版, 然后通过简单的几行代码就添加到你的控件中.

下面这篇文章就要告诉你如何如何一步步的添加一个动态的ItemTemplate和EditItemTemplate到DataGrid中. 另外, 还会告诉你怎么获取和更新用户对EditItemTemplate所做的改变. 例子将会是很简单的. 然后, 我很快就会在TripleASP上面正式发布一个改进后的TableEditor版本. 这个版本将更好的说明如何使用动态模版.

ITempalte的实现
为了能动态的添加ItemTemplate和EditItemTemplate, 我们需要创建2个类来实现ITemplate的接口(Interface). 第一个类是GenericItem. 这个类的主要工作就是: 取数据源的列名, 创建一个文本控件(literal contral), 为这个文本控件赋值, 最后把这个文本控件加到父控件(在这里父控件就是DataGrid了).

到目前为止还是很顺利. 在继续下面的讨论之前, 我们来看看代码和完成的步骤.
using System;
using System.Web;
using System.Data; using System.Web.UI;
using System.Web.UI.WebControls;

namespace TripleASP.ItemTemplates
{
/// <summary>
/// Summary description for GenericItem.
/// </summary>
public class GenericItem : ITemplate
{
private string column;
//private bool validate;
public GenericItem(string column)
{
this.column = column;
}
public void InstantiateIn(Control container)
{
Literal l = new Literal();
l.DataBinding += new EventHandler(this.BindData);
container.Controls.Add(l);
}

public void BindData(object sender, EventArgs e)
{
Literal l = (Literal) sender;
DataGridItem container = (DataGridItem) l.NamingContainer;
l.Text = ((DataRowView) container.DataItem)[column].ToString();

}
}
}

正如你看到的, GenericItem类实现了ITemplate的接口(interface). 因为我们是实现接口, 所以必须包括InstantiateIn这个方法. 这个方法是用来定义所有子控件和模版所属的控件对象的. 在这个方法里面, 我们创建了一个新的Literal控件来保存DataGrid的单元值. 接着, 我们添加了DataBinding事件处理函数. 这个事件处理函数实际上就是在DataGrid绑定数据的时候, 把单元值放到Literal控件的Text属性中. 最后, 把这个Literal控件加入到控件的容器集合中. 很简单吧?

动态EditItemTemplate
动态EditItemTemplate类ValidateEditItem跟GenericItem很类似, 但是有3个地方不同.
第一个不同的地方是, 我们添加的是Textbox控件而不是Literal控件. 这样的话, 在编辑模式下, 用户可以做任何修改.
第二个不同的地方, 你会发现我们会显式地命名控件. 这会使我们能够获取更新事件中的任何数据变化.
最后一个不同, 你会看到一个跟Textbox相联系的RequiredFieldValidator控件. 这是可选的. 但是, 这的确让你知道有些事是可以这样做的.
下面就是ValidateEditItem的代码:
using System;
using System.Data;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web;

namespace TripleASP.ItemTemplates
{
/// <summary>
/// Summary description for ValidateEditItem.
/// </summary>
public class ValidateEditItem : ITemplate
{
private string column;
public ValidateEditItem(string column)
{
this.column = column;
}

public void InstantiateIn(Control container)
{
TextBox tb = new TextBox();
tb.DataBinding += new EventHandler(this.BindData);
container.Controls.Add(tb);
tb.ID = column;

RequiredFieldValidator rfv = new RequiredFieldValidator();
rfv.Text = "Please Answer";
rfv.ControlToValidate = tb.ID;
rfv.Display = ValidatorDisplay.Dynamic;
rfv.ID = "validate" + tb.ID;
container.Controls.Add(rfv);

}

public void BindData(object sender, EventArgs e)
{
TextBox tb = (TextBox) sender;
DataGridItem container = (DataGridItem)tb.NamingContainer;
tb.Text = ((DataRowView) container.DataItem)[column].ToString();
}
}
}

动态模版的实现
现在我们已经有两个实现了ITempalte接口的类了. 一切准备好了! 我们现在要做的就是把它们加入到我们的datagrid里面.

我们把BindData和DynamicColumns两个方法放在一起. BindData主要是创建SQL查询语句, 往datagrid添加列(动态列), 然后把数据表绑定到datagrid.

void BindData()
{
string sql = "Select * from publishers Where State Is not null";
DataGrid1.Columns.Add(DynamicColumns("pub_id",false));
DataGrid1.Columns.Add(DynamicColumns("pub_name",true));
DataGrid1.Columns.Add(DynamicColumns("city",true));
DataGrid1.Columns.Add(DynamicColumns("state",true));
DataGrid1.Columns.Add(DynamicColumns("country",true));
DataGrid1.DataKeyField = "pub_id";
DataGrid1.DataSource = GetDataTable(sql);
DataGrid1.DataBind();
}

DynamicColumns有两个参数: column(字符类型)和isEditable(布尔类型). column变量当然就是我们要加入TemplateColumn的列名. isEditable变量是用作测试的, 如果我们希望这个列是允许编辑的话.
protected TemplateColumn DynamicColumns(string column, bool isEditable)
{
TemplateColumn genericcolumn = new TemplateColumn();
genericcolumn.HeaderText = column;
genericcolumn.ItemTemplate = new GenericItem(column);
if(isEditable)
{
genericcolumn.EditItemTemplate = new ValidateEditItem(column);
}
return genericcolumn;
}

正如你所看到的, 首先我们实例化一个TemplateColumn(genericcolumn), 根据我们要添加的列的名字设置HeaderText属性(当然,你可以设置为任何东西都可以). 接着, 我们通过添加新的GenericItem的参考(reference), 把ItemTemplate添加到genericcolumn, 并把名称传入. 最后, 我们必须检查isEditable, 以便看看我们需不需要允许编辑这个列. 如果为真, 我们要往ValidateEditItem添加新的参考, 而且把列名也传过去.

DataGrid事件
我们的编辑和取消事件是很标准的. 你有可能已经看过它们100遍了. 在我们的编辑事件里面, 我们简单地取出被选中的行的编号, 然后重新绑定数据.

protected void Edit_Click(Object sender, DataGridCommandEventArgs e)
{
DataGrid1.EditItemIndex = e.Item.ItemIndex;
BindData();
}
我们的取消事件是把当前所选行号设为-1. 这样就等于告诉datagrid, 不在是编辑模式了. 然后, 我们重新绑定数据.
protected void Cancel_Click(Object sender, DataGridCommandEventArgs e)
{
DataGrid1.EditItemIndex = -1;
BindData();
}
更新事件会跟你以前看到的有一点点不同. 然而, 它却会让你想起你在ASP的日子.
protected void Update_Click(Object sender, DataGridCommandEventArgs e)
{
//Gets the UniqueID that is attached to the front of each textbox
//dyamically added to our datagrid's EditItemTempate
string uid = e.Item.UniqueID + ":";

string pub_id = (string)DataGrid1.DataKeys[e.Item.ItemIndex];
string pub_name = (Request.Form[uid + "pub_name"].ToString());
string city = (Request.Form[uid + "city"].ToString());
string state = (Request.Form[uid + "state"].ToString());
string country = (Request.Form[uid + "country"].ToString());

//Simple method to update DB
UpdateRecord(pub_id,pub_name,city,state,country);
DataGrid1.EditItemIndex = -1;
BindData();
}

这样的话, EditItemTemplate就硬编码到页面中去了. 你可能已经看过一些取表单提交数据的例子, 其中的方法, 或者是通过控件位置取值, 或者是控件名称取值. 但是, 如果你是在运行时创建控件, 那么, 在PostBack的时候, ASP.NET是无法取得这些值的. 为此, 我们只能通过Request.Form的方法来得到这些值.

在你开始在ValidateEditItem类里面仔细寻找被小心命名的textbox的时候, 你必须记住, ASP.NET已经为控件的名字冲突做了预防措施. 一般来说, 这包括增加每个datagrid父控件的名称, datagrid本身的名称, 和一个代表每个textbox的序号的字符串放在textbox的ID前面. 我们可以大量的使用这样的方法. 但是这并不保证我们的代码绝对的模块化和可复用. 相反, 我们检查DataGridCommandEventArgs.Item.UniqueID 并在尾部加上":". 有了这个UniqueID, 我们就可以安全地取得textbox里面的编辑数据, 并更新到数据库.

结论
动态添加模版到你的模版控件会在开始的时候增加一点点的工作量. 但是, 一旦你建立了一系列的优秀的模版类, 你会发现, 实现ITemplate会非常的快速和容易. 它运行你建立强大的控件来满足你数据操作的需要. 如果你需要更好的例子, 请看我即将发布在TripleASP的TableEditor控件.

时间: 2024-10-27 04:30:26

DataGrid 动态列的相关文章

asp.net-datagrid 动态列如何绑定 支付现金

问题描述 datagrid 动态列如何绑定 支付现金 写了一个SQL语句,列是动态增加的,行数按记录数走,如何在asp.net 页面绑定,给予技术支持,本人联系电话15513712555,语言vb.net 价格电话协商,需提供完整代码实现本功能.

DataGrid动态添加模板列的一个例子

datagrid|动态|模板 数据源结构同http://blog.csdn.net/lovecherry/archive/2005/03/24/328455.aspx表dep:depid(标识主键),depname(学院名字)表stu:stuid(标识主键),stuname(学生名字),studepid(学院id=表dep.depid) 前台:<%@ Page language="c#" Codebehind="WebForm30.aspx.cs" AutoE

动态的管理ASP.NET DataGrid数据列

asp.net|datagrid|动态|数据 在ASP.NET的DataGrid数据显示控件编程中,我们有几种方式可以增加DataGrid columns.其中最常见的方法是在web forms设计器中增加,通过在控件工具箱中拖访DataGrid控件到web设计页面,然后在属性生成器中增加Columns列;还有一种方式就是在HTML视图模式下更改HTML代码的方式增加Columns列.但是这两种方式都是在设计时进行的,一旦设计完成就无法更改.其实我们也可以在程序运行时动态的增加或者删除Colum

嵌套的DataGrid如何为子DataGrid动态增加模板列

datagrid|动态|模板 例子比较简单,直接贴代码了,例子达到以下功能: (1)两个DataGrid嵌套 (2)外面一个DataGrid分页 (3)里面一个DataGrid动态增加模板列  <%@ Page language="c#" Codebehind="WebForm45.aspx.cs" AutoEventWireup="false" Inherits="csdn2.WebForm45" %> <

java-怎样在easyui中的datagrid的列中添加combobox并动态获取数据到combobox中?

问题描述 怎样在easyui中的datagrid的列中添加combobox并动态获取数据到combobox中? <table id="data" class="easyui-datagrid" style="width:700px;height:250px" url="getAllServer.do" data-options="pageSize:5 ,pageList: [3,5,10]" tool

DataGrid 动态添加模板列 实现代码_实用技巧

使用模版的另一个优势,就是它们能动态的添加到你的控件里面去. 这样的话, 你可以事先设计好模版, 然后通过简单的几行代码就添加到你的控件中. 下面这篇文章就要告诉你如何如何一步步的添加一个动态的ItemTemplate和EditItemTemplate到DataGrid中. 另外, 还会告诉你怎么获取和更新用户对EditItemTemplate所做的改变. 例子将会是很简单的. 然后, 我很快就会在TripleASP上面正式发布一个改进后的TableEditor版本. 这个版本将更好的说明如何使

DataGrid动态添加列问题

问题描述 最近用到DataGrid动态添加按钮列,但在自带分页时,大于1的页面点按钮实现功能后都跳转到第一页,这怎么解决? 解决方案 解决方案二:在按钮事件前记录DataGrid的CurrentPageIndex,事件后恢复应该可以

easyui动态列实现列数据格式化问题

问题描述 easyui动态列实现列数据格式化问题 最近遇到一个问题:做一个easyui表格的动态列,我在数据库里定义了一个easyui的列的formatter,因为formatter后面是一个方法,所以我存储成为String类型,但是从数据库读取后返回到页面上,js转为字符串,就报错, 正确的应该是formatter:function(){},现在我传回去成这样了formatter:'function(){}',多出来一个引号 解决方案 [EasyUi DataGrid]动态加载列easyui

jQuery Easyui学习之datagrid 动态添加、移除editor_jquery

 使用easyui行编辑的时候完成编辑的功能比较简单,但是如果要根据一个框的值动态改变别的值或者编辑的时候禁用某个框的时候就比较麻烦了. 比如像下面这样:添加行的时候每个值都是手动输入,修改的时候第一个值不能修改.我们来看下怎么实现这样的效果. easyui本身是不提供这么细节的功能的,需要我们自己拓展下: 在编辑的时候移除第一列的editor属性,添加的时候,添加第一列的属性. //扩展datagrid:动态添加删除editor $.extend($.fn.datagrid.methods,