65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET 自动对象到 UI 绑定

starIconstarIconstarIconstarIconstarIcon

5.00/5 (8投票s)

2012 年 4 月 19 日

CPOL

4分钟阅读

viewsIcon

87472

downloadIcon

1824

轻松将类绑定到 .NET 数据控件,如 GridView、FormView 等,并在代码隐藏中轻松获取更新的对象或列表。

引言

作为一名开发人员,我非常喜欢在代码隐藏中使用对象。您可以称它们为类或 POCO 或其他任何名称,但使用它们并编写代码既简单又有趣。然而,最重复和最烦人的任务之一是将对象属性显示在 UI 中,然后在用户更改某些内容时,将其作为对象返回到您的代码中。此实用程序/框架的目的是轻松实现双向绑定,以便只需几行代码,您就可以将对象的属性绑定到 UI,然后在代码隐藏中获取更新后的值,而无需大量手动编码。

背景

Microsoft ASP.NET 拥有非常好的控件,用于执行 UI 操作,例如 GridViewFormView,它们支持数据绑定。它们非常适合自动将值插入 UI 并显示它们,但是,所谓的双向绑定总体来说很糟糕,尤其是在处理对象时。

当您的用户在 UI 中编辑内容,而您想将其作为对象返回到代码隐藏时,这是一个非常麻烦且重复的工作。您有 2 个选项:

  1. 您可以使用 ObjectDataSource,它提供双向绑定,但您必须编写一个单独的 adapter 类,然后编写 SelectUpdateInsertDelete 方法。
  2. 您可以在后端处理绑定事件,并使用 FindControl 来查找每个控件,然后手动将 Object 的每个属性分配给 UI 控件的值。ugh!这对 Grid 来说尤其麻烦。

我喜欢双向绑定的概念,但我发现这两种技术都令人厌烦。此外,我讨厌在标记中放置 ObjectDataSource 并将方法和值硬编码到其中。我仍然喜欢第一种技术,即编写一个简单的 Adapter 类,并且我很快意识到,由于每个 adapter 类的步骤都相同,我可以使用泛型创建一个实用程序,该程序将自动提供 adapter,而无需为每个类单独编写它。我搜索并审查了许多用于实现双向数据绑定的框架和实用程序,以便轻松地将 Object 从 UI 获取回代码隐藏,但我没有找到任何非常简单的东西,所以我最终编写了这个非常简单的 ObjectBinding 类。

Using the Code

所以基本上,正如我上面所说的,这个实用程序的作用是允许将对象映射到 GridViewFormView 或其他 ASP.NET 控件。

作为示例,我将使用以下极其简单的类:

Public Class Customer

    Property CustomerID As String
    Property FirstName As String
    Property LastName As String
    Property Status As String
    Property Email As String

    Property Addresses As New List(Of Address)

End Class

Public Class Address
    Property AddressID As String
    Property AddressLine As String
    Property City As String
    Property State As String
    Property ZipCode As String
End Class

所以 Customer 是一个简单的对象,它有一个 Addresses 列表。我们将把 Customer 绑定到一个 FormView,并将其相关的地址绑定到一个 GridView,然后演示在 UI 中编辑 Customer 字段,或使用 Grid 在 UI 中添加/删除/更新 Address,然后只需几行简单的代码即可将其作为更新后的对象从 UI 中获取回代码隐藏。

所以这是标记。首先,这是 CustomerFormView

<asp:FormView ID="frmCustomer" runat="server" DataKeyNames="CustomerID">
  <ItemTemplate>
    First Name: <asp:Label ID="lblFirstName" runat="server" 
    Text='<%# Eval("FirstName") %>'></asp:Label><br />
    Last Name: <asp:Label ID="lblLastName" runat="server" 
    Text='<%# Eval("LastName") %>'></asp:Label><br />
    Email: <asp:Label ID="lblEmail" runat="server" 
    Text='<%# Eval("Email") %>'></asp:Label><br />
    Status: <asp:Label ID="lblStatus" runat="server" 
    Text='<%# Eval("Status") %>'></asp:Label><br />    
    <asp:LinkButton ID="lnkEdit" runat="server" 
    CommandName="Edit">Edit</asp:LinkButton>
  </ItemTemplate>
  <EditItemTemplate>
    <asp:TextBox ID="txtFirstName" runat="server" 
    Text='<%# Bind("FirstName") %>'></asp:TextBox><br />
    <asp:TextBox ID="txtLastName" runat="server" 
    Text='<%# Bind("LastName") %>'></asp:TextBox><br />
    <asp:TextBox ID="txtEmail" runat="server" 
    Text='<%# Bind("Email") %>'></asp:TextBox><br />
    <asp:DropDownList ID="ddlStatus" runat="server" SelectedValue='<%# Bind("Status") %>'>
        <asp:ListItem Text="Active" Value="Active"></asp:ListItem>
        <asp:ListItem Text="Inactive" Value="Inactive"></asp:ListItem>
    </asp:DropDownList>
    <br />
    <asp:LinkButton ID="btnSave" runat="server" CommandName="Update">Update
    </asp:LinkButton>&nbsp;
    <asp:LinkButton ID="btnCancel" runat="server" CommandName="Cancel">Cancel</asp:LinkButton>
  </EditItemTemplate>
