共用方式為


檢查與插入、更新和刪除建立關聯的事件 (C#)

由斯科特· 米切爾

下載 PDF

在本教學課程中,我們將檢查使用 ASP.NET 數據 Web 控件的插入、更新或刪除作業之前、期間及之後發生的事件。 我們也會瞭解如何自定義編輯介面,只更新產品欄位的子集。

簡介

使用 GridView、DetailsView 或 FormView 控件的內建插入、編輯或刪除功能時,當使用者完成新增記錄或更新或刪除現有記錄的程式時,就會發生各種步驟。 如上一個教學課程所述,當 GridView 中編輯數據列時,[編輯] 按鈕會取代為 Update 和 Cancel 按鈕,而 BoundFields 會變成 TextBoxes。 使用者更新數據並按兩下列步驟:

  1. GridView 會填入其 ObjectDataSource 的 ObjectDataSource UpdateParameters ,並填入編輯記錄的唯一識別字段(s) (透過 DataKeyNames 屬性),以及使用者輸入的值
  2. GridView 會叫用其 ObjectDataSource 的 Update() 方法,進而在基礎物件中叫用適當的方法(ProductsDAL.UpdateProduct在我們的上一個教學課程中)
  3. 基礎數據,現在包含更新的變更,會反彈至 GridView

在這個步驟序列中,會引發許多事件,讓我們能夠建立事件處理程式,以視需要新增自定義邏輯。 例如,在步驟 1 之前,GridView 的事件 RowUpdating 就會引發。 此時,如果發生一些驗證錯誤,我們可以取消更新要求。 Update()叫用 方法時,會引發 ObjectDataSource 的事件Updating,提供新增或自定義任何 UpdateParameters值的機會。 在 ObjectDataSource 的基礎物件方法完成執行之後,就會引發 ObjectDataSource 的事件 Updated 。 事件的事件處理程式 Updated 可以檢查更新作業的詳細數據,例如受影響的數據列數目,以及是否發生例外狀況。 最後,在步驟 2 之後,GridView 的事件 RowUpdated 就會引發;此事件的事件處理程式可以檢查剛執行之更新作業的其他資訊。

圖 1 描述更新 GridView 時的這一系列事件和步驟。 圖 1 中的事件模式不是使用 GridView 進行更新的唯一。 從 GridView、DetailsView 或 FormView 插入、更新或刪除數據時,會針對數據 Web 控件和 ObjectDataSource,在層級前和後置事件順序中產生相同的順序。

在 GridView 中更新數據時引發一系列的前置和後置事件

圖 1:在 GridView 中更新資料時引發一系列預先和後置事件 (按兩下以檢視完整大小的影像

在本教學課程中,我們將檢查使用這些事件來擴充內建插入、更新和刪除 ASP.NET 數據 Web 控制件的功能。 我們也會瞭解如何自定義編輯介面,只更新產品欄位的子集。

步驟 1:更新產品的ProductNameUnitPrice欄位

在上一個教學課程的編輯介面中,所有非只讀的產品欄位都必須包含。 如果我們要從 GridView 移除欄位 , 例如 QuantityPerUnit - 更新資料時,Web 控件不會設定 ObjectDataSource QuantityPerUnit UpdateParameters 的值。 然後 ObjectDataSource 會將值UpdateProduct傳入null商業規則層 (BLL) 方法,以將編輯的資料庫記錄數據QuantityPerUnit行變更為NULL值。 同樣地,如果從編輯介面中移除必要的欄位, ProductName更新將會失敗,並顯示「數據行 』ProductName' 不允許 Null」例外狀況。 此行為的原因是 ObjectDataSource 已設定為呼叫 ProductsBLL 類別的 UpdateProduct 方法,預期每個產品欄位都有輸入參數。 因此,ObjectDataSource 的 UpdateParameters 集合包含每個方法輸入參數的參數。

如果我們想要提供可讓使用者只更新字段子集的數據 Web 控件,則我們需要以程式設計方式設定 ObjectDataSource Updating 事件處理程式中的遺漏UpdateParameters值,或建立並呼叫只預期字段子集的 BLL 方法。 讓我們來探索後者的方法。

具體而言,讓我們建立一個頁面,只 ProductName 顯示可編輯 GridView 中的 和 UnitPrice 字段。 此 GridView 的編輯介面只允許使用者更新兩個顯示的欄位與 ProductName UnitPrice。 由於此編輯介面只提供產品的字段子集,因此,我們既需要建立 ObjectDataSource,該物件會使用現有的 BLL 方法,並在事件處理程式中Updating以程序設計方式設定遺漏的產品功能變數值,或者我們需要建立新的 BLL UpdateProduct 方法,只預期 GridView 中定義的字段子集。 在本教學課程中,讓我們使用后一個選項並建立 方法的多 UpdateProduct 載,其中只接受三個輸入參數: productNameunitPriceproductID

[System.ComponentModel.DataObjectMethodAttribute
    (System.ComponentModel.DataObjectMethodType.Update, false)]
public bool UpdateProduct(string productName, decimal? unitPrice, int productID)
{
    Northwind.ProductsDataTable products = Adapter.GetProductByProductID(productID);
    if (products.Count == 0)
        // no matching record found, return false
        return false;

    Northwind.ProductsRow product = products[0];

    product.ProductName = productName;
    if (unitPrice == null) product.SetUnitPriceNull();
      else product.UnitPrice = unitPrice.Value;

    // Update the product record
    int rowsAffected = Adapter.Update(product);

    // Return true if precisely one row was updated, otherwise false
    return rowsAffected == 1;
}

和原始 UpdateProduct 方法一樣,此多載一開始會檢查資料庫中是否有具有指定 ProductID之的產品。 如果沒有,則會傳 false回 ,表示更新產品資訊的要求失敗。 否則,它會呼叫 TableAdapter 的 Update() 方法ProductsRow,傳入 實例,以據以更新現有的產品記錄ProductNameUnitPrice字段,並認可更新。

在此類別 ProductsBLL 中,我們已準備好建立簡化的 GridView 介面。 DataModificationEvents.aspx開啟資料夾中的 EditInsertDelete ,並將 GridView 新增至頁面。 建立新的 ObjectDataSource,並將其設定為使用 ProductsBLL 類別搭配其Select()方法對應,GetProducts以及其Update()方法對應至UpdateProduct只接受 、 unitPriceproductID 輸入參數的多productName載。 圖 2 顯示將 ObjectDataSource Update() 方法對應至 ProductsBLL 類別的新 UpdateProduct 方法多載時,建立數據源精靈。

將 ObjectDataSource 的 Update() 方法對應至 New UpdateProduct 多載

圖 2:將 ObjectDataSource 的 Update() 方法對應至新的 UpdateProduct 多載 (按兩下以檢視完整大小的影像

由於我們的範例一開始只需要能夠編輯數據,但不需要插入或刪除記錄,請花點時間明確指出 ObjectDataSource 的 Insert()Delete() 方法不應該透過移至 INSERT 和 DELETE 索引標籤,並從下拉式清單中選擇 [無] 來對應至類別的任何 ProductsBLL 方法。

從 [插入] 和 [刪除] 索引標籤的下拉式清單中選擇 [無]

圖 3:從 [插入] 和 [刪除] 索引標籤的下拉式清單中選擇 [無] (按兩下以檢視完整大小的影像

完成此精靈之後,請核取 GridView 智慧標記中的 [啟用編輯] 複選框。

完成建立數據源精靈並系結至 GridView 之後,Visual Studio 會為這兩個控件建立宣告式語法。 移至 [來源] 檢視以檢查 ObjectDataSource 的宣告式標記,如下所示:

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    OldValuesParameterFormatString="original_{0}" SelectMethod="GetProducts"
    TypeName="ProductsBLL" UpdateMethod="UpdateProduct">
    <UpdateParameters>
        <asp:Parameter Name="productName" Type="String" />
        <asp:Parameter Name="unitPrice" Type="Decimal" />
        <asp:Parameter Name="productID" Type="Int32" />
    </UpdateParameters>
</asp:ObjectDataSource>

因為 ObjectDataSource 的 Insert()Delete() 方法沒有對應,因此沒有 InsertParametersDeleteParameters 區段。 此外,由於 Update() 方法會對應至 UpdateProduct 只接受三個輸入參數的方法多載,因此 區 UpdateParameters 段只有三 Parameter 個實例。

請注意,ObjectDataSource 的 OldValuesParameterFormatString 屬性設定為 original_{0}。 使用 [設定數據源精靈] 時,Visual Studio 會自動設定此屬性。 不過,由於我們的 BLL 方法不會預期原始 ProductID 值會傳入,因此請從 ObjectDataSource 的宣告式語法中完全移除此屬性指派。

注意

如果您只要從設計視圖中的 屬性視窗 清除OldValuesParameterFormatString屬性值,屬性仍會存在於宣告式語法中,但會設定為空字串。 請從宣告式語法移除 屬性,或從 屬性視窗 將值設定為預設值 {0}

雖然 ObjectDataSource 只有 UpdateParameters 產品的名稱、價格和標識碼,但 Visual Studio 已在 GridView 中針對每個產品的欄位新增 BoundField 或 CheckBoxField。

GridView 包含每個產品的欄位的 BoundField 或 CheckBoxField

圖 4:GridView 包含每個產品的欄位的 BoundField 或 CheckBoxField(按兩下以檢視完整大小的影像

當使用者編輯產品並按兩下其 [更新] 按鈕時,GridView 會列舉那些不是唯讀的字段。 然後,它會將 ObjectDataSource UpdateParameters 集合中對應參數的值設定為使用者輸入的值。 如果沒有對應的參數,GridView 會將一個參數新增至集合。 因此,如果我們的 GridView 包含所有產品的欄位 BoundFields 和 CheckBoxFields,ObjectDataSource 最終會叫 UpdateProduct 用所有參數的多載,儘管 ObjectDataSource 的宣告式標記只指定三個輸入參數(請參閱圖 5)。 同樣地,如果 GridView 中有一些非只讀產品欄位群組,但未對應至多載的輸入參數 UpdateProduct ,嘗試更新時將會引發例外狀況。

GridView 會將參數新增至 ObjectDataSource 的 UpdateParameters 集合

圖 5:GridView 會將參數新增至 ObjectDataSource 的 UpdateParameters 集合(按兩下以檢視完整大小的影像

為了確保 ObjectDataSource 會叫UpdateProduct用只接受產品名稱、價格和標識碼的多載,我們需要限制 GridView 只有 和 UnitPrice的可編輯字段ProductName。 這可以藉由移除其他 BoundFields 和 CheckBoxFields、將其他欄位的 ReadOnly 屬性設定為 true,或透過兩者的某些組合來完成。 在本教學課程中,我們只需要移除 和 UnitPrice BoundFields 以外的ProductName所有 GridView 欄位,之後 GridView 的宣告式標記看起來會像這樣:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
    <Columns>
        <asp:CommandField ShowEditButton="True" />
        <asp:BoundField DataField="ProductName"
          HeaderText="ProductName" SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
          SortExpression="UnitPrice" />
    </Columns>
</asp:GridView>

儘管多 UpdateProduct 載預期有三個輸入參數,但我們在 GridView 中只有兩個 BoundFields。 這是因為 productID 輸入參數是主鍵值,並透過編輯數據列的 DataKeyNames 屬性值傳入。

我們的 GridView 以及 UpdateProduct 多載可讓使用者只編輯產品的名稱和價格,而不會遺失任何其他產品字段。

介面只允許編輯產品的名稱和價格

圖 6:介面只允許編輯產品名稱和價格(按兩下以檢視完整大小的影像

注意

如上一個教學課程所述,必須啟用 GridView 的檢視狀態(預設行為)。 如果您將 GridView 的 EnableViewState 屬性設定為 false,您就會有不小心刪除或編輯記錄的並行用戶風險。

UnitPrice改善格式設定

雖然圖 6 所示的 GridView 範例運作正常, UnitPrice 但字段完全不會格式化,因此價格顯示缺少任何貨幣符號,而且有四個小數位數。 若要為不可編輯的數據列套用貨幣格式設定,只要將 BoundField 的 屬性設定UnitPrice{0:c} ,其 HtmlEncode 屬性就會設定為 falseDataFormatString

據以設定 UnitPrice 的 DataFormatString 和 HtmlEncode 屬性

圖 7:據以設定 UnitPriceDataFormatStringHtmlEncode 屬性 (按一下以檢視完整大小的影像

透過這項變更,不可編輯的數據列會將價格格式化為貨幣;不過,已編輯的數據列仍會顯示沒有貨幣符號且具有四個小數位數的值。

不可編輯的數據列現在會格式化為貨幣值

圖 8:不可編輯的數據列現在已格式化為貨幣值(按兩下以檢視完整大小的影像

屬性中指定的 DataFormatString 格式設定指示可以套用至編輯介面,方法是將 BoundField 的 ApplyFormatInEditMode 屬性 true 設定為 (預設值為 false)。 花點時間將這個屬性設定為 true

將 UnitPrice BoundField 的 ApplyFormatInEditMode 屬性設定為 true

圖 9:將 BoundField 的 ApplyFormatInEditMode 屬性設定UnitPricetrue按兩下以檢視完整大小的影像

有了這項變更,編輯數據列中所顯示的值 UnitPrice 也會格式化為貨幣。

GridView 的螢幕快照,其中顯示格式化為貨幣之已編輯數據列的 UnitPrice 值。

圖 10:編輯的數據 UnitPrice 列值現在已格式化為貨幣(按兩下以檢視完整大小的影像

不過,在文字框中以貨幣符號更新產品,例如 $19.00 會擲回 FormatException。 當 GridView 嘗試將使用者提供的值指派給 ObjectDataSource 的UpdateParameters集合時,就無法將字串 “$19.00” decimal 轉換成 UnitPrice 參數所需的 值(請參閱圖 11)。 為了解決這個問題,我們可以為 GridView RowUpdating 的事件建立事件處理程式,並讓它剖析為貨幣格式decimal的使用者UnitPrice

GridView RowUpdating 的事件接受作為 GridViewUpdateEventArgs 類型的第二個參數,其中包含字典做為其其中一個NewValues屬性,其中保存可供指派給 ObjectDataSource UpdateParameters 集合之使用者提供值的屬性之一。 我們可以使用貨幣格式,在事件處理程式中以下列程式代碼RowUpdating行來剖析的十進位值覆寫集合中的NewValues現有UnitPrice值:

protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
  if (e.NewValues["UnitPrice"] != null)
    e.NewValues["UnitPrice"] =
        decimal.Parse(e.NewValues["UnitPrice"].ToString(),
            System.Globalization.NumberStyles.Currency);
}

如果使用者已提供UnitPrice值(例如 “$19.00”),則會以 Decimal.Parse 計算的十進位值覆寫此值,將值剖析為貨幣。 這會正確地剖析任何貨幣符號、逗號、小數點等的十進位,並使用 System.Globalization 命名空間中的 NumberStyles 列舉。

圖 11 顯示使用者提供 UnitPrice中貨幣符號所造成的兩個問題,以及如何使用 GridView 的 RowUpdating 事件處理程式來正確剖析這類輸入。

此圖顯示 ObjectDataSource 如何處理 UnitPrice 欄位,以及 GridView 的 RowUpdate 事件處理程式如何將字串轉換成十進位。

圖 11:編輯的數據 UnitPrice 列值現在已格式化為貨幣(按兩下以檢視完整大小的影像

步驟 2:禁止NULL UnitPrices

當資料庫設定為允許NULL數據表數據UnitPrice行中的Products值時,我們可能會想要防止使用者流覽此特定頁面來指定NULLUnitPrice值。 也就是說,如果使用者在編輯產品數據列時無法輸入 UnitPrice 值,而不是將結果儲存到我們想要顯示訊息的資料庫,告知使用者,透過此頁面,任何編輯的產品都必須指定價格。

GridViewUpdateEventArgs傳遞至 GridView RowUpdating 事件處理程式的物件包含Cancel屬性,如果設定為 true,就會終止更新程式。 讓我們擴充RowUpdating事件處理程式,將 設定e.Canceltrue ,並顯示訊息,說明集合中的NewValues值為何UnitPricenull

首先,將標籤 Web 控件新增至名為 MustProvideUnitPriceMessage的頁面。 如果使用者在更新產品時無法指定 UnitPrice 值,則會顯示此標籤控件。 將 Label 的 Text 屬性設定為「您必須提供產品的價格」。我也已在 中建立名為 Warning 且具有下列定義的新 CSS 類別Styles.css

.Warning
{
    color: Red;
    font-style: italic;
    font-weight: bold;
    font-size: x-large;
}

最後,將 Label 的 CssClass 屬性設定為 Warning。 此時,設計工具應該以紅色、粗體、斜體、超大型字型大小顯示警告訊息,如圖 12 所示。

GridView 上方已新增標籤

圖 12:GridView 上方已新增標籤(按兩下以檢視完整大小的影像

根據預設,此標籤應該隱藏,因此請在事件處理程式中將其 Visible 屬性設定為 false Page_Load

protected void Page_Load(object sender, EventArgs e)
{
    MustProvideUnitPriceMessage.Visible = false;
}

如果用戶嘗試在不指定 UnitPrice的情況下更新產品,我們想要取消更新並顯示警告標籤。 增強 GridView 的 RowUpdating 事件處理程式,如下所示:

protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
    if (e.NewValues["UnitPrice"] != null)
    {
        e.NewValues["UnitPrice"] =
            decimal.Parse(e.NewValues["UnitPrice"].ToString(),
                System.Globalization.NumberStyles.Currency);
    }
    else
    {
        // Show the Label
        MustProvideUnitPriceMessage.Visible = true;

        // Cancel the update
        e.Cancel = true;
    }
}

如果使用者嘗試儲存產品而不指定價格,則會取消更新並顯示有用的訊息。 雖然資料庫(和商業規則)允許 NULL UnitPrice s,但這個特定的 ASP.NET 頁面則不允許。

用戶無法將 UnitPrice 保留空白

圖 13:使用者無法保留 UnitPrice 空白 (按兩下以檢視完整大小的影像

到目前為止,我們已經瞭解如何使用 GridView 的事件 RowUpdating ,以程式設計方式改變指派給 ObjectDataSource UpdateParameters 集合的參數值,以及如何完全取消更新程式。 這些概念會延續至 DetailsView 和 FormView 控件,也適用於插入和刪除。

這些工作也可以透過其 InsertingUpdatingDeleting 事件的事件處理程式,在 ObjectDataSource 層級完成。 這些事件會在叫用基礎對象的相關聯方法之前引發,並提供最後的機會來修改輸入參數集合或完全取消作業。 這三個事件的事件處理程式會傳遞 ObjectDataSourceMethodEventArgs 類型的物件,其具有兩個感興趣的屬性:

  • 取消,如果設定為 true,則會取消正在執行的作業
  • InputParameters,這是 、 UpdateParametersDeleteParametersInsertParameters集合,視事件處理程式是否為InsertingUpdatingDeleting 事件而定

為了說明在 ObjectDataSource 層級使用參數值,讓我們在頁面中加入 DetailsView,讓使用者新增產品。 此 DetailsView 將用來提供介面,以便快速將新產品新增至資料庫。 若要在新增新產品時保留一致的使用者介面,讓我們允許使用者只輸入 和 UnitPrice 字段的值ProductName。 根據預設,DetailsView 插入介面中未提供的值會設定為 NULL 資料庫值。 不過,我們可以使用 ObjectDataSource 的事件 Inserting 來插入不同的預設值,因為我們很快就會看到。

步驟 3:提供介面以新增產品

將 DetailsView 從 [工具箱] 拖曳至 GridView 上方的設計工具、清除其 和 Height Width 屬性,並將其系結至頁面上已存在的 ObjectDataSource。 這會為每個產品的欄位新增 BoundField 或 CheckBoxField。 由於我們想要使用此 DetailsView 來新增產品,因此我們需要從智慧標記中檢查 [啟用插入] 選項;不過,沒有這樣的選項,因為 ObjectDataSource 的 Insert() 方法並未對應至 類別中的 ProductsBLL 方法(回想一下,設定數據源時,我們會將此對應設定為 [無],請參閱圖 3)。

若要設定 ObjectDataSource,請從其智慧標記中選取 [設定數據源] 鏈接,啟動精靈。 第一個畫面可讓您變更 ObjectDataSource 所系結的基礎物件;設定為 ProductsBLL。 下一個畫面會列出 ObjectDataSource 方法與基礎對象的對應。 雖然我們明確指出 Insert()Delete() 方法不應該對應至任何方法,但如果您移至 INSERT 和 DELETE 索引標籤,您會看到對應存在。 這是因為ProductsBLL的和方法會使用 DataObjectMethodAttribute 屬性來指出它們分別是 和 DeleteProduct Delete()的預設方法Insert()AddProduct。 因此,除非您明確指定一些其他值,否則每次執行精靈時,ObjectDataSource 精靈都會選取這些精靈。

Insert()讓方法指向 AddProduct 方法,但再次將 [DELETE] 索引標籤的下拉式清單設定為 [無]。

將 INSERT 索引標籤的下拉式清單設定為 AddProduct 方法

圖 14:將 INSERT 索引標籤的下拉式清單設定為 AddProduct [方法] (按兩下以檢視完整大小的影像

將 [刪除] 索引標籤的下拉式清單設定為 [無]

圖 15:將 [刪除] 索引標籤的下拉式清單設定為 [無] (按兩下以檢視完整大小的影像

進行這些變更之後,ObjectDataSource 的宣告式語法將會展開以包含 InsertParameters 集合,如下所示:

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    SelectMethod="GetProducts" TypeName="ProductsBLL"
    UpdateMethod="UpdateProduct" OnUpdating="ObjectDataSource1_Updating"
    InsertMethod="AddProduct" OldValuesParameterFormatString="original_{0}">
    <UpdateParameters>
        <asp:Parameter Name="productName" Type="String" />
        <asp:Parameter Name="unitPrice" Type="Decimal" />
        <asp:Parameter Name="productID" Type="Int32" />
    </UpdateParameters>
    <InsertParameters>
        <asp:Parameter Name="productName" Type="String" />
        <asp:Parameter Name="supplierID" Type="Int32" />
        <asp:Parameter Name="categoryID" Type="Int32" />
        <asp:Parameter Name="quantityPerUnit" Type="String" />
        <asp:Parameter Name="unitPrice" Type="Decimal" />
        <asp:Parameter Name="unitsInStock" Type="Int16" />
        <asp:Parameter Name="unitsOnOrder" Type="Int16" />
        <asp:Parameter Name="reorderLevel" Type="Int16" />
        <asp:Parameter Name="discontinued" Type="Boolean" />
    </InsertParameters>
</asp:ObjectDataSource>

重新執行已新增回 屬性的 OldValuesParameterFormatString 精靈。 請花點時間將此屬性設定為預設值 ({0}) 或完全從宣告式語法中移除它,以清除此屬性。

使用提供插入功能的 ObjectDataSource,DetailsView 的智慧標記現在會包含 [啟用插入] 複選框;返回設計工具,並核取此選項。 接下來,剖析 DetailsView,使其只有兩個 BoundFields - ProductNameUnitPrice - 和 CommandField。 此時,DetailsView 的宣告式語法看起來應該像這樣:

<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
    <Fields>
        <asp:BoundField DataField="ProductName"
          HeaderText="ProductName" SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
          SortExpression="UnitPrice" />
        <asp:CommandField ShowInsertButton="True" />
    </Fields>
</asp:DetailsView>

圖 16 顯示此時透過瀏覽器檢視此頁面。 如您所見,DetailsView 會列出第一個產品的名稱和價格(Chai)。 不過,我們想要的是插入介面,可提供使用者快速將新產品新增至資料庫的方法。

DetailsView 目前以唯讀模式轉譯

圖 16:D etailsView 目前以只讀模式轉譯 (按兩下以檢視完整大小的影像

為了以插入模式顯示 DetailsView,我們需要將 DefaultMode 屬性設定為 Inserting。 這會在第一次瀏覽時呈現 InsertView 中的 DetailsView,並在插入新記錄之後將其保留在該處。 如圖 17 所示,這類 DetailsView 提供快速介面來新增記錄。

DetailsView 提供快速新增新產品的介面

圖 17:D etailsView 提供快速新增新產品的介面(按兩下即可檢視完整大小的影像

當使用者輸入產品名稱和價格時(例如“Acme Water”和 1.99,如圖 17 所示),然後按兩下 [插入]、後續回傳和插入工作流程開始,最終將新產品記錄新增至資料庫。 DetailsView 會維護其插入介面,且 GridView 會自動反彈至其數據源,以包含新產品,如圖 18 所示。

產品

圖 18:產品 「Acme Water」 已新增至資料庫

雖然圖 18 中的 GridView 未顯示,但來自 DetailsView 介面 CategoryIDSupplierIDQuantityPerUnit等的產品欄位會指派 NULL 資料庫值。 您可以執行下列步驟來檢視此問題:

  1. 移至 Visual Studio 中的 [伺服器總管]
  2. NORTHWND.MDF展開資料庫節點
  3. 以滑鼠右鍵按兩下 Products 資料庫數據表節點
  4. 選取 [顯示資料表資料]

這會列出數據表中的所有 Products 記錄。 如圖 19 所示,除了 、 ProductName和 以外的ProductID所有新產品數據行都有NULLUnitPrice值。

DetailsView 中未提供的產品欄位會獲指派 NULL 值

圖 19:D etailsView 中未提供的產品欄位是指派 NULL 的值(按兩下以檢視完整大小的影像

我們可能想要提供一個或多個這些數據行值以外的 NULL 預設值,可能是因為 NULL 不是最佳預設選項,或是資料庫數據行本身不允許 NULL 。 若要達成此目的,我們可以以程式設計方式設定 DetailsView InputParameters 集合的參數值。 此指派可以在 DetailsView ItemInserting 事件或 ObjectDataSource 事件的 Inserting 事件處理程式中完成。 由於我們已經在數據 Web 控件層級使用預先和後置層級事件,因此讓我們這次使用 ObjectDataSource 的事件進行探索。

步驟 4:將值指派給CategoryIDSupplierID參數

在本教學課程中,讓我們想像,透過這個介面新增新產品時,應用程式應該指派 和 CategoryID SupplierID 值為1。 如先前所述,ObjectDataSource 有一對在數據修改程序期間引發的前置和後置層級事件。 叫用其 Insert() 方法時,ObjectDataSource 會先引發其 Inserting 事件,然後呼叫其 Insert() 方法已對應的方法,最後引發 Inserted 事件。 Inserting事件處理程式提供我們最後一個調整輸入參數或完全取消作業的機會。

注意

在真實世界中,您可能會想要讓使用者指定類別和供應商,或根據一些準則或商業規則來挑選此值(而不是盲目選取標識碼 1)。 不論怎樣,此範例都會說明如何以程序設計方式從 ObjectDataSource 的預先層級事件設定輸入參數的值。

花點時間建立 ObjectDataSource Inserting 事件的事件處理程式。 請注意,事件處理程式的第二個輸入參數是 類型的ObjectDataSourceMethodEventArgs物件,其具有屬性可存取參數集合 (InputParameters) 和取消作業的屬性 。Cancel

protected void ObjectDataSource1_Inserting
    (object sender, ObjectDataSourceMethodEventArgs e)
{

}

此時, InputParameters 屬性會包含 ObjectDataSource 的集合, InsertParameters 其中包含從 DetailsView 指派的值。 若要變更其中一個參數的值,只需使用: e.InputParameters["paramName"] = value。 因此,若要將 和 SupplierID 設定CategoryID為1的值,請調整Inserting事件處理程式,如下所示:

protected void ObjectDataSource1_Inserting
    (object sender, ObjectDataSourceMethodEventArgs e)
{
    e.InputParameters["CategoryID"] = 1;
    e.InputParameters["SupplierID"] = 1;
}

此時,新增新產品(例如 Acme Soda), CategoryID 新產品的 和 SupplierID 數據行會設定為 1 (請參閱圖 20)。

新產品現在已將其 CategoryID 和 SupplierID 值設定為 1

圖 20:新產品現在已將其 CategoryIDSupplierID 值設定為 1 (按兩下以檢視完整大小的影像

摘要

在編輯、插入和刪除程式期間,數據 Web 控制項和 ObjectDataSource 都會繼續執行一些預先和後置層級的事件。 在本教學課程中,我們檢查了預先層級的事件,並瞭解如何使用這些事件來自定義輸入參數,或完全取消數據修改作業,同時來自數據Web控件和 ObjectDataSource 的事件。 在下一個教學課程中,我們將探討如何建立和使用後續層級事件的事件處理程式。

快樂的程序設計!

關於作者

斯科特·米切爾,七本 ASP/ASP.NET 書籍和 4GuysFromRolla.com 創始人的作者,自1998年以來一直與Microsoft Web 技術合作。 斯科特擔任獨立顧問、教練和作家。 他的最新書是 山姆斯在24小時內 ASP.NET 2.0。 他可以到達 mitchell@4GuysFromRolla.com, 或通過他的博客,可以在 找到 http://ScottOnWriting.NET

特別感謝

本教學課程系列已由許多實用的檢閱者檢閱。 本教學課程的主要檢閱者是 Jackie Goor 和 Liz Shulok。 有興趣檢閱我即將推出的 MSDN 文章嗎? 如果是,請將一行 mitchell@4GuysFromRolla.com放在 。