动态添加DataGrid模板列(英)

Implementing Dynamic ItemTemplates
By:
Scott Watermasysk
Published: 4/10/2002
Printer Friendly
Download

Template controls allow a developer to set up a complicated user interface in almost no time at all. ASP.Net has a couple of controls that use templates (the Datagrid is a prime example). While this works great, and often used templates can be saved as .ascx files to enhance reusability, there will likely be times where the layout of your control isn't known a head of time and you need to dynamically add a template based on different events.

One of the other great advantages to using templates, is they can be added to your controls dynamically. This way, you can design very detailed templates and add them to any of your templated controls with just a couple of lines of code.

The following article is going to walk you through the steps of adding a dynamic ItemTemplate and EditItemTemplate to a datagrid. In addition, it is going to show you how to retrieve and update any changes made by the user in the EditItemTemplate. This example will be fairly simple. However, I will soon be releasing a much-improved version of the TripleASP TableEditor, which will serve as a better example of what can be accomplished using dynamic templates.

Implementing ITemplate

In order for us to dynamically add our ItemTemplate and EditItemTemplate we are going to have to create two classes that implement the ITemplate interface. The first of these classes, GenericItem, simply takes the name of our data source's column, creates a literal control, adds the data source value to the literal control, and then adds the literal control to the parent control, which in this case, is our datagrid.

This was a very quick run down. Before we continue, lets take a quick look at the code, and see the steps it took to get this action completed.
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();
    
        }
    }
}
As you can see our GenericItem class implements the ITemplate interface. Because we are implementing the ITemplate interface in this class, we must include the method, InstantiateIn, which defines the Control object that child controls and templates belong to. In the InstantiateIn method, we are creating a new Literal control, which will hold the individual datagrid cell value. Next, we wire up a DataBinding event, which will actually add the cells value to the Text property of our Literal control when the parent datagrid's DataBind method is called. Finally, we add the Literal control to the control collection of our container control. Pretty Simple!

Dynamic EditItemTemplate

The dynamic EditItemTemplate class, ValidateEditItem, is the same as the GenericItem class with three key exceptions.
  1. The first difference you will notice is that we are now adding a textbox to the control collection instead of a literal control. This way, during edit mode, a user can make any applicable changes.
  2. The second major difference you will notice is that we took the time to explicitly name (through the ID property) our control. This will help us retrieve any data changes made during the update event.
  3. The third and final difference you will see is that we added a RequiredFieldValidator and connected it to our textbox. This is of course optional, but it does begin to show you how handy something like this could be.
Here is our ValidateEditItem class:
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();
        }
    }
}

Implementing the Dynamic Template

We now have our two classes that implement the ITemplate interface built and ready to go. All that we have to do now is add them to our datagrid.

We will quickly put together two methods, BindData and DynamicColumns. BindData will create our SQL querystring, add each of our datagrid's columns (using DynamicColumns), and then bind our datatable to the 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();
}
The DynamicColumns method has two parameters: column (a string) and isEditable (a bool). The column variable will of course be the name of the column we wish to add to our TemplateColumn and the isEditable variable will be used to test, if we wish, to allow this column to be edited within our datagrid. INSERT DYNAMICCOLUMNS
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;
}
As you can see, we will first instantiate a new TemplateColumn, genericcolumn, set its HeaderText property to the name of the column we are about to add (You can of course set this to anything you like, but to keep it simple, we chose to set it to the column name). Next we add the ItemTemplate to the genericcolumn by adding a new reference to our GenericItem class and passing it the name of our column. Finally we check our isEditable bool to see if we would like to allow editing on this column. If true, we add a new reference to our ValidateEditItem and again pass along the name of the column we are adding to the datagrid.

The DataGrid Events