</asp:FormView>

正如您所见,这是一个非常简单且基础的 FormView,其中包含一些绑定到类属性的控件。我们有一个 ItemTemplate,还有一个 EditItemTemplate

这是地址 GridView 的标记:

<asp:GridView ID="grdAddresses" runat="server" 
         AutoGenerateColumns="False" DataKeyNames="AddressID">
    <Columns>
        <asp:BoundField DataField="AddressLine" HeaderText="Address" />
        <asp:BoundField DataField="City" HeaderText="City" />
        <asp:BoundField DataField="State" HeaderText="State" />
        <asp:BoundField DataField="ZipCode" HeaderText="Zip" />
        <asp:CommandField ShowEditButton="True" />
        <asp:CommandField ShowDeleteButton="True" />
    </Columns>
</asp:GridView>

GridViewFormView 更简单。

所以现在,这是代码隐藏:

' Declare Object Binders as Page level Variables
Dim dsCustomer As New ObjectBinder(Of Customer) ' Will be used to bind Customer
Dim dsAddress As New ObjectBinder(Of Address) ' Will be used to bind Addresses

这是我们将在 Page Init 事件中执行的操作:

Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
    If Not Page.IsPostBack Then
        ' Create a dummy Customer
        Dim c As New Customer With {.FirstName = "Razi", .LastName = "Syed", _ 
        .Email = "<a href="mailto:emailme@razisyed.com">emailme@razisyed.com", _
        .Status = "Active"}

        ' Create dummy addresses for the customer
        c.Addresses.Add(New Address With {.AddressLine = "123 Main St.", _
        .City = "Houston", .State = "TX", .ZipCode = "77001"})
        c.Addresses.Add(New Address With {.AddressLine = "987 Second St.", _
        .City = "Austin", .State = "TX", .ZipCode = "77002"})
        c.Addresses.Add(New Address With {.AddressLine = "456 Third St.", _
        .City = "Dallas", .State = "TX", .ZipCode = "77003"})

        ' The Object Binder can be initialized by setting an instance or a list
        ' Not setting an instance will basically create an empty datasource

        dsCustomer.SetInstance(c) ' Set Customer Instance (for FormView)
        dsAddress.SetList(c.Addresses) ' Set Address List (for GridView)

    End If

    ' Bind frmCustomer to Data Source (3 lines of code)
    Dim odsCustomer = dsCustomer.GetDataSource
    phDataSources.Controls.Add(odsCustomer)
    frmCustomer.DataSourceID = odsCustomer.ID

    ' Bind grdAddresses to Data Source 
    Dim odsAddresses = dsAddress.GetDataSource
    phDataSources.Controls.Add(odsAddresses)
    grdAddresses.DataSourceID = odsAddresses.ID
    
End Sub

就这样!customeraddresses 将显示给用户。如果用户使用 formviewgridview 进行编辑/插入/删除,它将自动更新对象。最棒的是,您可以按如下方式检索对象,而无需搜索控件并手动分配属性。

这是检索对象的代码:

' Get Customer Object from UI without any effort
Dim c As Customer = dsCustomer.Instance ' Get an instance (for FormView)
c.Addresses = dsAddress.List ' Get a list (for GridView)

Dim output As String = "Customer: <br>" & _
                       "First Name: " & c.FirstName & "<br>" & _
                       "Last Name: " & c.LastName & "<br>" & _
                       "Email: " & c.Email & "<br>" & _
                       "Status: " & c.Status & "<br>" & _
                       "<br>" & _
                       "Addresses:<br>"

For Each a As Address In c.Addresses
    output &= a.AddressLine & ", " & a.City & ", " & a.State & " " & a.ZipCode & "<br>"
Next

lblOutput.Text = output

关注点

最值得关注的当然是 ObjectBinder 类。代码已包含在下载中。它实际上非常简单,尤其是考虑到它完成了一项艰巨的任务!

这个类所做的是创建 ObjectDataSource 和一个用于 ListUpdateInsertDelete 的方法。它使用 .NET 泛型,允许几乎任何类与这个简单的实用程序一起工作,而不必创建一个单独的适配器类,并将其手动插入到标记中的 ObjectDataSource 中。

这为您提供了一种非常方便且易于实现 ASP.NET WebForms 中 MVVM 架构模式的方法。

清理。

ObjectBinder 使用会话来存储信息,如果不妥善清理,从长远来看可能会导致问题,因为它会留下不必要的项目在 Session 中。

要清理并从 session 中删除项目,应在 Page 的卸载方法中调用“Clear”方法。另一种方法是将类文件包含在您的 Web 应用程序项目中,并更改代码以使用 ViewState 而不是 session。我正在努力为 ObjectBinder 实现 IDisposable,以便它可以自动进行清理,但在那之前,需要手动调用“Clear”。

尽情享用!

历史

  • 2012 年 4 月 25 日:初始版本
© . All rights reserved.