ASP.NET中的双向数据绑定

时间:2011-08-12 12:24:20

标签: asp.net data-binding postback

尝试在对象列表和数据列表控件之间使用数据绑定。我想做的是

  1. 创建对象列表
  2. 将它们绑定到控件
  3. 更改用户界面中的数据
  4. 将ui中的更改绑定到对象列表
  5. 发布回来的
  6. - 拥有带有ui的新值的对象列表

  7. <body>
        <form id="form1" runat="server">
        <div>
            <asp:DataList ID="DataList1" runat="server" DataKeyField="ClassID" ViewStateMode="Enabled">
                <ItemTemplate>
                    <asp:TextBox ID="txtValue1" runat="server" Text='<%# Bind("Value1") %>'></asp:TextBox>
                    <asp:TextBox ID="txtValue2" runat="server" Text='<%# Bind("Value2") %>'></asp:TextBox>
                    <asp:TextBox ID="txtvalue3" runat="server" Text='<%# Bind("Value3") %>'></asp:TextBox>
                </ItemTemplate>
            </asp:DataList>
            <asp:Button ID="btnDoPostBack" runat="server" Text="Do Post Back" />
        </div>
        </form>
    </body>
    

    Option Explicit On
    Option Strict On
    
    Imports System.Diagnostics
    
    Partial Class _Default
        Inherits System.Web.UI.Page
    
    Dim Class1List As List(Of Class1)
    
    Protected Sub Page_PreLoad(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreLoad
        Dim txtValue1 As TextBox
        Dim txtValue2 As TextBox
        Dim txtValue3 As TextBox
        Dim ItemIndex As Integer = 0
    
        If Page.IsPostBack Then
            Class1List = CType(Session("Class1List"), List(Of Global.Class1))
            'Class1List = CType(DataList1.DataSource, List(Of Global.Class1))
            For Each myDataListItem As DataListItem In DataList1.Items
                txtValue1 = CType(myDataListItem.FindControl("txtValue1"), TextBox)
                Long.TryParse(txtValue1.Text, Class1List(ItemIndex).Value1)
    
                txtValue2 = CType(myDataListItem.FindControl("txtValue2"), TextBox)
                Integer.TryParse(txtValue2.Text, Class1List(ItemIndex).Value2)
    
                txtValue3 = CType(myDataListItem.FindControl("txtValue3"), TextBox)
                Class1List(ItemIndex).Value3 = txtValue3.Text
    
                ItemIndex += 1
            Next
        End If
    End Sub
    
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim myClass1 As Class1
    
        If Not Page.IsPostBack Then
            Class1List = New List(Of Class1)
            myClass1 = New Class1
            Class1List.Add(myClass1)
            BindData()
        Else
            'Class1List = CType(DataList1.DataSource, List(Of Global.Class1))
            Debug.WriteLine("Page_Load, Value1 = " & Class1List(0).Value1.ToString())
            Debug.WriteLine("Page_Load, Value2 = " & Class1List(0).Value2.ToString())
            Debug.WriteLine("Page_Load, Value3 = " & Class1List(0).Value3)
        End If
    End Sub
    
    Protected Sub Page_Unload(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Unload
        Session("Class1List") = Class1List
    End Sub
    
    Sub BindData()
        DataList1.DataSource = Class1List
        DataList1.DataBind()
    End Sub
    
    Protected Sub DataList1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataListItemEventArgs) Handles DataList1.ItemDataBound
        Dim myClass1 As Class1
    
        If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem Then
            myClass1 = CType(e.Item.DataItem, Class1)
            Debug.WriteLine("DataList1_ItemDataBound, Value1 = " & myClass1.Value1.ToString())
            Debug.WriteLine("DataList1_ItemDataBound, Value2 = " & myClass1.Value2.ToString())
            Debug.WriteLine("DataList1_ItemDataBound, Value3 = " & myClass1.Value3)
    
        End If
    End Sub
    
    Protected Sub btnDoPostBack_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDoPostBack.Click
        Dim myRandom As New Random
    
        Class1List(0).Value1 = myRandom.Next(100)
        Class1List(0).Value2 = myRandom.Next(100)
        Class1List(0).Value3 = myRandom.Next(100).ToString()
        Debug.WriteLine("btnDoPostBack_Click, Value1 = " & Class1List(0).Value1.ToString())
        Debug.WriteLine("btnDoPostBack_Click, Value2 = " & Class1List(0).Value2.ToString())
        Debug.WriteLine("btnDoPostBack_Click, Value3 = " & Class1List(0).Value3)
        BindData()
    End Sub
    End Class
    

    Class Class1很简单:

    Option Explicit On
    Option Strict On
    
    Imports Microsoft.VisualBasic
    
    Public Class Class1
    Private _ClassID As Long
    Private _Value1 As Long
    Private _Value2 As Integer
    Private _value3 As String = String.Empty
    
    Public Property ClassID As Long
        Get
            Return _ClassID
        End Get
        Set(ByVal value As Long)
            _ClassID = value
        End Set
    End Property
    
    Public Property Value1 As Long
        Get
            Return _Value1
        End Get
        Set(ByVal value As Long)
            _Value1 = value
        End Set
    End Property
    
    Public Property Value2 As Integer
        Get
            Return _Value2
        End Get
        Set(ByVal value As Integer)
            _Value2 = value
        End Set
    End Property
    
    Public Property Value3 As String
        Get
            Return _value3
        End Get
        Set(ByVal value As String)
            _value3 = value
        End Set
    End Property
    End Class
    

    更新:我得到了上面的代码来做我想做的事情 - 我在想有更好的方法吗?

1 个答案:

答案 0 :(得分:3)

您没有显示数据绑定“加载”阶段(将数据列表绑定到控件的代码) - 所以我假设你的部分不满意的是“保存”阶段(Page_PreLoad中的代码将修改后的值控件绑定到列表),即#4 in你的清单:

  

将ui中的更改绑定到对象列表

听起来你想要“双向数据绑定”:你希望.NET能够像模拟中读取一样轻松地更新你的模型。这是common complaint。一个解决方案是subclass WebControl,但那是一团糟。

您已使用<%# Bind("...") %>语法,因此您有正确的想法。该方法应该与<asp:SqlDataSource>开箱即用,但您想要更新自定义类,因此您需要使用<asp:ObjectDataSource>。使用this article中的方法,但使用ObjectDataSource而不是SqlDataSource。

但首先,您必须通过使用[System.ComponentModel.DataObject]标记并指定适当的更新方法,使您的模型(即Class1)与ObjectDataSource兼容:

[System.ComponentModel.DataObjectMethodAttribute(
    System.ComponentModel.DataObjectMethodType.Update, true)]
public bool UpdateProduct(string productName, ...) {
    ...
}

这将允许您在webform上使用ObjectDataSource,最后获得漂亮的双向数据绑定。阅读链接以获取完整的详细信息。

Visual Studio提供了各种笨重的自动化方式,例如TableAdapters和臭名昭着的Strongly-Typed DataSet (STD),但这些方法无法帮助像您这样拥有自己的对象模型的人。无论如何我不推荐STD。

  

我在想有更好的方法吗?

我不认为你目前的方法很糟糕。如果您担心网络表格中存在大量逻辑,那么使用MVC方法可以获得更多,而不是担心绑定糖......