DataGrid 動態列

來源:互聯網
上載者:User
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控制項.



相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。