本文档是 Visual C# 教程 (切换到 Visual Basic 教程)

在本教程中,我们将研究如何将 ObjectDataSource 的 Insert()、Update() 和 Delete() 方法映射到 BLL 类的方法,以及如何配置 GridView、DetailsView 和 FormView 控件,使它们提供数据修改功能。

« 前一篇教程  |  下一篇教程 »

Part 3

使用 FormView 创建更灵活的数据修改用户界面

FormView 提供内置的数据插入、编辑和删除支持。但由于 FormView 使用模板而不是字段,因此没有空间添加 GridView 和 DetailsView 控件使用的 BoundField 或 CommandField 来提供数据修改界面。作为替代,此界面(Web 控件,用于收集添加新条目或编辑现有条目时的用户输入,以及 New、Edit、Delete、Insert、Update 和 Cancel 按钮)必须手动添加到相应的模板中。幸运的是,Visual Studio 在通过其智能标记中的下拉列表将 FormView 绑定到数据源时,将自动创建需要的界面。

为演示这些技术,我们首先向 Basics.aspx 页面添加一个 FormView,并从 FormView 的智能标记中将其绑定到已创建的 ObjectDataSource。这将为 FormView 生成一个 EditItemTemplate、一个 InsertItemTemplate 和一个 ItemTemplate,这些模板带有用于收集用户输入的 TextBox Web 控件,以及用于 New、Edit、Delete、Insert、Update 和 Cancel 按钮的 Button Web 控件。此外,FormView 的 DataKeyNames 属性设为 ObjectDataSource 返回的对象的主键字段(ProductID)。最后,在 FormView 的智能标记中选中 Enable Paging 选项。

下面显示了在将 FormView 绑定到 ObjectDataSource 之后,FormView 的 ItemTemplate 的声明性标记。默认情况下,每个非布尔值产品字段都被绑定到一个 Label Web 控件的 Text 属性,每个布尔值字段 (Discontinued) 被绑定到一个禁用的 CheckBox Web 控件的 Checked 属性。为使 New、Edit 和 Delete 按钮在被单击时能触发相应的 FormView 行为,务必将它们的 CommandName 值分别设为 New、Edit 和 Delete。

<asp:FormView ID="FormView1" runat="server" DataKeyNames="ProductID"
    DataSourceID="ObjectDataSource1" AllowPaging="True">
    <EditItemTemplate>
        ...
    </EditItemTemplate>
    <InsertItemTemplate>
        ...
    </InsertItemTemplate>
    <ItemTemplate>
        ProductID:
        <asp:Label ID="ProductIDLabel" runat="server"
            Text='<%# Eval("ProductID") %>'></asp:Label><br />
        ProductName:
        <asp:Label ID="ProductNameLabel" runat="server"
            Text='<%# Bind("ProductName") %>'>
        </asp:Label><br />
        SupplierID:
        <asp:Label ID="SupplierIDLabel" runat="server"
            Text='<%# Bind("SupplierID") %>'>
        </asp:Label><br />
        CategoryID:
        <asp:Label ID="CategoryIDLabel" runat="server"
            Text='<%# Bind("CategoryID") %>'>
        </asp:Label><br />
        QuantityPerUnit:
        <asp:Label ID="QuantityPerUnitLabel" runat="server"
            Text='<%# Bind("QuantityPerUnit") %>'>
        </asp:Label><br />
        UnitPrice:
        <asp:Label ID="UnitPriceLabel" runat="server"
            Text='<%# Bind("UnitPrice") %>'></asp:Label><br />
        UnitsInStock:
        <asp:Label ID="UnitsInStockLabel" runat="server"
            Text='<%# Bind("UnitsInStock") %>'>
        </asp:Label><br />
        UnitsOnOrder:
        <asp:Label ID="UnitsOnOrderLabel" runat="server"
            Text='<%# Bind("UnitsOnOrder") %>'>
        </asp:Label><br />
        ReorderLevel:
        <asp:Label ID="ReorderLevelLabel" runat="server"
            Text='<%# Bind("ReorderLevel") %>'>
        </asp:Label><br />
        Discontinued:
        <asp:CheckBox ID="DiscontinuedCheckBox" runat="server"
            Checked='<%# Bind("Discontinued") %>'
            Enabled="false" /><br />
        CategoryName:
        <asp:Label ID="CategoryNameLabel" runat="server"
            Text='<%# Bind("CategoryName") %>'>
        </asp:Label><br />
        SupplierName:
        <asp:Label ID="SupplierNameLabel" runat="server"
            Text='<%# Bind("SupplierName") %>'>
        </asp:Label><br />
        <asp:LinkButton ID="EditButton" runat="server"
            CausesValidation="False" CommandName="Edit"
            Text="Edit">
        </asp:LinkButton>
        <asp:LinkButton ID="DeleteButton" runat="server"
            CausesValidation="False" CommandName="Delete"
            Text="Delete">
        </asp:LinkButton>
        <asp:LinkButton ID="NewButton" runat="server"
            CausesValidation="False" CommandName="New"
            Text="New">
        </asp:LinkButton>
    </ItemTemplate>
