Specifying a DataSource

Specifying a DataSource

When first examining the data Web controls, one might (incorrectly) assume that these controls can only render data from a traditional database, such as Oracle, Microsoft SQL Server, Microsoft Access, and so on. As we've seen thus far, the DataSource can be assigned to a DataSet object, which can not only be populated from traditional data stores, but also from well-formed XML files or strings (see the "On the Web" section at the end of this chapter for further references on binding to an XML file or string), or can be constructed by hand.

There are other objects that qualify to be assigned to a control's DataSource. Specifically, the object must implement the IEnumerable interface.

NOTE

An interface is essentially a list of empty methods. It contains no code for the methods, just the methods' declaration. An interface can be thought of as a contract: When a class implements an interface, it is guaranteeing to the world that those methods will be defined in the interface.


The IEnumerable interface defines only one method, GetEnumerator(), which returns an object that implements the IEnumerator interface. The IEnumerator interface contains one property, Current, and two methods: MoveNext() and Reset(). A class that implements the IEnumerable interface is essentially announcing that it provides a standard means for stepping through some collection of items.

Hence, any object you want to assign to a data Web control's DataSource property must implement, either directly or indirectly, the IEnumerable interface. For example, when the DataSet is bound to a data Web control, the first item in the DataSet's Tables collection is grabbed and its DefaultView property is referenced. The DefaultView property returns a DataView instance, and the DataView class implements the IEnumerable interface.

If you are thoroughly confused at this point, don't worry. For now, just rest assured that the DataSet can be assigned to the DataSource because it can be enumerated. Similarly, DataReaders (OleDbDataReader and SqlDataReader) can be assigned to a data Web control's DataSource property, as it directly implements the IEnumerable interface.

In fact, nearly all the collection classes in the System.Collections namespace implement the IEnumerable interface, meaning you can assign objects like ArrayLists, Hashtables, SortedLists, Stacks, and Queues to the DataSource property. Similarly, the Array class in the System namespace implements IEnumerable, meaning standard arrays can also be used.

To summarize, the following types of objects can be assigned to the DataSource property:

  • DataSet

  • DataReader objects (OleDbDataReader, SqlDataReader, and so on)

  • Arrays

  • The collection classes (ArrayList, Queue, Hashtable, and so on)

Of course, you can write your own classes that implement IEnumerable, or implement an interface that implements IEnumerable. In fact, we'll examine a code sample where we do just that in a bit, but first, let's look at two quick examples using a DataReader, an array, and a Hashtable.

Binding a SqlDataReader to a DataGrid

Listing 2.1 has the same output as Listing 1.1, and the DataGrid declaration is the same. The only difference is that we're populating the database data via a SqlDataReader, as opposed to using a DataSet.

Listing 2.1 Displaying Data from a SqlDataReader
  1: <%@ import Namespace="System.Data" %>   2: <%@ import Namespace="System.Data.SqlClient" %>   3: <script runat="server">   4:     Sub Page_Load(sender as Object, e as EventArgs)   5:       '1. Create a connection   6:        Const strConnString as String = "server=localhost;uid=sa;pwd=; database=pubs"   7:        Dim objConn as New SqlConnection(strConnString)   8:   9:       '2. Create a command object for the query  10:       Const strSQL as String = "SELECT * FROM authors"  11:       Dim objCmd as New SqlCommand(strSQL, objConn)  12:  13:       objConn.Open()   'Open the connection  14:  15:       'Finally, specify the DataSource and call DataBind()  16:       dgAuthors.DataSource = objCmd.ExecuteReader (CommandBehavior.CloseConnection)  17:       dgAuthors.DataBind()  18:  19:       objConn.Close()   'Close the connection  20:     End Sub  21: </script>  22:  23: <asp:datagrid  runat="server" /> 

The HTML output of the code in Listing 2.1 is identical to that in Listing 1.2. Furthermore, a screenshot of the output of Listing 2.1 can be seen back in Figure 1.1.

Binding an Array to a DataList

Recall that an array can be assigned to a data Web control's DataSource property, because the Array class implements the IEnumerable interface. This fact is quite useful, because there are many scenarios where you might have an array of information that you want to display on a Web page. In classic ASP, you would have to iterate through the array, emitting the array's contents and some HTML markup. However, with ASP.NET, you can simply bind the contents of an array to an appropriate data Web control.

Listing 2.2 illustrates the binding of a DataList to the contents of an array. Specifically, the files in a directory are displayed on an ASP.NET Web page via the Directory.GetFiles(directoryPath ) method. This method returns a string array of file names from the directory directoryPath .

Listing 2.2 You Can Bind an Array to a DataList
  1: <%@ import Namespace="System.IO" %>   2: <script runat="server">   3:   4:     Sub Page_Load(sender as Object, e as EventArgs)   5:       'Set the DataSource to a String array of file names   6:       dgFiles.DataSource = Directory.GetFiles("C:\Inetpub\wwwroot\")   7:       dgFiles.DataBind()   8:     End Sub   9:  10: </script>  11:  12: <asp:datalist  runat="server"  13:      RepeatColumns="2" CellSpacing="5">  14:   <ItemTemplate>  15:     <%# Container.DataItem %>  16:   </ItemTemplate>  17: </asp:datalist> 

