2011-08-12 68 views
3

試圖在對象列表和數據列表控件之間使用數據綁定。我想要做的是ASP.NET中的雙向數據綁定

  1. 創建對象
  2. 讓他們綁定控件
  3. 變化數據在UI
  4. 有列表綁定到一個對象
  5. 名單的變化在UI
  6. 在回傳 - 有新的值對象的列表從UI

<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 

的類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 

更新:我身後上面的代碼做我想做的事情 - 我想有是更好的方法?

回答

3

你沒有展示你綁定「加載」階段(從列表控件綁定數據代碼) - 所以我假設你是不滿意的部分是「保存」階段在列表中(在Page_PreLoad代碼結合所述修改後的值控件回列表),即#4:

在綁定到對象

的列表中的用戶界面的變化

這聽起來像你想要的「雙向數據綁定」:你想要.NET的更新你的模型很容易,因爲它從你的模型中讀取。這是一個common complaint。一種解決方案是subclass WebControl,但這是一團糟。

您已經在使用<%# Bind("...") %>語法,因此您有正確的想法。該方法應該可以與<asp:SqlDataSource>,開箱即用,但您想要更新自定義類,因此您需要使用<asp:ObjectDataSource>來代替。使用this article中的方法,但使用ObjectDataSource而不是SqlDataSource。

但首先你得讓你的模型(即Class1)與[System.ComponentModel.DataObject]標記,並指定這樣適當的更新方法與ObjectDataSource控件兼容:

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

這將允許你使用一個ObjectDataSource上你的網絡表單,並最終得到很好的雙向數據綁定。閱讀鏈接瞭解全部細節。

的Visual Studio提供這種自動化的各種笨重的方式,如TableAdapters和臭名昭著的Strongly-Typed DataSet (STD),但這些並不能幫助人喜歡自己誰都有自己的對象模型。無論如何,我不推薦STD。

我在想有更好的辦法嗎?

我不認爲你目前的做法不好。如果您擔心網絡表格中有大量邏輯,您可以通過使用MVC方法獲得更多收益,而不必擔心綁定糖...

+0

感謝您的理智檢查。問題在於 - 我使用的是GridView - 客戶不得不選擇每一行,按更新一行,然後更新每行。想要所有的網格像Excel一樣打開。還發現這些數據本質上是分層的,因此它將列在列表中。所以我正在使用嵌套的DataList控件來查看我是否可以實現預期的結果。 – Bubba