Data Binding and Viewing Data Using an ObjectList Control

You can use the ObjectList ASP.NET mobile control to provide a versatile view of data. This control shows two views of your data source, a list view that shows a summary of each item, and a view that shows item details. You can explicitly define the list fields that you want to show for each item, or you can automatically generate them from the data source. By default, the control generates a field for each field in the data source, in the order it appears within the data source. The name of each automatically generated field is used as the field title.

You can bind data in an ObjectList control to a DataView or a DataSet object. To bind data in an ObjectList mobile control to a DataView object, set the DataSource property, and then call the DataBind method to perform data binding. For example, if you have a DataSet object with a table named Titles, you can use the following statements to perform data binding:

myObjectList.DataSource = ds.Tables["Titles"].DefaultView;
myObjectList.DataBind();

Alternatively, to bind data directly to a DataSet object, you must additionally set the DataMember property to the name of the table. The following example is equivalent to the previous one:

myObjectList.DataSource = ds;
myObjectList.DataMember = "Titles";
myObjectList.DataBind();

You can also set an item field to a value composed of several of the data item's properties. To do this, you can override the ItemDataBind event of the ObjectList control, and set the field programmatically. The following example sets the Summary field to a combination of the title and price of a book:

private void ObjectList_OnItemDataBind(Object sender, 
    ObjectListDataBindEventArgs e)
{
    e.ListItem["Summary"] = String.Format( String.Format ("{0} – {1}", 
        DataBinder.Eval(e.DataItem, "title"),
        DataBinder.Eval (e.DataItem, "price")));
}

In addition, you can control how each item is rendered in the list view. By default, the list view uses the first field to represent each item. However, you can set the LabelField property to any defined or automatically generated field, including one that is not visible in the details view. Using the previous example, you can use the Summary field as the label for an item, while hiding it in the details view.

Performing Data Binding Within an ObjectList

An ObjectList control shows content only if it is bound to a data source. The data source can be any object that implements the IEnumerable interface or the IListSource interface. However, each object in the data source must be of the same class, or must inherit from the same common class. When the AutoGenerateFields is set to true, the objects in the data source must be of the same class.

For each object in the data source, the ObjectList control constructs an ObjectListItem instance and stores it in its Items collection. This collection can be inspected, but not modified, by your code.

All properties that the object list refers to must be public properties of a class common to all objects in the data source. All properties that fields refer to must also be of a bindable type. Valid bindable types are String, DateTime, Decimal, and the set of primitive types.

For each object in the data source, the control performs the following data binding steps:

  1. For each field, the ObjectList control uses the field's DataField property to determine which property of the data object to look up. Each value is saved in the ObjectListItem instance as an indexed field value.

  2. After all fields are bound in this way, the control calls any ItemDataBind event handler that is defined for the ObjectList control. You can use this handler to do more complex data binding and to set values in the ObjectListItem instance.

    Note

    Some changes to an ObjectList control require you to rebind the data on that control. These changes include adding or removing fields, changing the DataField property of a field, and changing the DataFormatString property of a field.

Initiating Automatic Field Generation During Data Binding

At data binding, if the AutoGenerateFields property is set to true, the ObjectList control inspects the data source and then automatically generates fields. If the data source is a list of type ITypedList, the ObjectList control inspects the information for the type. Otherwise, the ObjectList control inspects the type information of the first object in the list.

For each bindable public property of the inspected type, the ObjectList control generates a field bound to the property. This occurs during data binding; if you make changes to a field, or add or remove fields, you must bind the properties again.

By default, automatically generated fields are visible, they use default formatting, and they have the same title as the property name. All of these values can be changed programmatically. In addition, you can specify the title of the field by adding an ObjectListTitleAttribute attribute to the property. For example, if the object has a property declared as [ObjectListTitle("Address")]myAddress, the generated field will have the title "Address."

If the ObjectList control has explicitly defined fields, auto-generated fields are added after those fields.

The following example shows how to display a list of custom objects in an ObjectList control.

<%@ Page Language="VB" 
    Inherits="System.Web.UI.MobileControls.MobilePage" %>
<%@ Register TagPrefix="mobile" 
    Namespace="System.Web.UI.MobileControls" 
    Assembly="System.Web.Mobile" %>

