Building Microsoft ASP.NET Applications for Mobile Devices, Second Edition [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Building Microsoft ASP.NET Applications for Mobile Devices, Second Edition [Electronic resources] - نسخه متنی

Andy Wigley; Peter Roxburgh

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
توضیحات
افزودن یادداشت جدید






Chapter 10: Advanced List Control Programming

Chapter 6. In this chapter, you'll learn about some more advanced techniques for programming list controls. You'll learn how to data-bind the list controls to a data collection, how to override methods of the list controls to change what is displayed in the list, and how to use the template features of the List and ObjectList controls to override the default rendering of these controls.


Using the Advanced Data Binding Features of the List Controls


As described in Chapter 6, the Microsoft ASP.NET mobile controls include three controls that you can use to present lists of data items: SelectionList, List, and ObjectList. In this section, you'll learn how to take advantage of the data binding capabilities of these controls.


Defining Static List and SelectionList Items


The SelectionList and List controls allow you to define items statically in the ASP.NET server control syntax, using one or more <Item> elements. Here's an example:

<Item Text="Text" Value="Value" />

The Text attribute specifies the item displayed to the user, while the Value attribute specifies a hidden associated value.

List items defined this way create entries in a System.Web.UI.MobileControls.MobileListItemCollection object. Instead of using server control syntax to define items, you can use code to add, remove, and clear items in this collection. The following code excerpt shows how to define several items in code for display in a SelectionList control; it's taken from the sample StaticListItemsFromCode in the companion material on this book's Web site.

protected void Page_Load(Object sender, EventArgs e)
{
if (!IsPostBack)
{
SelectionList1.Items.Add(
new MobileListItem("Dunes", "Posn:1 Pl:38 Pts:80"));
SelectionList1.Items.Add(
new MobileListItem("Phoenix", "Posn:2 Pl:38 Pts:70"));
SelectionList1.Items.Add(
new MobileListItem("Eagles", "Posn:3 Pl:38 Pts:69"));
SelectionList1.Items.Add(
new MobileListItem("Zodiac", "Posn:4 Pl:38 Pts:68"));
}
}

The Items property of the SelectionList and List controls exposes the MobileListItemCollection object of the list control. In code, you can access this collection, modify items, or hide individual list items by setting the Visible property of the item to false.


Binding to a Data Collection


Although static lists have their uses, invariably your applications will work with items from a data collection. With the ObjectList control, you can only bind it to a data collection as it doesn't support statically defined items.

You can bind the controls that support data binding to two types of data sources: those that implement the IEnumerable interface, and those that implement the IListSource interface. Many of the collection classes supplied in the Microsoft .NET Framework implement the IEnumerator interface and consequently can be used as a data source. Examples of collections that implement IEnumerator include Array, ArrayList, Hashtable, ListDictionary, and many of the collections associated with controls, such as MobileListItemCollection, the object the List control uses to contain MobileListItem objects (as described a moment ago).





Tip

If a class is enumerable, you can walk through it using the C# foreach statement or the Microsoft Visual Basic .NET For EachInNext statement.


You can also bind controls to collections that implement IListSource. A number of .NET classes support this interface, including DataSet and DataTable. These classes are part of the Microsoft ADO.NET architecture and represent an in-memory cache of data retrieved from a database. We'll offer a more detailed description of the DataSet class in Chapter 11, in the section "Using ADO.NET."

In the descriptions of list controls in Chapter 6, you saw many examples demonstrating the use of a .NET collection that supports IEnumerable. Listings 10-1 and 10-2, which are excerpts from the DataboundListExample contained in the companion material on this book's Web site, offer a variation on those examples. In Listing 10-1, you define the TeamStats class to use as the source data items. In Listing 10-2, the Page_Load method in the code-behind module of a mobile Web Forms page creates the TeamStats objects and inserts them into an ArrayList collection. The code then binds the List control (List1) to the collection of TeamStats objects.

Listing 10-1: TeamStats class definition






namespace MSPress.MobWeb.DBListEx
{
class TeamStats
{
private String _teamName;
private int _position, _played, _won, _drawn, _lost, _points;
public TeamStats(String teamName,
int position,
int played,
int won,
int drawn,
int lost,
int points)
{
this._teamName = teamName;
this._position = position;
this._played = played;
this._won = won;
this._drawn = drawn;
this._lost = lost;
this._points = points;
}
public String TeamName { get { return this._teamName; } }
public int Position { get { return this._position; } }
public int Played { get { return this._played; } }
public int Won { get { return this._won; } }
public int Drawn { get { return this._drawn; } }
public int Lost { get { return this._lost; } }
public int Points { get { return this._points; } }
}
}











Listing 10-2: Code-behind module binding a List control to an ArrayList collection






using System;
using System.Collections;
using System.Web.UI.MobileControls;
namespace MSPress.MobWeb.DBListEx
{
public class DataboundListExample : System.Web.UI.MobileControls.MobilePage
{
protected List List1;
override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
this.List1.ItemCommand +=
new ListCommandEventHandler(this.List1_OnItemCommand);
}
protected void Page_Load(Object sender, EventArgs e)
{
if (!IsPostBack)
{
ArrayList array = new ArrayList();
array.Add(new TeamStats("Dunes",1,38,24,8,6,80));
array.Add(new TeamStats("Phoenix",2,38,20,10,8,70));
array.Add(new TeamStats("Eagles",3,38,20,9,9,69));
array.Add(new TeamStats("Zodiac",4,38,20,8,10,68));
List1.DataSource = array;
List1.DataTextField = "TeamName";
List1.DataValueField = "Points";
List1.DataBind();
}
}
private void List1_OnItemCommand(
Object source, ListCommandEventArgs args)
{
// Display the Stats page.
this.ActiveForm = Form2;
Label1.Text = args.ListItem.Text + ": " + args.ListItem.Value;
}
}
}












