3

Trying to use data binding between a list of objects and a data list control. What I want to do are

  1. create the list of objects
  2. have them bound to the controls
  3. change data in the UI
  4. have the changes in the ui bound to the list of objects
  5. on post back - have the list of objects with the new values from the 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 

The Class Class1 is trivial:

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 

Update: I got the code behind above to do what I want it to do - I was thinking there was a better way?

1 Answer 1

3

You didn't show your databinding "Load" phase (the code which binds the data from the list to the controls)--so I assume the part you are unhappy with is the "Save" phase (the code in Page_PreLoad which binds the modified values from the controls back to the list), i.e. #4 in your list:

have the changes in the ui bound to the list of objects

It sounds like you want "two-way Data Binding": you want .NET to update your model as easily as it reads from your model. This is a common complaint. One solution is to subclass WebControl, but that's a mess.

You are already using the <%# Bind("...") %> syntax, so you have the right idea. That approach should work out-of-the-box with <asp:SqlDataSource>, but you want to update a custom class, so you need to use <asp:ObjectDataSource> instead. Use the approach in this article, except with ObjectDataSource instead of SqlDataSource.

But first you have to make your model (i.e., Class1) compatible with ObjectDataSource by marking it with [System.ComponentModel.DataObject] and designating the appropriate update method like this:

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

This would allow you to use an ObjectDataSource on your webform and finally get nice 2-way databinding. Read the links to for full details.

Visual Studio offers various clunky ways of automating this, such as TableAdapters and the infamous Strongly-Typed DataSet (STD), but those don't help people like yourself who have their own object model. I don't recommend STDs anyway.

I was thinking there was a better way?

I don't think your current approach is bad. If you're worried about having tons of logic in your webforms, you would gain much more by using an MVC approach than worrying about binding sugar...

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the sanity check. What the problem is - I was using GridView - customer balked at having to select each row, press update for one one row, and then update for each row. Wants all of the grid open like Excel. Also found that the data is hierarchical in nature so it will be list in list in list. So I am playing with nested DataList controls to see if I can achieve desired results.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.