<script runat="server">
    Private customers(3) As Person

    Private Class Person
        Private _Name, _Nickname, _Initials As String

        Public Sub New(ByVal name As String, _
            ByVal nickname As String, _
            ByVal initials As String)

            Me._Name = name
            Me._Nickname = nickname
            Me._Initials = initials
        End Sub

        Public ReadOnly Property Name() As String
            Get
                Return _Name
            End Get
        End Property
        Public ReadOnly Property Nickname() As String
            Get
                Return _Nickname
            End Get
        End Property
        Public ReadOnly Property Initials() As String
            Get
                Return _Initials
            End Get
        End Property
    End Class

    Private Sub Page_Load(ByVal sender As Object, _
        ByVal e As System.EventArgs)

        ReDim customers(2)
        customers(0) = _
            New Person("George Washington", "George", "GW")
        customers(1) = _
            New Person("Abraham Lincoln", "Abe", "AL")
        customers(2) = _
            New Person("Theodore Roosevelt", "Teddy", "TR")

        If (Not IsPostBack) Then
            ' Bind the array to the list.
            List1.DataSource = customers
            List1.DataTextField = "Name"
            List1.DataBind()
        End If
    End Sub

    Protected Sub List1_ItemCommand( _
        ByVal sender As Object, _
        ByVal e As ListCommandEventArgs)

        ' Show the Summary text
        Dim selectedPerson As Person = _
            customers(e.ListItem.Index)
        Label1.Text = _
            String.Format("{0} (AKA {1}), initials {2}", _
            selectedPerson.Name, _
            selectedPerson.Nickname, _
            selectedPerson.Initials)

        ActiveForm = Form2
    End Sub

    Protected Sub Command1_Click(ByVal sender As Object, _
        ByVal e As EventArgs)

        Me.ActiveForm = Me.Form1
    End Sub

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<body>
    <mobile:form id="Form1" runat="server">
        <mobile:List ID="List1" Runat="server" 
            OnItemCommand="List1_ItemCommand" />
    </mobile:form>

    <mobile:Form ID="Form2" Runat="server">
        <mobile:Label ID="Label1" runat="server" />
        <mobile:Command ID="Command1" Runat="server" 
            StyleReference="subcommand" 
            OnClick="Command1_Click">
            Return</mobile:Command>
    </mobile:Form>
</body>
</html>
<%@ Page Language="C#" 
    Inherits="System.Web.UI.MobileControls.MobilePage" %>
<%@ Register TagPrefix="mobile" 
    Namespace="System.Web.UI.MobileControls" 
    Assembly="System.Web.Mobile" %>
<%@ Import Namespace="System.Collections" %>