</asp:FormView>

图22 显示了 FormView 的 ItemTemplate 在浏览器中的显示效果。列出所有产品字段,并在底部显示New 、Edit 和 Delete 按钮。

图22 :默认 FormView ItemTemplate 列出所有产品字段及 New 、Edit 和 Delete 按钮

与GridView 和 DetailsView 类似,单击 Delete 按钮或任何 CommandName 属性设为 Delete 的 Button 、LinkButton 或ImageButton 都将引起回传,同时基于 FormView 的 DataKeyNames 值填充ObjectDataSource 的 DeleteParameters ,并调用ObjectDataSource 的 Delete() 方法。

单击 Edit 按钮会引发一次回传,数据被重新绑定到负责呈现编辑界面的EditItemTemplate 。此界面包含用于编辑数据的 Web 控件,以及 Update 和 Cancel 按钮。Visual Studio 生成的默认 EditItemTemplate 中包含对应每个自增长字段 ( ProductID ) 的 Label ,对应每个非布尔值字段的 TextBox ,以及对应每个布尔值字段的 CheckBox 。这种行为与 GridView 和 DetailsView 控件自动生成 BoundField 非常相似。

注意:FormView 自动生成的 EditItemTemplate 也会为只读字段( 如 CategoryName 和 SupplierName )呈现TextBox Web 控件。后面将介绍如何解决此问题。

EditItemTemplate 中的 TextBox 控件使用双向数据绑定 将其Text 属性绑定到相应数据字段的值。双向数据绑定以 <%# Bind("dataField") %> 表示,既可用于将数据绑定到模板,也可用于填充 ObjectDataSource 的参数以便插入或编辑记录。也就是说,当用户从 ItemTemplate 单击 Edit 按钮时, Bind() 方法返回指定的数据字段值。用户完成修改并单击 Update 时,使用 Bind() 指定的数据字段的值回传到 ObjectDataSource 的 UpdateParameters 。单向数据绑定以 <%# Eval("dataField") %> 表示,只在数据被绑定到模板时获取数据字段值,而 不会 在回传时将用户输入的值返回到数据源的参数。

下面的声明性标记显示了FormView 的EditItemTemplate 。注意,这里的数据绑定语法中使用了Bind() 方法,且 Update 和 Cancel Button Web 控件的 CommandName 属性都进行了相应的设置。