Our edit and cancel events are very standard and you have likely seen them 100's of times. In our edit event we simply retrieve the index number of the row selected to be edited, and then rebind our data.
protected void Edit_Click(Object sender, DataGridCommandEventArgs e)
{
    DataGrid1.EditItemIndex = e.Item.ItemIndex;
    BindData();
}
Our cancel event simply sets the currently selected row to -1, which tells our datagrid that we are no longer in edit mode, and then again, rebind our data.
protected void Cancel_Click(Object sender, DataGridCommandEventArgs e)
{
    DataGrid1.EditItemIndex = -1;
    BindData();
}
The update event will be a little different from most of the other examples you have seen on updating data in a datagrid. However, it will definitely remind you of your days in classic 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();
}
In situations where the EditItemTemplate is hard coded into the page, you would have likely seen examples of retrieving the posted back data by either referencing the controls location (DataGridCommandEventArgs.Item.Cells[]Controls[]) or by finding the control by name (DataGridCommandEventArgs.Item.FindControl). However, if you create controls at runtime then ASP.NET can't create them for you when you do a postback. Thus, in order to retrieve our updated values, we need to take a step back into the past and use the Request.Forms collection.

Before you jump in and start trying to find the textboxes we so carefully named in our ValidateEditItem class, you have to remember that ASP.Net takes a precautionary step to make sure the names of our controls do not clash with one another. In general, this involves adding the name of each of our datagrid's parent controls, the name of our datagrid itself, and a string representing the control index of each textbox to the beginning of each textboxes' ID property. We could hard code a large part of this, but it would not allow our code to be as modular and reusable as possible. Instead, we check the DataGridCommandEventArgs.Item.UniqueID property and add an extra ":" to the end of it. Armed with the UniqueID we can safely retrieve the values we changed in our textboxes during edit mode, and update our database.

Conclusion

Dynamically adding Templates to your templated controls takes a little more work to set up the first time. But once you have built a couple of good template classes, you will find that implementing the ITemplate interface can be done quickly and easily. Which will allow you building powerful controls to handle a great deal of your routine data needs. For a better example of this, please watch out for the upcoming release of the TripleASP TableEditor control.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
未来社区的建设背景和需求分析指出,随着智能经济、大数据、人工智能、物联网、区块链、云计算等技术的发展,社区服务正朝着数字化、智能化转型。社区服务渠道由分散向统一融合转变,服务内容由通用庞杂向个性化、服务导向转变。未来社区将构建数字化生态,实现数据在线、组织在线、服务在线、产品智能和决策智能,赋能企业创新,同时注重人才培养和科研平台建设。 规划设计方面,未来社区将基于居民需求,打造以服务为中心的社区管理模式。通过统一的服务平台和应用,实现服务内容的整合和优化,提供灵活多样的服务方式,如推送式、订阅式、热点式等。社区将构建数据与应用的良性循环,提高服务效率,同时注重生态优美、绿色低碳、社会和谐,以实现幸福民生和产业发展。 建设运营上,未来社区强调科学规划、以人为本,创新引领、重点突破,统筹推进、整体提升。通过实施院落+社团自治工程,转变政府职能,深化社区自治法制化、信息化,解决社区治理中的重点问题。目标是培养有活力的社会组织,提高社区居民参与度和满意度,实现社区治理服务的制度机制创新。 未来社区的数字化解决方案包括信息发布系统、服务系统和管理系统。信息发布系统涵盖公共服务类和社会化服务类信息,提供政策宣传、家政服务、健康医疗咨询等功能。服务系统功能需求包括办事指南、公共服务、社区工作参与互动等,旨在提高社区服务能力。管理系统功能需求则涉及院落管理、社团管理、社工队伍管理等,以实现社区治理的现代化。 最后,未来社区建设注重整合政府、社会组织、企业等多方资源,以提高社区服务的效率和质量。通过建立社区管理服务综合信息平台,提供社区公共服务、社区社会组织管理服务和社区便民服务,实现管理精简、高效、透明,服务快速、便捷。同时,通过培育和发展社区协会、社团等组织,激发社会化组织活力,为居民提供综合性的咨询和服务,促进社区的和谐发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值