<script runat="server">
    private ArrayList customers = new ArrayList();

    private class Person
    {
        private String _Name, _Nickname, _Initials;

        public Person(String name, String nickname, String initials)
        {
            this._Name     = name;
            this._Nickname = nickname;
            this._Initials = initials;
        }

        public String Name     { get { return _Name;     } }
        public String Nickname { get { return _Nickname; } }
        public String Initials { get { return _Initials; } }
    }

    private void Page_Load(object sender, System.EventArgs e)
    {
        customers.Add(
            new Person("George Washington", "George", "GW"));
        customers.Add(
            new Person("Abraham Lincoln", "Abe", "AL"));
        customers.Add(
            new Person("Theodore Roosevelt", "Teddy", "TR"));

        if(!IsPostBack)
        {
            // Bind the array to the list.
            List1.DataSource    = customers;
            List1.DataTextField = "Name";
            List1.DataBind();
        }
    }

    private void List1_ItemCommand(object sender, 
        ListCommandEventArgs e)
    {
        Person selectedPerson = (Person)customers[e.ListItem.Index];
        Label1.Text = String.Format("{0} (AKA {1}), initials {2}", 
            selectedPerson.Name, selectedPerson.Nickname,
            selectedPerson.Initials);

        ActiveForm = Form2;
    }

    protected void Command1_Click(object sender, EventArgs e)
    {
        this.ActiveForm = this.Form1;
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<body>
    <mobile:form id="Form1" runat="server">
        <mobile:List ID="List1" Runat="server" 
            OnItemCommand="List1_ItemCommand">
        </mobile:List>
    </mobile:form>
    <mobile:Form ID="Form2" Runat="server">
        <mobile:Label ID="Label1" runat="server" />
        <mobile:Command ID="Command1" Runat="server" 
            OnClick="Command1_Click">Return</mobile:Command>
    </mobile:Form>
</body>
</html>

Associating Commands Within an Object List

The ObjectList control allows a set of commands to be associated with an item. Each command has a Name property used to uniquely identify the command, and a Text property used to render the command.

The control provides two ways to define commands:

By default, all items in the list share the same set of commands. However, before rendering the set of commands for a given item, the control raises the ShowItemCommands event. An event handler can use this method to modify the set of visible commands for the item.

When the user selects a command, an ItemCommand event is raised, with information about the selected item and the name of the selected command.

Even if you define a default command for an item, you must include a command by the same name in the Commands collection. If the control cannot render a UI that includes a shortcut for the default command, it must display the default command as part of the set of commands.

Accessing Field Values of a List Item

When you associate an event handler with an ObjectList control, it renders list items as interactive elements. Clicking an item in a list generates an event that retrieves the appropriate action for that item. During data binding, each field is bound to its corresponding property.

To retrieve a field value from an ObjectListItem object, use the following syntax, where lstItem is an ObjectListItem instance:

lstItem[fieldName]

The following example is similar to the previous example, but uses two Command controls for each record, and uses the field syntax to retrieve field values:

<%@ Page Language="VB" 
    Inherits="System.Web.UI.MobileControls.MobilePage" %>
<%@ Register TagPrefix="mobile" 
    Namespace="System.Web.UI.MobileControls" 
    Assembly="System.Web.Mobile" %>
<%@ Import Namespace="System.Collections" %>

<script runat="server">
    Public Class Person
        ' Private Fields
        Private _Name, _Nickname, _Initials, _Wife As String

        ' Constructor
        Public Sub New(ByVal name As String, _
            ByVal nickname As String, ByVal initials As String, _
            ByVal wife As String)

            Me._Name = name
            Me._Nickname = nickname
            Me._Initials = initials
            Me._Wife = wife
        End Sub

        ' Public Properties
        Public ReadOnly Property Name()
            Get
                Return _Name
            End Get
        End Property
        Public ReadOnly Property Nickname()
            Get
                Return _Nickname
            End Get
        End Property
        Public ReadOnly Property Initials()
            Get
                Return _Initials
            End Get
        End Property
        Public ReadOnly Property Wife()
            Get
                Return _Wife
            End Get
        End Property
    End Class

    Private Sub Page_Load(ByVal sender As Object, _
        ByVal e As EventArgs)

        If Not IsPostBack Then
            ' An ArrayList for the Person objects
            Dim customers As New ArrayList()

            customers.Add( _
                New Person("George Washington", "George", _
                    "GW", "Martha"))
            customers.Add( _
                New Person("Abraham Lincoln", "Abe", _
                    "AL", "Mary"))
            customers.Add( _
                New Person("Theodore Roosevelt", "Teddy", _
                    "TR", "Alice Lee"))

            ' Bind the array to the list.
            ObjectList1.DataSource = customers
            ObjectList1.LabelField = "Name"
            ObjectList1.DataBind()
        End If
    End Sub

    Protected Sub ObjectList1_ItemCommand( _
        ByVal sender As Object, _
        ByVal e As ObjectListCommandEventArgs)

        If e.CommandName = "ShowSummary" Then
            ' Show the Summary text
            Label1.Text = _
            String.Format("{0}, AKA: '{1}', initials: '{2}'", _
                e.ListItem("Name"), e.ListItem("Nickname"), _
                e.ListItem("Initials"))
        ElseIf e.CommandName = "MoreInfo" Then
            ' Show the More Info text
            Label1.Text = String.Format("{0}'s wife was {1}", _
                e.ListItem("Nickname"), e.ListItem("Wife"))
        End If
        Me.ActiveForm = Form2
    End Sub
    Protected Sub Command1_Click(ByVal sender As Object, _
        ByVal e As EventArgs)

        ' Show the first form
        Me.ActiveForm = Form1
    End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<body>
    <mobile:form id="Form1" runat="server">
        <mobile:ObjectList ID="ObjectList1" Runat="server" 
            CommandStyle-StyleReference="subcommand"
            LabelStyle-StyleReference="title" 
            OnItemCommand="ObjectList1_ItemCommand">
            <Command Name="ShowSummary" Text="Summary" />
            <Command Name="MoreInfo" Text="More Info" />
        </mobile:ObjectList>
    </mobile:form>
    <mobile:Form ID="Form2" Runat="server">
        <mobile:Label ID="Label1" runat="server" />
        <mobile:Command ID="Command1" Runat="server" 
            OnClick="Command1_Click">Return
        </mobile:Command>
    </mobile:Form>
</body>
</html>
<%@ Page Language="C#" 
    Inherits="System.Web.UI.MobileControls.MobilePage" %>
<%@ Register TagPrefix="mobile" 
    Namespace="System.Web.UI.MobileControls" 
    Assembly="System.Web.Mobile" %>
<%@ Import Namespace="System.Collections" %>

<script runat="server">
    private class Person
    {
        // Private Fields
        private String _Name, _Nickname, _Initials, _Wife;

        // Constructor
        public Person(string name, string nickname, 
            string initials, string wife)
        {
            this._Name     = name;
            this._Nickname = nickname;
            this._Initials = initials;
            this._Wife     = wife;
        }
        // Public Properties
        public String Name     { get { return _Name;     } }
        public String Nickname { get { return _Nickname; } }
        public String Initials { get { return _Initials; } }
        public String Wife     { get { return _Wife; } }
    }

    private void Page_Load(object sender, System.EventArgs e)
    {
        if(!IsPostBack)
        {
            // An ArrayList for the Person objects
            ArrayList customers = new ArrayList();

            // Fill the Person object
            customers.Add( 
                new Person("George Washington", "George", 
                    "GW", "Martha"));
            customers.Add( 
                new Person("Abraham Lincoln", "Abe", 
                    "AL", "Mary"));
            customers.Add(
                new Person("Theodore Roosevelt", "Teddy", 
                    "TR", "Alice Lee"));

            // Bind the array to the list.
            ObjectList1.DataSource    = customers;
            ObjectList1.LabelField = "Name";
            ObjectList1.DataBind();
        }
    }

    protected void ObjectList1_ItemCommand
        (object sender, ObjectListCommandEventArgs e)
    {
        if (e.CommandName == "ShowSummary")
        {
            // Show the Summary text
            Label1.Text = 
                String.Format("{0}, AKA: '{1}', initials: '{2}'",
                    e.ListItem["Name"], e.ListItem["Nickname"], 
                    e.ListItem["Initials"]);
        }
        else if (e.CommandName == "MoreInfo")
        {
            // Show the More Info text
            Label1.Text = String.Format("{0}'s wife was {1}",
                e.ListItem["Nickname"], e.ListItem["Wife"]);
        }
        this.ActiveForm = Form2;
    }
    protected void Command1_Click(object sender, EventArgs e)
    {
        // Show the first form
        this.ActiveForm = Form1;
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<body>
    <mobile:form id="Form1" runat="server">
        <mobile:ObjectList ID="ObjectList1" Runat="server" 
            CommandStyle-StyleReference="subcommand"
            LabelStyle-StyleReference="title" 
            OnItemCommand="ObjectList1_ItemCommand">
            <Command Name="ShowSummary" Text="Summary" />
            <Command Name="MoreInfo" Text="More Info" />
        </mobile:ObjectList>
    </mobile:form>
    <mobile:Form ID="Form2" Runat="server">
        <mobile:Label ID="Label1" runat="server" />
        <mobile:Command ID="Command1" Runat="server" 
            OnClick="Command1_Click">Return
        </mobile:Command>
    </mobile:Form>

</body>
</html>

Data Binding in ObjectList Templates

In the ObjectList control, you can define templates to customize the user's experience. If you are doing inline data binding in templates, use syntax such as the following:

<%#((ObjectListItem)Container)["BookName"]%> 

You can also use the DataBinder.Eval method to bind data in all templates, as in the following example:

<%#DataBinder.Eval(((ObjectListItem)Container).DataItem,"fieldname")%>

See Also

Concepts

Accessing Data Using Listing Controls