摘要:[C#][ASP.NET]在GridView中將DropDownList關聯另一個DropDownList歷險記
執行畫面如下:
.aspx如下
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
time:<%=DateTime.Now.ToLongTimeString() %>
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" AllowSorting="True"
AutoGenerateColumns="False" DataKeyNames="OrderID,ProductID"
DataSourceID="SqlDataSource1" PageSize="5" onrowupdated="GridView1_RowUpdated">
<Columns>
<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" ShowSelectButton="True" />
<asp:BoundField DataField="OrderID" HeaderText="OrderID" ReadOnly="True" SortExpression="OrderID" />
<asp:TemplateField HeaderText="CategoryName" SortExpression="CategoryName">
<EditItemTemplate>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="SqlDataSource1"
DataTextField="CategoryName" DataValueField="CategoryID" AutoPostBack="True"
SelectedValue='<%# Eval("CategoryID") %>'>
</asp:DropDownList>
</ContentTemplate>
</asp:UpdatePanel>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT [CategoryID], [CategoryName] FROM [Categories]"></asp:SqlDataSource>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Eval("CategoryName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="ProductName" SortExpression="ProductName">
<EditItemTemplate>
<asp:UpdatePanel ID="UpdatePanel2" runat="server">
<ContentTemplate>
<asp:DropDownList ID="DropDownList2" runat="server" DataSourceID="SqlDataSource2"
DataTextField="ProductName" DataValueField="ProductID" SelectedValue='<%# Bind_ProductID(DropDownList2) %>'>
</asp:DropDownList>
</ContentTemplate>
</asp:UpdatePanel>
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="select ProductID,ProductName from Products WHERE ([CategoryID] = @CategoryID) union select -1 as ProductID,'' as ProductName from Products order by ProductName">
<SelectParameters>
<asp:ControlParameter ControlID="DropDownList1" Name="CategoryID" PropertyName="SelectedValue"
Type="Int32" />
</SelectParameters>
</asp:SqlDataSource>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Eval("ProductName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice" />
<asp:BoundField DataField="Quantity" HeaderText="Quantity" SortExpression="Quantity" />
<asp:BoundField DataField="Discount" HeaderText="Discount" SortExpression="Discount" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
DeleteCommand="DELETE FROM [Order Details] WHERE [OrderID] = @OrderID AND [ProductID] = @ProductID"
InsertCommand="INSERT INTO [Order Details] ([OrderID], [ProductID], [UnitPrice], [Quantity], [Discount]) VALUES (@OrderID, @ProductID, @UnitPrice, @Quantity, @Discount)"
SelectCommand="SELECT [Order Details].OrderID, Categories.CategoryID, Categories.CategoryName, [Order Details].ProductID, Products.ProductName,
[Order Details].UnitPrice, [Order Details].Quantity, [Order Details].Discount
FROM [Order Details] INNER JOIN
Products ON [Order Details].ProductID = Products.ProductID INNER JOIN
Categories ON Products.CategoryID = Categories.CategoryID" UpdateCommand="UPDATE [Order Details] SET [UnitPrice] = @UnitPrice, [Quantity] = @Quantity, [Discount] = @Discount, [ProductID] = @New_ProductID WHERE [OrderID] = @OrderID AND [ProductID] = @ProductID">
<DeleteParameters>
<asp:Parameter Name="OrderID" Type="Int32" />
<asp:Parameter Name="ProductID" Type="Int32" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="UnitPrice" Type="Decimal" />
<asp:Parameter Name="Quantity" Type="Int16" />
<asp:Parameter Name="Discount" Type="Single" />
<asp:Parameter Name="OrderID" Type="Int32" />
<asp:Parameter Name="ProductID" Type="Int32" />
<asp:ControlParameter Name="New_ProductID" Type="Int32" ControlID="GridView1$ctl03$DropDownList2" PropertyName="SelectedValue" />
</UpdateParameters>
<InsertParameters>
<asp:Parameter Name="OrderID" Type="Int32" />
<asp:Parameter Name="ProductID" Type="Int32" />
<asp:Parameter Name="UnitPrice" Type="Decimal" />
<asp:Parameter Name="Quantity" Type="Int16" />
<asp:Parameter Name="Discount" Type="Single" />
</InsertParameters>
</asp:SqlDataSource>
</form>
</body>
</html>
.cs如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected string Bind_ProductID(DropDownList DropDownList_ProductID)
{
string Result;
GridViewRow GridViewRow_1 = (GridViewRow)DropDownList_ProductID.NamingContainer;
if (GridViewRow_1.DataItem == null)
{
Result = "-1";
}
else
{
DataRowView DataRowView_1 = (DataRowView)GridViewRow_1.DataItem;
Result = DataRowView_1["ProductID"].ToString();
}
return Result;
}
protected void GridView1_RowUpdated(object sender, GridViewUpdatedEventArgs e)
{
if (e.Exception != null)
{
e.ExceptionHandled = true;
e.KeepInEditMode = true;
Response.Write("");
}
}
}
過程中遇到的錯誤:
原本想法:
<asp:DropDownList ID="DropDownList2" runat="server" DataSourceID="SqlDataSource2"
DataTextField="ProductName" DataValueField="ProductID" SelectedValue='<%# Bind("ProductID") %>'>
</asp:DropDownList>
導致錯誤:
諸如 Eval()、XPath() 和 Bind() 等資料繫結方法,只能在資料繫結控制項的內容中使用。
'DropDownList2' 擁有的 SelectedValue 無效,因為它不在項目清單中。
參數名稱: value
替代方式:
<asp:DropDownList ID="DropDownList2" runat="server" DataSourceID="SqlDataSource2"
DataTextField="ProductName" DataValueField="ProductID" SelectedValue='<%# Bind_ProductID(DropDownList2) %>'>
</asp:DropDownList>
原本想法:
protected string Bind_ProductID(DropDownList DropDownList_ProductID)
{
string Result;
GridViewRow GridViewRow_1 = (GridViewRow)DropDownList_ProductID.NamingContainer;
DataRowView DataRowView_1 = (DataRowView)GridViewRow_1.DataItem;
Result = DataRowView_1["ProductID"].ToString();
return Result;
}
導致錯誤(在選擇CategoryName時):
和另一種錯誤
[ArgumentOutOfRangeException: 'DropDownList2' 擁有的 SelectedValue 無效,因為它不在項目清單中。
參數名稱: value]
替代方式:
將DropDownList2(ProductID)的資料來源總有一個"-1"的選項
SelectCommand="select ProductID,ProductName from Products WHERE ([CategoryID] = @CategoryID) union select -1 as ProductID,'' as ProductName from Products order by ProductName"
然後發現在選擇CategoryName時,GridViewRow_1.DataItem 是 null,於是利用這個現象將程式修改成
protected string Bind_ProductID(DropDownList DropDownList_ProductID)
{
string Result;
GridViewRow GridViewRow_1 = (GridViewRow)DropDownList_ProductID.NamingContainer;
if (GridViewRow_1.DataItem == null)
{
Result = "-1";
}
else
{
DataRowView DataRowView_1 = (DataRowView)GridViewRow_1.DataItem;
Result = DataRowView_1["ProductID"].ToString();
}
return Result;
}
原本想法:
<asp:ControlParameter Name="New_ProductID" Type="Int32" ControlID="DropDownList2" PropertyName="SelectedValue" />
導致錯誤:
在 ControlParameter 'New_ProductID' 中找不到控制項 'DropDownList2'。
替代方式(在瀏覽端程式查看DropDownList2的Name):
<asp:ControlParameter Name="New_ProductID" Type="Int32" ControlID="GridView1$ctl03$DropDownList2" PropertyName="SelectedValue" />