日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

考察DataGrid控件 Part 7

系統 2227 0

考察DataGrid控件 Part 7 (上)

本文英文原版:
http://aspnet.4guysfromrolla.com/articles/080702-1.aspx


導言:

在編輯界面里,默認的是TextBoxes控件,不過你可以對界面進行定制使其更具靈活性。比如,假如DataGrid控件里的某個列是True/False域,我們展現一對True/False單選項要比默認的TextBoxes控件要好的多;再比如,假設一個列為某個表的外鍵(foreign key),我們提供一個DropDownList控件供用戶選擇恰當的選項或許是個更好的辦法。定制DataGrid的編輯界面需要額外的代碼,不過這些都比較簡單,我個人認為,難的是理解發生在頁面背后的運行機制原理。


用EditItemTemplate定制編輯界面

為了定制DataGrid的編輯界面,我們要用到模版列(TemplateColumn)。記得在本系列文章的Part 5部分提到過,可以向DataGrid添加模版列以自定義HTML輸出效果。如果是綁定列(BoundColumn)的話,默認的是TextBox界面。在本文,我們要用到的是一個real-world示例。在本系列的前面部分,我們看到的示例關于ASPFAQs.com上的常見問題解答。用到的是FAQ數據庫,它有一系列的數據表,其中最主要的是tblFAQ表,每一行記錄對應一條FAQ(即常見問題解答)。其中一個列FAQCategoryID,它是數據表tblFAQCategory的一個外鍵,該數據表的每一行記錄對應一個FAQ種類(這些種類包括Array, Appilcation Object, Email, ASP.NET, Forms等等) 。下面是這2個表的重要部分的定義:

考察DataGrid控件 Part 7
基于前6章的基礎知識,你應該快速而容易的創建一個DataGrid來顯示每條FAQ,包括FAQ的種類名稱(注意不是integer類型的)。下面的SQL語句可以挑選出每條FAQ的種類名稱:
SELECT FAQID, F.FAQCategoryID, Name AS CategoryName, Description
FROM tblFAQ F
INNER JOIN tblFAQCategory FC ON FC.FAQCategoryID = F.FAQCategoryID