Understanding Data Binding and ViewState


If you look at the code listings in this chapter, you might notice that the Page_Load method in 10-4, and 10-6 builds the data collection and data-binds the List control only if MobilePage.IsPostBack is false—in other words, only during the processing of the initial request, but not on subsequent requests in this application, as shown here:

    protected void Page_Load(Object sender, EventArgs e)
{
if (!IsPostBack)
{
ArrayList array = new ArrayList();
array.Add(new TeamStats("Dunes", "Posn:1 Pl:38 Pts:80"));
array.Add(new TeamStats("Phoenix", "Posn:2 Pl:38 Pts:70"));
array.Add(new TeamStats("Eagles", "Posn:3 Pl:38 Pts:69"));
array.Add(new TeamStats("Zodiac", "Posn:4 Pl:38 Pts:68"));
List1.DataSource = array;
List1.DataBind();
}
}

This is efficient code because the code that accesses the data (which is trivial in this example, but would likely be more complex and take longer to run in a real application) runs only on the first request. If you data-bind the control on every request, your application is performing unnecessary work. On subsequent requests, the List control "remembers" the contents of the list without having to bind to the data collection again because the Text and Value properties of the MobileListItem objects (the container objects for an item in the List control) are persisted in ViewState between requests. Similarly, with the ObjectList control, each ObjectListItem object maintains a string collection of the values of each field from the data item that will be displayed in the initial list and in the Details view. This string collection is also persisted in ViewState between requests. This process is illustrated in Figure 10-1.


Figure 10-1: Saving list control data to ViewState





Caution

You might encounter a subtle problem if you data-bind the control on every request. Remember that the client browser posts back to the server whenever the user clicks on an item in a list, clicks a button, or engages in other similar interactive operations. Perhaps your application displays a list, allowing a user to select an item, whereupon you display a new screen that displays details of the selected item. Then the user clicks a button that causes your application to display the original list once more. If you data-bind on every request and the underlying data source has been updated in the meantime, the list you display to your user the second time will change, which is not always what you intended.

Of course, this behavior might be exactly what you want, in which case you would be correct to data-bind on every request.


Using the DataItem Property to Access the Data Source


When a control is data bound, as with statically defined items, the individual list items are stored in a MobileListItemCollection object (or an ObjectListItemCollection, in the case of the ObjectList control) that's accessible through the control's Items property. However, the DataItem property of each MobileListItem in the collection is assigned a value that is a reference to the original item in the data source. This property is null if the control isn't data bound and if you have created statically defined list items.

In many applications, you do not need to access the source data item through the DataItem property after the control has been data bound. For example, the code just shown in Listing 10-2 does not make use of the DataItem property. In the Page_Load method, the DataTextField property of List1 is set to the name of the field in the data source to display in the list (TeamName) and the DataValueField is set to the name of the field that provides the hidden value (Points). Then the List1.DataBind() method is called, and the List control reads in its data from the data source. Farther down in Listing 10-2, the List1_OnItemCommand method is the ItemCommand event handler for the List control; the ListCommandEventArgs argument to this method has a ListItem property, which exposes the MobileListItem object for the selected item. As shown in Listing 10-2, this method contains the following code:

        private void List1_OnItemCommand(
Object source, ListCommandEventArgs args)
{
// Display the Stats page.
this.ActiveForm = Form2;
Label1.Text = args.ListItem.Text + ": " + args.ListItem.Value;
}

This code sets Label1.Text to a string constructed from the args.ListItem.Text and args.ListItem.Value properties of the selected item and then sets the active Form control to Form2 so that Label1 is displayed. The args.ListItem.Text property, the data that is displayed in the list, is the TeamName field from the original data source. The Value property is the Points field, as set by the DataValueField property of the List control.

If we make use of the DataItem property, we have more flexibility concerning which fields we can use from the source data item. For example, you can modify the List1_OnItemCommand method in Listing 10-2 to fetch the TeamName, Played, Points, and Position fields from the data source and to display them in a TextView control instead of a Label control with the following code:

protected void List1_OnItemCommand(Object source, 
ListCommandEventArgs args)
{
this.ActiveForm = Form2;
TextView1.Text = String.Format (
"<b>{0}</b><br/>Played : {1}<br/>Points " +
": {2}<br/>Position : {3}",
((TeamStats)(args.ListItem.DataItem)).TeamName,
((TeamStats)(args.ListItem.DataItem)).Played,
((TeamStats)(args.ListItem.DataItem)).Points,
((TeamStats)(args.ListItem.DataItem)).Position);
}


Why the DataItem Property Is Sometimes null


It's important to remember that the DataItem property is set to the source data item only during the processing of the request, when data binding of the control takes place. It's a common mistake to data-bind a control within a Page_Load method but then to place that code within an if (!IsPostBack) statement. After the initial list is sent back to the requesting browser, your application running on the server closes down and is destroyed, as usual. When the user clicks an item in the list, the client browser posts back the next HTTP request, and the ASP.NET runtime restarts your ASP.NET application on the server. Display of the list data still occurs on later requests because the Text and Value properties of each MobileListItem are persisted in ViewState, however, the DataItem property is not persisted. The list is not data bound during this request processing because IsPostBack is true. When an OnItemCommand (or other) event handler method executes, it does so during the processing of a subsequent request. On this request, the control is not data bound, so code that gets the DataItem property fails at run time because the DataItem property is null. The control must be data bound on every request for this code to work.

/ 145