Note that on line 15, where we perform our data-binding syntax in the ItemTemplate, we simply refer to Container.DataItem, rather than using the DataBinder.Eval() method. We'll examine why in more detail later on in this chapter. For now, just take notice of how an array can be assigned to the DataSource property. A screenshot of Listing 2.2, when viewed through a browser, can be seen in Figure 2.1.

Figure 2.1. A list of the files in the C:\Inetpub\wwwroot directory is listed in a two-column grid.

graphics/02fig01.gif

Binding a Hashtable to a Repeater

Collections in the Systems.Collections namespace implement the IEnumerable interface, and are therefore candidates for binding to a data Web control. In Listing 2.3, we examine the binding of a Hashtable class. Hash tables are data structures that are like arrays, but indexed by a string key rather than by a numeric index. (For this reason, hash tables are also referred to as associative arrays.)

In Listing 2.3, we create our own Hashtable object to store point values for the various cards in a card game called Crazy Eights. (See http://www.pagat.com/eights/crazy8s.html for the rules of Crazy Eights.) We'd like our Hashtable object, cardValues, to be indexed by the name of the card whose point value we're interested in. Therefore, if we wanted to see how many points a Jack was worth, we'd simply check cardValues["Jack"] (C# syntax), which would return the value 10. (We'd use cardValues("Jack") if we were using Visual Basic .NET.)

Listing 2.3 simply creates the cardValues Hashtable object (line 6) and then adds an item to the Hashtable for each card type. Finally, the Hashtable is bound to a Repeater control, which lists the cards and their associated values in a bulleted list.

Listing 2.3 A Hashtable, or any Collection that Implements IEnumerable, Can Be Bound to a Data Web Control
  1: <script runat="server" language="C#">   2:   3:   void Page_Load(Object sender, EventArgs e)    4:   {   5:     // create a Hashtable   6:     Hashtable cardValues = new Hashtable();   7:   8:     // populate the Hashtable with some values   9:     cardValues.Add("Two", 20);  10:     cardValues.Add("Three", 3);  11:     cardValues.Add("Four", 4);  12:     ... some lines removed for brevity ...  13:     cardValues.Add("King", 10);  14:     cardValues.Add("Ace", 10);  15:  16:     // bind the Hashtable to the repeater  17:     rptCardValues.DataSource = cardValues;  18:     rptCardValues.DataBind();  19:   }  20:  21: </script>  22:  23: <p>  24: Card values for Crazy Eights!  25: <asp:repeater  runat="server">  26:   <HeaderTemplate>  27:     <ul>  28:   </HeaderTemplate>  29:   <ItemTemplate>  30:     <li><%# DataBinder.Eval(Container.DataItem, "Key") %> - 31:     <%# DataBinder.Eval(Container.DataItem, "Value") %></li>  32:   </ItemTemplate>  33:   <FooterTemplate>  34:     </ul>  35:   </FooterTemplate>  36: </asp:repeater>  37: </p> 

As with Listing 2.2, in Listing 2.3 we have some potentially confusing data binding syntax in the ItemTemplate (lines 30 and 31). Here we use the DataBinder.Eval method, and in the second parameter, we have "Key" and "Value" (lines 30 and 31, respectively). Don't worry if this doesn't make sense; we'll discuss this matter thoroughly soon. Instead, focus on the fact that we could bind a Hashtable to a Repeater. Figure 2.2 shows a screenshot of Listing 2.3 when viewed through a browser. One interesting thing to note is that the cards and their associated values in the screenshot are not in the same order as they were added to the Hashtable in the code (lines 9 through 14). This is because of the internal storage semantics of the Hashtable class the items are not necessarily stored in the order in which they were entered. Consult the .NET Framework documentation on the Hashtable class for more information about the algorithms used to store items in a Hashtable. (There's also a direct link to the online documentation for the Hashtable class in the "On the Web" section at the end of this chapter.)

Figure 2.2. A bulleted list of the cards and their associated values.

graphics/02fig02.gif

At this point, we've looked at assigning four different types of objects to the DataSource property: a DataSet, a SqlDataRepeater, an array, and a Hashtable. Essentially, we can assign any object that implements the IEnumerable interface to the DataSource property. In fact, in a later section in this chapter, "Building a Class That Implements IEnumerable," we'll examine how to construct our own class that can be assigned to a data Web control's DataSource property.

Before we do that, though, let's turn our attention to the DataBind() method and examine what's happening behind the scenes. This next section examines why, among other things, why the data-binding syntax was the way it was for the ItemTemplates in Listings 2.2 and 2.3 (refer back to line 15 and lines 30 and 31 in Listings 2.2 and 2.3, respectively). Personally, I think the next section is important and worth reading for a deeper understanding of the low-level details of the data Web controls; however, a thorough understanding is not necessary. If you need to skip the next section, or don't fully understand it or its concepts, don't worry! You can continue working through the rest of the book.



ASP. NET Data Web Controls Kick Start
ASP.NET Data Web Controls Kick Start
ISBN: 0672325012
EAN: 2147483647
Year: 2002
Pages: 111

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net