Trong bài viết này, tôi sẽ chứng minh làm thế nào liên kết danh sách thả xuống điều khiển GridView trong chế độ chỉnh sửa. Nếu bạn là người mới sử dụng GridView, tôi muốn giới thiệu bạn hướng dẫn sau:
Tổng quan:
Tôi đang sử dụng nguồn dữ liệu Adventure Works. Khi trang web được tải, ta lấy sản phẩm từ Production. Bảng Product và bind chúng vào GridView. Chúng ta hiển thị một số sản phẩm thuộc tính như Product ID, Product Number, Product Name, Product Subcategory Name và List Price. Khi người dùng nhấp vào chỉnh sửa, GridView vào chế độ chỉnh sửa. Chúng ta đánh dấu Product Name, Product Sub Category và List price có thể chỉnh sửa trong thiết kế. Trong trường hợp Product Sub Category, chúng ta nạp danh sách của tất cả các loại sản phẩm có sẵn trong bảng Production. Bảng ProductionSubcategory vào danh sách thả xuống(DropDownList) và có sẵn cho người dùng lựa chọn.
Kết nối Cơ sở dữ liệu.
Tạo project ứng dụng ASP.NET Web mới. Mở web.config và thêm mục sau đây để kết nối chuỗi.
<add name="Sql" connectionString="Data Source=(local);
Initial Catalog=AdventureWorks;User=testuser;Password=testuser;"
providerName="System.Data.SqlClient"/>
Page Design
Tạo ra trang web ASP.NET mới. Đổi tên default.aspx thành EditProductsView.aspx và cập nhật bất kỳ tham chiếu. Chỉ cần áp dụng một số định dạng cơ bản. Như bạn có thể thấy chúng ta đang khai thác vào bốn sự kiện của GridView để đáp ứng yêu cầu này. Tôi sẽ thảo luận về những sự kiện đó sau.
<asp:gridview id="gvProducts"
autogeneratecolumns="False"
BorderColor="White" BorderStyle="Ridge"
CellSpacing="1" CellPadding="3" GridLines="None"
BackColor="White" BorderWidth="2px"
emptydatatext="No data available."
runat="server" DataKeyNames="ProductID"
OnRowEditing="gvProducts_RowEditing"
OnRowCancelingEdit="gvProducts_RowCancelingEdit"
onrowupdating="gvProducts_RowUpdating"
onrowdatabound="gvProducts_RowDataBound">
Chúng ta sẽ không cho phép người dùng chỉnh sửa ProductID và Product Number, vì vậy sử dụng BoundColumns để hiển thị chúng.
<Columns>
<asp:BoundField DataField="ProductID" HeaderText="Product ID"
ReadOnly="true">
</asp:BoundField>
<asp:BoundField DataField="ProductNumber" HeaderText="Product Number"
ReadOnly="true">
</asp:BoundField>
……………
…………..
Người dùng được phép cập nhật Product Name, Product Number, Price và sub category. GridView trong chế độ xem, chúng ta wrap những thuộc tính này trong ITEM TEMPLATE. Khi GridView sử dụng ở chế độ chỉnh sửa, người sử dụng thực sự có thể thay đổi tên sản phẩm và giá cả của nó, vì vậy chúng ta làm cho hai mặt hàng trong trường Text. Tuy nhiên, ông không thể thay đổi sub category name, ta chỉ có thể chọn sub category từ danh sách có nghĩa là hiện tại ta có thể thay đổi map.
….
……………….
<asp:TemplateField headertext="Product Name">
<HeaderStyle HorizontalAlign="Left" Width="200px" />
<ItemStyle HorizontalAlign="Left" Width="200px"/>
<ItemTemplate> <%#Eval("ProductName")%></ItemTemplate>
<EditItemTemplate>
<asp:TextBox id="txtProductName" text='<%#Eval("ProductName")%>'
runat="server"/>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField headertext="Sub Category">
<HeaderStyle HorizontalAlign="Left" Width="150px" />
<ItemStyle HorizontalAlign="Left" />
<ItemTemplate> <%#Eval("SubCategoryName")%></ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ddlSubCategories" runat="server" >
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField headertext="Price">
<HeaderStyle HorizontalAlign="Right" Width="80" />
<ItemStyle HorizontalAlign="Right" Width="80" />
<ItemTemplate> <%#Eval("ListPrice","{0:c}")%></ItemTemplate>
<EditItemTemplate>
<asp:TextBox id="txtListPrice" text='<%#Eval("ListPrice")%>'
Width="80" runat="server"/>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
Người dùng phải bấm vào nút "Edit" để nhập vào chế độ chỉnh sửa. Trong khi ở chế độ chỉnh sửa, ta có thể chọn để thực hiện hai hành động. Ta có thể thay đổi các thuộc tính sản phẩm và click vào nút "Update" để thay đổi cơ sở dữ liệu hoặc có thể click vào "Cancel" để quay trở lại chế độ bình thường.
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="btnedit" runat="server" CommandName="Edit"
Text="Edit"/>
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton ID="btnupdate" runat="server"
CommandName="Update" Text="Update" />
<asp:LinkButton ID="btncancel" runat="server"
CommandName="Cancel" Text="Cancel"/>
</EditItemTemplate>
</asp:TemplateField>
</asp:gridview>
Thực hiện:
Khi trang web được yêu cầu, sự kiện Page_Load là một trong những sự kiện bị get ở phía máy chủ. Chúng ta lấy sản phẩm từ cơ sở dữ liệu và lưu nó trong ViewState để làm mới trang tiếp theo.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
BindData();
}
private void BindData()
{
//Bind the grid view
gvProducts.DataSource = RetrieveProducts();
gvProducts.DataBind();
}
private DataSet RetrieveProducts()
{
if (ViewState["Products"] != null)
return (DataSet)ViewState["Products"];
//fetch the connection string from web.config
string connString =
ConfigurationManager.ConnectionStrings["Sql"].ConnectionString;
//SQL statement to fetch entries from products
string sql = @"Select top 10 P.ProductID, P.Name as ProductName,
P.ProductNumber, ListPrice, PS.ProductSubCategoryID,
ps.Name as SubCategoryName
from Production.Product P
INNER JOIN Production.ProductSubcategory PS
ON P.ProductSubcategoryID = PS.ProductSubcategoryID";
DataSet dsProducts = new DataSet();
//Open SQL Connection
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
//Initialize command object
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
//Fill the result set
adapter.Fill(dsProducts);
}
}
ViewState["Products"] = dsProducts;
return dsProducts;
}
Khi người dùng nhấp vào nút "Edit", sự kiện OnRowEditing được raised và xử lý sự kiện gvProducts_RowEditing thường được gọi. Chúng ta thiết lập các chỉ số chỉnh sửa của GridView đến hàng bạn đang cố gắng để chỉnh sửa. Vì nó là post back, chúng ta phải tái ràng buộc điều khiển GridView. Bất cứ khi nào chúng ta cố gắng kết nối dữ liệu với Grid RowDataBound bắn một lần cho mỗi hàng như databound. Nếu bạn muốn xử lý bất kỳ dữ liệu ràng buộc các trường hợp đặc biệt có liên quan. Chúng ta nạp subcategories vào DropDownList. Chúng ta nhận được danh sách có sẵn sub categories từ Production. ProductSubcategory và sẽ ràng buộc nó vào danh sách thả xuống.
protected void gvProducts_RowEditing(object sender,
GridViewEditEventArgs e)
{
gvProducts.EditIndex = e.NewEditIndex;
BindData();
}
protected void gvProducts_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//check if is in edit mode
if ((e.Row.RowState & DataControlRowState.Edit) > 0)
{
DropDownList ddlSubCategories =
(DropDownList)e.Row.FindControl("ddlSubCategories");
//Bind subcategories data to dropdownlist
ddlSubCategories.DataTextField = "SubCategoryName";
ddlSubCategories.DataValueField = "ProductSubcategoryID";
ddlSubCategories.DataSource = RetrieveSubCategories();
ddlSubCategories.DataBind();
DataRowView dr = e.Row.DataItem as DataRowView;
ddlSubCategories.SelectedValue =
dr["ProductSubCategoryID"].ToString();
}
}
}
private DataTable RetrieveSubCategories()
{
//fetch the connection string from web.config
string connString =
ConfigurationManager.ConnectionStrings["Sql"].ConnectionString;
//SQL statement to fetch entries from products
string sql = @"Select ProductSubcategoryID, Name as SubCategoryName
from Production.ProductSubcategory";
DataTable dtSubCategories = new DataTable();
//Open SQL Connection
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
//Initialize command object
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
//Fill the result set
adapter.Fill(dtSubCategories);
}
}
return dtSubCategories;
}
Thay đổi sub category đến "Chains" và giá đến $50. Bấm vào nút "Update" và sự kiện gvProducts_RowUpdating được gọi. Chúng ta nhận được các giá trị entered/changed bởi người sử dụng và vào cơ sở dữ liệu.
protected void gvProducts_RowUpdating(Object sender,
GridViewUpdateEventArgs e)
{
// Get the product id of the selected product
string productID = gvProducts.DataKeys[e.RowIndex].Value.ToString();
// Get the GridViewRow object that represents the row being edited
// from the Rows collection of the GridView control.
GridViewRow row = gvProducts.Rows[e.RowIndex];
// Get the controls that contain the updated values. In this
// example, the updated values are contained in the TextBox
// controls declared in the edit item templates of each TemplateField
// column fields in the GridView control.
TextBox txtProductNumber = (TextBox)row.FindControl("txtProductNumber");
TextBox txtProductName = (TextBox)row.FindControl("txtProductName");
DropDownList ddlSubCategories =
(DropDownList)row.FindControl("ddlSubCategories");
TextBox txtListPrice = (TextBox)row.FindControl("txtListPrice");
//update the product
UpdateProduct(productID, txtProductName.Text,
ddlSubCategories.SelectedValue,
txtListPrice.Text);
gvProducts.EditIndex = -1;
ViewState["Products"] = null;
BindData();
}
Private void UpdateProduct(string productID,
string productName, string subCategoryID, string listPrice)
{
//fetch the connection string from web.config
string connString =
ConfigurationManager.ConnectionStrings["Sql"].ConnectionString;
//SQL statement to update a product
string sql = String.Format(@"Update Production.Product set Name='{0}'
,ProductSubcategoryID={1}
,ListPrice ={2}
where ProductID = {3}",
productName,
subCategoryID,
listPrice, productID);
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
//Initialize command object
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.ExecuteNonQuery();
}
}