<asp:FormView ID="FormView1" runat="server" DataKeyNames="ProductID"
    DataSourceID="ObjectDataSource1" AllowPaging="True">
    <EditItemTemplate>
        ProductID:
        <asp:Label ID="ProductIDLabel1" runat="server"
          Text="<%# Eval("ProductID") %>"></asp:Label><br />
        ProductName:
        <asp:TextBox ID="ProductNameTextBox" runat="server"
          Text="<%# Bind("ProductName") %>">
        </asp:TextBox><br />
        SupplierID:
        <asp:TextBox ID="SupplierIDTextBox" runat="server"
          Text="<%# Bind("SupplierID") %>">
        </asp:TextBox><br />
        CategoryID:
        <asp:TextBox ID="CategoryIDTextBox" runat="server"
          Text="<%# Bind("CategoryID") %>">
        </asp:TextBox><br />
        QuantityPerUnit:
        <asp:TextBox ID="QuantityPerUnitTextBox" runat="server"
           Text="<%# Bind("QuantityPerUnit") %>">
        </asp:TextBox><br />
        UnitPrice:
        <asp:TextBox ID="UnitPriceTextBox" runat="server"
           Text="<%# Bind("UnitPrice") %>">
        </asp:TextBox><br />
        UnitsInStock:
        <asp:TextBox ID="UnitsInStockTextBox" runat="server"
           Text="<%# Bind("UnitsInStock") %>">
        </asp:TextBox><br />
        UnitsOnOrder:
        <asp:TextBox ID="UnitsOnOrderTextBox" runat="server"
           Text="<%# Bind("UnitsOnOrder") %>">
        </asp:TextBox><br />
        ReorderLevel:
        <asp:TextBox ID="ReorderLevelTextBox" runat="server"
           Text="<%# Bind("ReorderLevel") %>">
        </asp:TextBox><br />
        Discontinued:
        <asp:CheckBox ID="DiscontinuedCheckBox" runat="server"
            Checked="<%# Bind("Discontinued") %>" /><br />
        CategoryName:
        <asp:TextBox ID="CategoryNameTextBox" runat="server"
             Text="<%# Bind("CategoryName") %>">
        </asp:TextBox><br />
        SupplierName:
        <asp:TextBox ID="SupplierNameTextBox" runat="server"
             Text="<%# Bind("SupplierName") %>">
        </asp:TextBox><br />
        <asp:LinkButton ID="UpdateButton" runat="server"
            CausesValidation="True" CommandName="Update"
            Text="Update">
        </asp:LinkButton>
        <asp:LinkButton ID="UpdateCancelButton" runat="server"
            CausesValidation="False" CommandName="Cancel"
            Text="Cancel">
        </asp:LinkButton>
    </EditItemTemplate>
    <InsertItemTemplate>
        ...
    </InsertItemTemplate>
    <ItemTemplate>
        ...
    </ItemTemplate>
</asp:FormView>

现在,如果我们试图使用 EditItemTemplate ,将引发一个异常。这是因为 CategoryName 和 SupplierName 字段在 EditItemTemplate 中呈现为 TextBox Web 控件。我们需要将这些TextBox 更改为Label ,或将它们全部删除。现在,我们选择将它们从 EditItemTemplate 中删除。

图23 为单击 Chai 的 Edit 按钮后,浏览器中显示的 FormView 。注意,ItemTemplate 中不再显示 SupplierName 和 CategoryName 字段,因为我们已将这两个字段从 EditItemTemplate 中删除了。单击 Update 按钮时,FormView 将执行与 GridView 和 DetailsView 控件相同的步骤。

图23 :EditItemTemplate 默认将每个可编辑的产品字段显示为一个TextBox 或 CheckBox

单击 FormView 的 ItemTemplate 中的 Insert 按钮将产生一次回传。但没有数据绑定到 FormView ,因为添加了一条新记录。InsertItemTemplate 界面包含用于添加新记录的 Web 控件以及 Insert 和 Cancel 按钮。与自动生成的 EditItemTemplate 的界面相似,Visual Studio 生成的默认 InsertItemTemplate 中包含对应每个非布尔值字段的 TextBox 和对应每个布尔值字段的 CheckBox 。 TextBox 控件使用双向数据绑定,将其 Text 属性绑定到相应数据字段的值。

下面的声明性标记显示了FormView 的InsertItemTemplate 。注意,这里的数据绑定语法中使用了Bind() 方法,且 Insert 和 Cancel Button Web 控件的 CommandName 属性都进行了相应设置。

