Constituent Items of DataGrid

Binding Columns

In real-world scenarios, when you create columns, you need more options than auto-generation offers. Auto-generation does not let you specify the header text, nor does it provide text formatting. Perhaps the strongest reason to opt for manual binding is that auto-generation always displays all columns in the data source in the order in which they are returned.

caution

If you plan to manually bind columns to your DataGrid control, make sure you explicitly set AutoGenerateColumns to false. You can do that either declaratively or programmatically. Otherwise, the DataGrid control will place extra columns all the automatically generated columns after the last column you manually create.

You typically bind columns using the <columns> tag in the body of the <asp:datagrid> server control.

<asp:datagrid runat="server" ... >  <columns> <asp:BoundColumn runat="server" DataField="employeeid" HeaderText="ID" /> <asp:BoundColumn runat="server" DataField="firstname" HeaderText="First Name" /> <asp:BoundColumn runat="server" DataField="lastname" HeaderText="Last Name" /> </columns> </asp:datagrid>

Alternatively, you can create a new column of the desired class, fill its members, and then add the class instance to the DataGrid control s Columns collection by using the Add method. Here is some code that adds a BoundColumn class to a grid:

BoundColumn bc = new BoundColumn(); bc.DataField = "firstname"; bc.HeaderText = "First Name"; grid.Columns.Add(bc);

The order of columns in the collection determines the order in which the columns are displayed in the DataGrid control.

Bound Columns

The BoundColumn class displays in a single column the contents of a field in the data source. The structure of BoundColumn is characterized by the properties in Table 2-3.

Table 2-3 Structural Properties of the BoundColumn Class

Property

Description

DataField

The field name from the data source to which the column is bound.

DataFormatString

A string that specifies the display format for items in the column.

FooterText

The text displayed in the footer section of the column.

HeaderImageUrl

The URL of an image that will appear in the header section of the column.

HeaderText

The text displayed in the header section of the column.

ReadOnly

Indicates whether the items in the BoundColumn can be edited. If set to true, the column won t be affected by the edit mode.

SortExpression

The sort expression used when the column is selected for sorting.

All the properties listed in Table 2-3 can be declared in the ASP.NET page layout or set programmatically. The names of the class members match the <asp:BoundColumn> tag attributes.

In addition to the properties listed in Table 2-3, the BoundColumn class supports the following style properties:

  • FooterStyle Represents the style properties for the footer

  • ItemStyle Represents the style properties for all column cells

  • HeaderStyle Represents the style properties for the header

The graphical style of a column is primarily influenced by these properties. If you don t set any of them, the column will inherit the styles set at the level of the DataGrid control.

Button Columns

A button column contains a user-defined command button that corresponds to each row in the column. You specify the button caption by setting the Text property of the ButtonColumn class. Alternatively, you can bind the caption displayed in a command button to a single field in the data source by setting the DataTextField property. Clicking a command button in a column raises the ItemCommand event, which you can programmatically respond to by providing an event handler. Table 2-4 shows the key properties of the ButtonColumn class.

Table 2-4 Key Properties of the ButtonColumn Class

Property

Description

ButtonType

The type of button that will be displayed in the column. Values are defined in the ButtonColumnType enumeration: LinkButton (the default) and PushButton.

CommandName

The name of the command invoked when a user clicks a button in the column.

DataTextField

The field name from the data source to which the column is bound. If you set this property, the caption of each button will reflect the contents of the corresponding data source row.

DataTextFormatString

The display format for the caption in each command button.

FooterText

The text displayed in the footer section of the column.

HeaderImageUrl

The URL of an image that will appear in the header of the column.

HeaderText

The text displayed in the header section of the column.

SortExpression

The sort expression to use when the column is selected for sorting.

Text

The text displayed as the button caption. If you set this property, all buttons have the same text.

A button column allows you to associate an action with the items displayed in a column, but in most cases, you will want to use static text to identify the action (for example, Add, More, Remove). You can also define the button s caption to depend on the underlying data source by setting DataTextField.

The following code is a simple but realistic example of how to create and use a button column in a DataGrid control. Figure 2-2 shows the corresponding output.

<asp:DataGrid runat="server" AutoGenerateColumns="false" CellPadding="2" CellSpacing="2" GridLines="none" BorderStyle="solid" BorderColor="black" BorderWidth="1" font-size="x-small" font-names="verdana" DataKeyField="employeeid" OnItemCommand="HandleCommands"> <AlternatingItemStyle BackColor="palegoldenrod" /> <ItemStyle BackColor="beige" /> <columns> <asp:BoundColumn runat="server" DataField="employeeid" HeaderText="ID" /> <asp:BoundColumn runat="server" DataField="firstname" HeaderText="First Name" /> <asp:BoundColumn runat="server" DataField="lastname" HeaderText="Last Name" /> <asp:ButtonColumn runat="server" Text="More" CommandName="moreinfo"> <itemstyle backcolor="lightblue" font-bold="true" /> </asp:ButtonColumn> </columns> </asp:DataGrid>

Figure 2-2

A DataGrid control with a button column that can display additional information for the clicked data item.