(演示頁面為 http://aspnet.4guysfromrolla.com/demos/dgExample13.aspx )

現在假設你想讓用戶編輯DataGrid,你可能會想,“哈哈,我已經看完前6章,我知道怎么做了,首先添加一個EditCommandColumn!”不錯,這是正確的第一步,不過我們還要做更多的工作,因為默認時,綁定列呈現的編輯界面不太理想。看一下這個演示頁面

http://aspnet.4guysfromrolla.com/demos/dgExample14.aspx ),點擊某行的Edit按鈕,你會看到什么?要是你懶得點這個演示頁面的話,下面的這個圖顯示了最終效果。

考察DataGrid控件 Part 7

我們注意到在編輯模式里,列Category已經轉變成了默認的TextBox。咋一看好像沒什么問題,假設某人想把編號為2的Category由Strings變為Arrays,他只需要鍵入Arrays。然而,從各個方面考慮這并不是最優方案。首先,Category列是數據表tblFAQCategory的外鍵,雖然你可以遍歷tblFAQCategory來查找恰當的category名稱,然后用對應的FAQCategoryID值來更新處于編輯狀態的tblFAQ row,但這樣顯的有點凌亂。再者,假如用戶輸入有誤呢,比如將“Strings”輸入成“String”?你怎么辦呢?彈出一個錯誤消息嗎?假設用戶是有意的,那么要在tblFAQCategory里新添加一行記錄嗎?

明顯,理想情況是在Category列將TextBox替換成listbox,設置一些選項供用戶選擇。為此,我們需要在模版列里指定一個EditItemIndex控件,當用戶選擇一行編輯時,達到自定義HTML輸出效果的目的。前面提到過要自定義編輯界面,我們要用到模版列(TemplateColumn),而非綁定列(BoundColumn)。因此,首先我們需要將顯示category的綁定列轉換為模版列,如下面的代碼所顯(關于模版列的更多信息請參考Part 5):

<asp:datagrid id="dgPopularFAQs" runat="server" ... >
<Columns>
<asp:EditCommandColumn EditText="Edit" CancelText="Cancel"
UpdateText="OK" />

<asp:BoundColumn DataField="FAQID" ItemStyle-Width="10%"

ReadOnly="True"
ItemStyle-HorizontalAlign="Center"

HeaderText="FAQ ID" />

<asp:TemplateColumn HeaderText="Category">
<ItemTemplate>
<%# DataBinder.Eval(Container.DataItem, "CategoryName") %>
</ItemTemplate>
</asp:TemplateColumn>

<asp:BoundColumn DataField="Description" HeaderText="FAQ Question"

/>
</Columns>
</asp:datagrid>

在此,我們僅僅從數據源將CategoryName列展示出來,還沒完;當前,如果用戶點擊“Edit”按鈕的話,并不會呈現出某個category列,換句話說,他們只會看到category的text文本,而不是TextBox,DropDownList等。這是因為在編輯模式里編輯某行記錄的話,我們不使用綁定列那么就必須使用HTML。為此我們需要在TemplateColumn控件里使用EditItemTemplate(好比只顯示而不編輯數據時在ItemTemplate里用HTML呈現效果)

因此,在編輯模式里我們用DropDownList來顯示category。為此我們只需要添加DropDownList控件即可,像這樣:


<asp:TemplateColumn HeaderText="Category">
<ItemTemplate>
<%# DataBinder.Eval(Container.DataItem, "CategoryName") %>
</ItemTemplate>

<EditItemTemplate>
<asp:DropDownList runat="server" id="lstCategories"
DataValueField="FAQCategoryID"
DataTextField="Name"
DataSource="???" />
</EditItemTemplate>
</asp:TemplateColumn>

既然我們希望DropDownList顯示現有的FAQ種類,我們需要將DropDownList綁定到一個數據源。當對DropDownList進行綁定時我們需要指定DropDownList顯示的文字和對應的傳遞值。既然DropDownList顯示的每一項對應表tblFAQCategory里的一行記錄,比較妥當的做法是DropDownList將種類的名稱(即Name列)顯示出來,而傳遞的值是AQCategoryID,因為在表tblFAQCategory里一個AQCategoryID對應一個Name,而AQCategoryID是主鍵值(如果你對此完全被搞糊涂了,我建議你參考這篇文章:Creating Databound DropDown Lists in ASP.NET http://www.4guysfromrolla.com/webtech/071101-1.shtml )。這就是我在上文提到DataValueField和DataTextFields的原因。

當然,我們應該明白這樣道理:當你指定DropDownList綁定哪些列時,實際上你已經指定了數據源。從本質上來說,我們需要用表tblFAQCategory的行記錄來構建一個數據集(DataSet),在深入研究以前,我們先考察一下當編輯DataGrid里的數據時,在后臺到底發生了什么呢?


考察DataGrid控件 Part 7 (中)

本文英文原版:
http://aspnet.4guysfromrolla.com/articles/080702-1.2.aspx


DataGrid的幕后機制

調用DataGrid的DataBind()方法時,它枚舉數據源的內容。對數據源里的每一項(item),相應的添加一個DataGridItem實例。每個DataGridItem都有一個ItemType屬性,要么被標明為Item、或者AlternatingItem,又或者EditItem(當然還有其它ItemType類型,不過對本例而言,我們只關注這3種)。添加的第一個(以及所有為奇數)的DataGridItem被標明為一個ItemType of Item(也就是Item、AlternatingItem或EditItem);而添加的第二個(以及所有為偶數)的DataGridItem被標明為AlternateItem。

一旦指定DataGridItem的ItemType屬性后,便可以運用相應的用戶界面屬性。打個比方,如果指定ItemType屬性為Item,那么我們就可以使用Item對應的ItemStyle屬性了。我們知道,DataGrid用Table類(Table class)來控制顯示界面(自然地,DataGrid呈現為一個HTML表格);此外DataGridItem源自于TableRow class類,那就意味著DataGridItem對象將呈現為一個HTML表格行(TABLE row).

記得DataGrid class類有一個EditItemIndex屬性,我們對DataGrid進行編輯時就要用到這個屬性。比如,在DataGrid的OnEditCommand事件處理器里,我們要做的是將DataGrid的EditItemIndex設置為點擊了"Edit"按鈕的那一行的index值。 當枚舉數據源時,如果當前行與EditItemIndex相匹配,那么就將該DataGridItem行標記為EditItem,進行編輯。編輯時,如果某列為綁定列(BoundColumn),該列就呈現為默認的TextBox,該TextBox的Text屬性的值就是用戶編輯輸入的值;如果某列為模版列(TempalteColumn),那么就呈現為它的EditItemTemplate(如果設置為available的話)。

綜上,當調用DataGrid的DataBind()方法時,將對數據源進行枚舉,數據將一行一行的添加到DataGrid(DataGrid從本質來說就是一個HTML表格)。有一點很重要,對添加到DataGrid的每一行("row")來說,可以對其使用任何的數據綁定語法,就本章而言,我們就在模版列的ItemTemplate里使用了數據綁定語法(the <%# ... %>)。此外,行里的任何控件也有自己的DataBind()方法。


言歸正傳,對放置在EditItemTemplate標簽里的DropDownList控件來說,當調用DataGrid的DataBind()方法時,“處于編輯狀態的”DropDownList的DataBind()也會被調用。基于前面的知識,可以推斷出我們應該將DropDownList的數據源設置為某個數據集(DataSet)并自動調用其DataBind()方法。問題是怎樣設置DropDownList的數據源(DataSource)屬性呢?答案是使用數據綁定語法!

指定DropDownList的DataSource屬性

我們使用我們熟悉的數據綁定語句來指定DropDownList的DataSource屬性,具體來說,我們用表tblFAQCategory來填充一個數據集,再用一個函數將該數據集返回,像下面這樣:

<asp:TemplateColumn HeaderText="Category">
<ItemTemplate>
<%# DataBinder.Eval(Container.DataItem, "CategoryName") %>
</ItemTemplate>

<EditItemTemplate>
<asp:DropDownList runat="server" id="lstCategories"
DataValueField="FAQCategoryID"
DataTextField="Name"
DataSource="<%# GetCategories() %>" />
</EditItemTemplate>
</asp:TemplateColumn>

函數GetCategories()僅僅返回一個由表tblFAQCategory的行進行填充的數據集。這個函數很簡單,像下面這樣:

<% @Import Namespace="System.Data" %>
<% @Import Namespace="System.Data.SqlClient" %>
<script language="vb" runat="server">
'Create a connection
Dim myConnection as New SqlConnection(connString)
Dim ddlDataSet as DataSet = New DataSet()

Function GetCategories() as DataSet
'Populate the ddlDataSet
Const strSQLDDL as String = _
"SELECT FAQCategoryID, Name FROM tblFAQCategory ORDER BY Name"

Dim myDataAdapter as SqlDataAdapter = New _
SqlDataAdapter(strSQLDDL, myConnection)

myDataAdapter.Fill(ddlDataSet, "Categories")

Return ddlDataSet
End Function

...
演示頁面為: http://aspnet.4guysfromrolla.com/demos/dgExample15.aspx

注意,數據庫連接(connection)和數據集ddlDataSet都是在頁面上定義的,這意味著ASP.NET Web 頁面上的任何一個函數都可以訪問這2個對象。對數據庫連接對象進行完整(globally)定義的原因是我們要用到2個獲取數據庫信心的函數—GetCategories() 和 BindData()。相比起來,與其為這2個函數分別創建creating, opening和closing的分段連接對象,我們還不如直接使用完整的數據庫連接對象。請注意,該連接對象在達到目的時(也就是當頁面完全顯示出來后)自動關閉。

GetCategories()函數簡單易懂,只是用表tblFAQCategory的查詢結果來填充數據集ddlDataSet,再將填充好了的數據集返回。在演示頁面里當點擊"Edit"按鈕時,DropDownList控件確實被綁定了,再仔細看看,那發現了什么問題?

對了,當點擊某行的"Edit"按鈕時,DropDownList顯示的是數據集里第一行的類類名,而非其本來的類名。比如,第一個FAQ的類名是"Strings",當你點擊第一行的"Edit"按鈕后,顯示的卻是"Application Object"。還好,要修補這個小問題我們只需要使用一些數據綁定語法和代碼,我們在最后一部分再討論。

考察DataGrid控件 Part 7 (下)
本文英文原版
http://aspnet.4guysfromrolla.com/articles/080702-1.3.aspx

確保DropDownList恰當的Selected Item

在編輯模式里,為確保DropDownList有恰當的Selected Item,我們需要編程設置DropDownList的SelectedIndex屬性。為此,我們需要使用數據綁定語法,具體的說,我們要調用一個函數,將所選擇的FAQ的FAQCategoryID值傳給它,代碼如下:

<asp:TemplateColumn HeaderText="Category">
<ItemTemplate>
<%# DataBinder.Eval(Container.DataItem, "CategoryName") %>
</ItemTemplate>

<EditItemTemplate>
<asp:DropDownList runat="server" id="lstCategories"
DataValueField="FAQCategoryID"
DataTextField="Name"
DataSource="<%# GetCategories() %>"
SelectedIndex='<%# GetSelIndex(Container.DataItem("FAQCategoryID")) %>'
/>
</EditItemTemplate>
</asp:TemplateColumn>

函數GetSelIndex()接收的是編輯行的FAQCategoryID值(那就是為什么我們要在DataGrid里包含FAQCategoryID列,雖然并不在DataGrid里將該列顯示出來)。記得DropDownLis控件的SelectedIndex屬性是一個integer類型的值,且大小介于0和它包含的項的總數(number of items)之間。比方,我們想將選擇第五項,我們只需要將SelectedIndex屬性設置為4(因為第一項的index值為0)

所以,函數GetSelIndex()返回一個integer類型的值,它對應DropDownList的所選項。我們知道數據集ddlDataSet用來填充(populate)控件DropDownList,同時數據集ddlDataSet每行的index與DropDownList的每項的index一一對應。所以,函數GetSelIndex()遍歷數據集,將每行與傳入的FAQCategoryID值相比較。一旦匹配的話,函數就返回該行的index,然后對DropDownList的SelectedIndex屬性賦值。聽起來有點暈,下面的代碼也許能更好的便于你理解:

Function GetSelIndex(CatID as String) as Integer
Dim iLoop as Integer

'Loop through each row in the DataSet
Dim dt as DataTable = ddlDataSet.Tables("Categories")
For iLoop = 0 to dt.Rows.Count - 1
If Int32.Parse(CatID) = _
Int32.Parse(dt.Rows(iLoop)("FAQCategoryID")) then
Return iLoop
End If
Next iLoop
End Function

演示頁面為: http://aspnet.4guysfromrolla.com/demos/dgExample16.aspx


在OnUpdateCommand事件處理器里檢索DropDownList的值

當用戶編輯某行記錄時,將會顯示"Update" 和 "Cancel"按鈕供選擇(在演示頁面里,我將"Update"替換為"OK"了)。當用戶點擊"Update"按鈕時將觸發OnUpdateCommand事件。就像在Part 6探討過的一樣,為了用輸入的數據對數據庫進行更新,我們需要為OnUpdateCommand事件編寫一個事件處理器。

為了獲取用戶從DropDownList選取的值,我們使用FindControl方法來得到DropDownList控件的實例;訪問SelectedItem.Value屬性,也就是用戶在DropDownList控件里所選的條目的FAQCategoryID值。OnUpdateCommand事件處理器的代碼如下:

Sub dgPopFAQs_Update(sender As Object, e As DataGridCommandEventArgs)
'Determine what category was selected
Dim strCategoryID as String, strCategoryName as String
strCategoryID = CType(e.Item.FindControl("lstCategories"), _
DropDownList).SelectedItem.Value
strCategoryName = CType(e.Item.FindControl("lstCategories"), _
DropDownList).SelectedItem.Text

... Make a SQL call to update the database ...

'Return the DataGrid to its pre-editing state
dgPopularFAQs.EditItemIndex = -1
BindData()
End Sub

演示頁面為: http://aspnet.4guysfromrolla.com/demos/dgExample17.aspx

使用EditItemTemplate定制其它編輯界面

在本文我們考察了使用EditItemTemplate來包含一個DropDownList控件。當然,你也可以用它來為DataGrid里的其它列進行編輯界面定制。比如,你可能覺得DataGrid默認生成的TextBox 太小,你可以用EditItemTemplate來增大TextBox 的尺寸。另一個比較有實際意義的運用是,假如有一個Yes/No類型的列,你可以添加一個包含"Yes" / "No"值的DropDownList控件或干脆設置一個 單選按鈕,這比使用TextBox要好的多。

注意演示頁面,在編輯界面里我們使用的是75-column的TextBox.

結語:

本文對Part 6的內容進行了擴展,允許對DataGrid的編輯界面進行用戶定制。我們首先探討了如何來模版列里用EditItemTemplate對某個列進行編輯界面定制。然后,考察了如何將表tblFAQCategory的內容綁定到DropDownList,以及自動的選擇恰當的條目(item)。最后,我們學習了如何讀取用戶從DropDownList選取的值;這一步很重要,它關系到用用戶期望的值對數據庫進行更新。

謹記,用EditItemTemplate對編輯界面進行用戶定制的潛力是無窮的,只是看你的能力而已!

祝編程快樂!

考察DataGrid控件 Part 7


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 成武县| 资溪县| 密云县| 南和县| 凤城市| 龙岩市| 临安市| 巫溪县| 梅州市| 枞阳县| 津南区| 车险| 赤壁市| 鄂托克前旗| 清河县| 苍山县| 五家渠市| 永仁县| 梁山县| 开原市| 淮阳县| 宝兴县| 东阳市| 洪雅县| 澄城县| 密云县| 肃南| 上饶市| 舒城县| 舟山市| 通州市| 淮安市| 抚远县| 讷河市| 东宁县| 长顺县| 禹城市| 辛集市| 双流县| 阿拉善盟| 白沙|