<asp:FormView ID="FormView1" runat="server" DataKeyNames="ProductID"
    DataSourceID="ObjectDataSource1" AllowPaging="True">
    <EditItemTemplate>
        ...
    </EditItemTemplate>
    <InsertItemTemplate>
        ProductName:
        <asp:TextBox ID="ProductNameTextBox" runat="server"
           Text="<%# Bind("ProductName") %>">
        </asp:TextBox><br />
        SupplierID:
        <asp:TextBox ID="SupplierIDTextBox" runat="server"
           Text="<%# Bind("SupplierID") %>">
        </asp:TextBox><br />
        CategoryID:
        <asp:TextBox ID="CategoryIDTextBox" runat="server"
           Text="<%# Bind("CategoryID") %>">
        </asp:TextBox><br />
        QuantityPerUnit:
        <asp:TextBox ID="QuantityPerUnitTextBox" runat="server"
           Text="<%# Bind("QuantityPerUnit") %>">
        </asp:TextBox><br />
        UnitPrice:
        <asp:TextBox ID="UnitPriceTextBox" runat="server"
           Text="<%# Bind("UnitPrice") %>">
        </asp:TextBox><br />
        UnitsInStock:
        <asp:TextBox ID="UnitsInStockTextBox" runat="server"
           Text="<%# Bind("UnitsInStock") %>">
        </asp:TextBox><br />
        UnitsOnOrder:
        <asp:TextBox ID="UnitsOnOrderTextBox" runat="server"
           Text="<%# Bind("UnitsOnOrder") %>">
        </asp:TextBox><br />
        ReorderLevel:
        <asp:TextBox ID="ReorderLevelTextBox" runat="server"
           Text="<%# Bind("ReorderLevel") %>">
        </asp:TextBox><br />
        Discontinued:
        <asp:CheckBox ID="DiscontinuedCheckBox" runat="server"
           Checked="<%# Bind("Discontinued") %>" /><br />
        CategoryName:
        <asp:TextBox ID="CategoryNameTextBox" runat="server"
            Text="<%# Bind("CategoryName") %>">
        </asp:TextBox><br />
        SupplierName:
        <asp:TextBox ID="SupplierNameTextBox" runat="server"
           Text="<%# Bind("SupplierName") %>">
        </asp:TextBox><br />
        <asp:LinkButton ID="InsertButton" runat="server"
            CausesValidation="True" CommandName="Insert"
            Text="Insert">
        </asp:LinkButton>
        <asp:LinkButton ID="InsertCancelButton" runat="server"
            CausesValidation="False" CommandName="Cancel"
            Text="Cancel">
        </asp:LinkButton>
    </InsertItemTemplate>
    <ItemTemplate>
        ...
    </ItemTemplate>
</asp:FormView>

FormView 自动生成的 InsertItemTemplate 有一个小问题。具体地说,该模板也会为只读字段(如 CategoryName 和 SupplierName )创建 TextBox Web 控件。与 EditItemTemplate 类似,我们需要从 InsertItemTemplate 中删除这些 TextBox 。

图24 为添加新产品 Acme Coffee 时,浏览器中显示的 FormView 。注意,ItemTemplate 中不再显示 SupplierName 和 CategoryName 字段,因为我们已将这两个字段删除了。单击 Insert 按钮时,FormView 将执行与 DetailsView 控件相同的步骤,向 Products 表中添加一条新记录。图 25 为插入 Acme Coffee 后,FormView 中显示的该产品详细信息。

图24 :InsertItemTemplate 规定 FormView 的插入界面

图25 :新产品 Acme Coffee 的详细信息显示在 FormView 中

由于 FormView 将只读界面、编辑界面和插入界面分别用三个单独的模板表示,它达到了比DetailsView 和 GridView 更高程度的界面控制。

注意:与 DetailsView 一样,FormView 的 CurrentMode 属性表明了当前显示的界面,而DefaultMode 属性表明了 FormView 在完成编辑或插入操作后返回的模式。

小结

在本教程中,我们学习了使用 GridView 、DetailsView 和FormView 插入、编辑和删除数据的基本知识。这三种控件提供了一定程度的内置数据修改功能,利用 Web 数据控件和 ObjectDataSource 实现,而无需在 ASP.NET 页面中编写任何代码。但通过简单的鼠标操作技术,我们只能提供简陋的数据修改界面。如果要提供确认、插入编程设置的值、灵活地处理异常情况及自定义用户界面,则需要依靠大量其它的技术。我们将在后面几篇教程中讨论这些技术。

快乐编程 !



上一页 | 1 | 2 | 3 | 下一页

下一篇教程