When a user clicks a button column, to execute code in response, you must write an ItemCommand handler and link it to the DataGrid control by using the OnItemCommand attribute.

<asp:datagrid runat="server" ... OnItemCommand="ItemCommandHandler">

An ItemCommand handler requires the following prototype:

void ItemCommandHandler(Object sender, DataGridCommandEventArgs e)

The DataGridCommandEventArgs class makes available three key properties:

  • Item Represents the DataGridItem element that was clicked

  • CommandName Represents the command name associated with the clicked button

  • CommandSource Represents the button object that raised the click event

The following code shows how to retrieve and display more information about the clicked data item. The full source code for the CmdColumns.aspx application is available on the companion CD.

void HandleCommands(Object sender, DataGridCommandEventArgs e) { if (e.CommandName == "moreinfo") { int nEmpID = (int) grid.DataKeys[e.Item.ItemIndex]; SqlConnection conn = new SqlConnection(txtConn.Text); String strCmd = "SELECT * FROM Employees " + "WHERE employeeid = " + nEmpID.ToString(); SqlCommand cmd = new SqlCommand(strCmd, conn); conn.Open(); SqlDataReader dr = cmd.ExecuteReader(); dr.Read(); MoreInfo.Text = BuildMoreInfoText(dr); dr.Close(); conn.Close(); } }

The expression e.Item.ItemIndex evaluates to the ordinal position of the clicked item. As explained in Chapter 1 when we discussed DataList controls, the DataKeys array can contain a primary key value for each displayed item in the column. As the preceding code illustrates, the event handler retrieves this value and arranges a new query that requests more information for that particular row. This information is then organized into a readable format, as shown in Figure 2-3.

Figure 2-3

Clicking the More column button in this DataGrid control displays additional information about the item.

Link Columns

The HyperLinkColumn class works in much the same way as the ButtonColumn class, but HyperLinkColumn allows you to jump to a different URL within a specified frame. You set the Text property to specify the caption for the link. To specify the actual URL the user will navigate to when the link is clicked, you set the NavigateUrl property if you set Text, all links in the column will share the same caption. Alternatively, you can bind the caption and URL in the column to a field in a data source by using the property pair DataTextField and DataNavigateUrlField. Table 2-5 shows the key properties of the HyperLinkColumn class.

note

The DataTextField and Text properties are assumed to be mutually exclusive. The HyperLinkColumn class assumes that you never have both set at the same time. If you do, DataTextField takes precedence and Text will be ignored.

Table 2-5 Key Properties of the HyperLinkColumn Class

Property

Description

DataNavigateUrlField

The field name from the data source that determines the URL to jump to when a user clicks a link.

DataNavigateUrlFormatString

Specifies the display format for the URL of the links, letting you create parametric URLs.

DataTextField

The field name from the data source to which the column is bound. If you set this property, the caption of each button will reflect the contents of the corresponding data source row.

DataTextFormatString

The string that specifies the display format for the caption in each command button.

FooterText

The text displayed in the footer section of the column.

HeaderImageUrl

The URL of an image to appear in the header section of the column.

HeaderText

The text displayed in the header section of the column.

NavigateUrl

The URL to jump to when the user clicks a link in the column.

SortExpression

The string that specifies the sort expression to use when the user selects the column for sorting.

Target

The target window or frame where the linked Web page should be displayed.

Text

The text displayed as the button caption. If you set this property, all the buttons have the same text.

For link columns, the formatting capabilities provided by the DataGrid control are extremely helpful because they allow you to arrange parametric URLs. Let s alter our previous code example and point users that want to know more about a certain employee to a Web page. Instead of a button column, use the following link column:

<asp:HyperLinkColumn runat="server" DataNavigateUrlField="employeeid" DataNavigateUrlFormatString="moreinfo.aspx?id={0}" DataTextField="lastname" DataTextFormatString="More on {0}" Target="frInfo" />

In .NET, the expression {n} is used to indicate the nthargument of a series in much the same way as the old acquaintance %n is used with the function printf in plain old C programs. When used with the DataGrid control, however, the {n} expression is limited to just one argument. Thus the following assignments have only one placeholder that is silently determined by the DataGrid control:

DataNavigateUrlFormatString="moreinfo.aspx?id={0}" DataTextFormatString="More on {0}"

DataNavigateUrlFormatString replaces its {0} placeholder with the content of the field pointed to by DataNavigateUrlField. Similarly, DataTextFormatString relies on the services of DataTextField. As a result, when the user clicks the cell of the employee whose ID is 5 (this field is employeeid), the URL that is linked to this is:

moreinfo.aspx?id=5

Figure 2-4 shows an application that uses a Web page (MoreInfo.aspx) and an embedded frame to display more information about a given employee. The full source code for the Hyperlinks.aspx application is available on the companion CD.

Figure 2-4

Additional information about employees can be displayed using an <iframe> tag and link columns.

To redirect the output of the linked URL, you can use the Target property to point to a particular window, frame, or floating frame. Floating frames are a browser-specific feature. Microsoft Internet Explorer renders them by using the <iframe> tag. Netscape browsers instead rely on the <layer> tag. The preceding code uses the following tag declaration:

<iframe frameborder="no" name="frInfo"></iframe>

Notice that for the code to work, you must close the <iframe> tag in the conventional way that is, by using the closing tag </iframe>. Are you having difficulty seeing the shaded frame behind the white box in Figure 2-4? The rendering of the <iframe> tag is heavily affected by the frameborder attribute, which removes its ugly 3-D frame border, and the following CSS style:

<style> iframe { border:solid 1px black; filter:progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true'); } </style>

The filter attribute can be used to give a shadow to almost all HTML tags. It works only with Internet Explorer 5 and later versions and is happily ignored on other browsers, so using it is harmless.

note

For a page using child frames, the functionality of button and link columns is similar except when reviewing previously visited pages. If the user clicks a button column, the subsequent action is taken within the same page. If the user clicks a link column, the browser navigates to a new URL.

Programmatic Binding

The columns of a DataGrid control are stored in the Columns collection. The collection is filled out during the page initialization phase. When the OnLoad event for the page occurs, the Columns collection is ready for use. At this time, though, the only columns described in the collection are the columns declaratively linked through the <columns> ASP.NET tag. Can you bind columns programmatically? Can you show and hide columns on demand? The answer to both questions is yes.

Just as any other ASP.NET element, DataGrid s columns are also rendered through objects. To add a new column programmatically, first create a new column using one of the column classes as appropriate. For example, you can create a data bound column using this code:

BoundColumn bc = new BoundColumn(); bc.DataField = strField; bc.HeaderText = strHeader; grid.Columns.Add(bc);

Adding link or button columns is not very different from creating a data bound column except that you have to use a different column class and might need to address a different set of properties.

With programmatic binding, the rub is that the DataGrid control does not persist the information about the new, programmatically bound columns. In fact, only the columns statically linked through the <columns> tag are automatically added to the Columns collection of the DataGrid object when the page posts back to the server. To work around this issue, make sure that you programmatically add your own extra columns in the Page_Load event handler:

public void Page_Load(Object sender, EventArgs e) { if (!Page.IsPostBack) { // Execute only the first time...  } else BindColumnsProgrammatically(); }

In this way, extra columns are added each time the page is requested, ensuring the DataGrid consistency. This solution, though, does not solve the second question raised above. What happens if columns can be added on demand by clicking a button or as the result of a certain operation? In these cases, you don t have a fixed set of columns to add through a user-defined method as in the previous code snippet.

Dynamic Column Binding

When the number of extra columns cannot be predetermined, to be able to persist them across multiple page requests, you can only track the added column and where in the grid it is added. Whenever the action that adds the column occurs, you must record the action on a persistent device and have enough information to allow you to repeat the column creation the next time the page is refreshed. You could persist column information in the page global ViewState property. However, since this information is eventually serialized into the page s hidden __VIEWSTATE field, which is sent back and forth between the server page and the client browser, you might want to keep the amount of information as lean as possible to reduce the page payload. Instead of serializing each column, you could store only the information that you need to re-create the column. In the sample application, ProgBinding.aspx, I persist a string made of comma-separated numbers, each of which identifies a particular column. To restore columns, the application retrieves all the column codes from the ViewState and runs a statement like the one shown here:

switch(colCode) { case "1": AddBoundColumn("title", "Position"); break; case "2": AddBoundColumn("country", "Country"); break; case "3": AddButtonColumn("More", "moreinfo"); break; }

The full source code for the ProgBinding.aspx application is available on the companion CD. Figure 2-5 shows the dynamically displayed columns.

Figure 2-5

Columns bound programmatically are persisted across multiple page requests.

ViewState vs. Attributes

ViewState is a global, page-scoped repository of persistent information. Each ASP.NET control manages internally its own ViewState repository, which is then poured out into the global ViewState object for the page.

The control-specific ViewState property is a protected member and cannot be accessed from ASP.NET code. As a result, applications cannot store persistent information within the state of a particular control using ViewState. To persist information on a per-control basis, applications could use the control s Attributes collection. Attributes is one of the properties that controls automatically store in their own ViewState repository, so from the applications viewpoint the mechanism of persistence is exactly the same as with ViewState.

Although in practice you can interchangeably use ViewState and Attributes to persist information, they definitely have different design centers and have been introduced to serve clearly different purposes. ViewState is a collection of state values from the page and its controls. Attributes is meant to be the collection of HTML attributes for which ASP.NET controls do not provide an equivalent property. For example, you use Attributes to set the src attribute of an <iframe> tag or to assign a client-side JavaScript function to the onclick attribute of a button. All controls have (and persist) their own Attributes collection. Given its goal, the Attributes collection only accepts strings whereas ViewState can accept any valid .NET type. In addition, bear in mind that all attributes set through the Attributes collection are also written to the HTML page as custom attributes of the corresponding tags. (This is not necessarily a bad thing; just be aware of it.)



Building Web Solutions with ASP. NET and ADO. NET
Building Web Solutions with ASP.Net and ADO.NET
ISBN: 0735615780
EAN: 2147483647
Year: 2002
Pages: 75
Authors: Dino Esposito

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