1. Trang chủ
  2. » Công Nghệ Thông Tin

Professional ASP.NET 1.0 Special Edition- P12 doc

40 140 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Professional ASP.NET 1.0 Special Edition
Trường học Standard University
Chuyên ngành Computer Science
Thể loại Thesis
Năm xuất bản 2001
Thành phố New York
Định dạng
Số trang 40
Dung lượng 1,14 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

The only other control is the Label named lblInfo that we use to display information about each book in the table: Binding the DataGrid The code in this page is divided into three

Trang 1

'Release Date' Column:

<ASP:RadioButton id="chkVisible" GroupName="Col2Visible" runat="server"

AutoPostback="True" /> Visible &nbsp;

<ASP:RadioButton id="chkNotVisible" GroupName="Col2Visible" runat="server"

Trang 2

<ASP:TemplateColumn HeaderText="" ItemStyle-BackColor="silver">

Trang 3

is "Info" We'll see how we use this when we look at the code in the page shortly

The only other control is the Label named lblInfo that we use to display information about each book in the table:

<ASP:Label id="lblInfo" runat="server" />

</form>

Binding the DataGrid

The code in this page is divided into three subroutines:

ƒ Page_Load is executed each time the page is loaded It sets the visibility of the Released column and then calls the BindDataGrid routine

ƒ BindDataGrid fetches the data from the database and returns it as a DataReader object Then it binds this

to the DataGrid control to display the values

ƒ ShowInfo runs when any of the command buttons in the grid is clicked It retrieves the ISBN and title of the book from the row and displays it in the Label control at the foot of the page

Showing and Hiding Columns

When we click the relevant radio button at the top of the page, the Released column is hidden or shown in the grid Compare this next screenshot with the previous one to see the difference:

Trang 4

The radio buttons have their AutoPostback property set to True so that the page is reloaded each time the selection is changed In the Page_Load event, we check to see if this is the first time the page has been loaded If not (that is, if it's

a postback) we just set the Visible property of the appropriate column using its index within the Columns collection of the DataGrid control If it's not a postback, we have to set the default value for the radio buttons and bind the grid to the data source In this case, the Released column will be displayed, because the default is to show all columns:

Sub Page_Load()

If Page.IsPostBack Then

'display or hide the "Released" column

'have to use the index of the column not the column name

MyDataGrid.Columns(3).Visible = (chkVisible.Checked = True)

Else

chkVisible.Checked = True 'set default value

Trang 5

BindDataGrid() 'create dataset and bind grid

End If

End Sub

Reacting to the ItemCommand Event

The other interesting feature of the example page is how it displays information about each book in response to a click on the More Info button In the definition of the DataGrid control, we specified the name of an event handler for the ItemCommand event by setting the OnItemCommand property of the DataGrid:

OnItemCommand="ShowInfo"

When any control within the grid is activated - in our case the ASP:Button control with the caption More Info - this event handler is executed The parameters sent to the event handler contain a reference to the control that initiated the event, and a DataGridCommandEventArgs object that contains details of the event as well as references to the current row in the control (the row containing the control that was activated)

Within our event handler, we access the CommandName of the CommandSource object (our More Info button) to see which control it was that activated the event (there could be more than one in each row) Our button has a CommandNameproperty value of Info, so we can choose the action to take based on this:

Sub ShowInfo(objSender As Object, objArgs As DataGridCommandEventArgs)

'runs when any command button in the grid is clicked

'see if the CommandName of the clicked button was "Info"

If objArgs.CommandSource.CommandName = "Info" Then

Trang 6

zero), and get the value from the Text property Then we can use these values to create the output and place it in the Label control located below the grid on our page:

'get values of ISBN and Title from Text property of the table cells

'for the current row returned in the objArgs parameter values

Dim strISBN As String = objArgs.Item.Cells(1).Text

Dim strTitle As String = objArgs.Item.Cells(2).Text

'display the information in the page- possibly extract from database?

lblInfo.Text = "More information about the book:<br /><b>" & strTitle _

& "</b><br />(ISBN " &strISBN & ") goes here "

End If

End Sub

Using this technique we could extract the ISBN and use it to look up information about the book in another table Or we could even use it to access another web site or a Web Service to get information to display to the user

Handling Data Binding Events

The content of each cell or item in a list control is created as that control is being executed, as part of the overall page creation process This means that the content of each cell is controlled only by the value in the data source and the formatting applied by the template or style properties in the control definition However, it's often useful to be able to access and modify the content at runtime, based on the actual value that occurs in the source dataset

We can do this by reacting to events that the control raises The most useful in this scenario is the DataBinding event, which occurs after the values for the column have been determined, but before they are output to the client This event

is supported in all the list controls designed for data binding, including the ASP:DataGrid, ASP:DataList,

ASP:Repeater, and HtmlSelect controls

In essence we just have to create a handler for the event, and tell the control where to find this event handler It is then

Trang 7

called for each row in the data source as the binding takes place Within the event handler, we can access the entire row

of data, and modify the content of any of the controls within that row

The example page Handling Data Binding Events in a DataList Object (datalist-bind-events.aspx) demonstrates this technique by adding the slogan "Great for ASP Programmers!" to any book title that contains the words "Active Server Pages" or "ADO":

How It Works

The definition of the DataList control we use in this example is much the same as in previous examples We have

<HeaderTemplate>, <ItemTemplate>, and <FooterTemplate> elements along with some CSS styles to specify how to format the output from the control What's important here is that we also set the OnItemDataBound property of the DataList object to the name of an event handler that we want to be executed as each row in the list is bound to the data source:

<ASP:DataList id="MyDataList" runat="server" RepeatLayout="Table"

OnItemDataBound="CheckTitle">

</ASP:DataList>

Trang 8

We use the same Page_Load event handler as in previous examples to get a DataView object that contains our source data from the separate custom user control, and bind it to the grid for display What makes this example different is the event handler that we have specified for the ItemDataBound event

Reacting to the ItemDataBound Event

Our event handler, named CheckTitle, is shown next When it's called by the control, as each row is bound to the source data, it is passed two parameters The first is the usual reference to the object that caused the event, and the second is

a DataListItemEventArgs object that contains information about the event, and the row that was being bound

The first thing we do in our event handler is to check what type of row was being bound - whether it's a header row, footer row, item row, alternating item row, and so on (the type of template used to create the row determines this) We're only interested in item and alternating item rows We obtain the row type from the ItemType property of the current row in the DataListItemEventArgs object:

Sub CheckTitle(objSender As Object, objArgs As DataListItemEventArgs)

'see what type of row (header, footer, item, etc.) caused the event

Dim objItemType As ListItemType = CType(objArgs.Item.ItemType, ListItemType)

'only format the results if it's an Item or AlternatingItem event

'objArgs.Item.DataItem returns the data for this row of items

Trang 9

Dim objRowVals As DataRowView = CType(objArgs.Item.DataItem, DataRowView)

'get the value of the Title column

Dim strTitle As String = objRowVals("Title")

Now we can test the value to see if it's one that we want to modify We're looking for book titles that contain the words

"Active Server Pages" or "ADO" If we find one that matches, we use the FindControl method of the row to get a reference to the control with an ID value of TitleLabel This is the control that we bound to the Title column within the definition of the DataList control earlier in our page Once we get our reference to this control, we can append the extra text (Great for ASP Programmers!), putting it in a <span> element that specifies the large red font style:

If strTitle.IndexOf("Active Server Pages") >= 0 _

Or strTitle.IndexOf("ADO") >= 0 Then

'get a reference to the "Title" ASP:Label control in this row

Dim objLabel As Label = _

CType(objArgs.Item.FindControl("TitleLabel"), Label)

'add a message to this Label control

objLabel.Text += " &nbsp; <span class='bigRed'>" _

& "Great for ASP Programmers!</span>"

Trang 10

current values of the data - something we can't always do by hard-coding logic into the page

This technique isn't limited to just adding text to a Label control We could place other controls (such as <img> elements)

in the output of a DataList that are not visible, and then change their properties in the ItemDataBound event handler based on the values in the bound data Or we could just change the formatting of existing bound content based on the current value The possibilities are almost endless

Sorting and Filtering Rows in a DataGrid

When we need to display more than a few rows of data, it's helpful for users to be able to sort the rows based on values

in a specific column, and filter the rows based on the values in any column Both techniques make it much easier for users

to find what they are looking for It means extra round-trips to the server using the current generation of controls, but it's

a useful feature to add to your applications nonetheless

We can provide both these facilities easily when using a DataGrid control The DataGrid can do most of the work required to provide a "sort by column" facility And if the data source for the control is a DataView object, we can take advantage of the sorting and filtering features that it includes:

ƒ To sort the rows within a DataView, we just have to set the Sort property to a string containing the name of the column, and optionally the keyword DESC to sort in descending order We can sort by more than one column

by separating the column names with a comma

ƒ To filter the rows that appear in the DataView, we set the RowFilter property to an expression that specifies the rows to be displayed A simple example is "TitleLIKE'ASP'" More details on the Sort and RowFilterproperties are provided in the upcoming data access chapters

The big advantage in using a DataGrid control is that it has a property named AllowSorting, and it exposes an event named SortCommand When we set the AllowSorting property to True (usually done within the definition of the control), each column heading automatically becomes a hyperlink When these are clicked, a postback occurs and the event handler specified for the SortCommand property is executed

You can see the way that we implement both sorting and filtering in the example page Sorting Rows and Finding Data in

a DataGrid Control ( sort-find-datagrid.aspx):

Trang 11

How It Works

The HTML section of this page contains the textbox and button used to filter the rows based on the title of the book These controls are followed by the definition of the DataGrid that we use to display the matching titles:

<form runat="server">

Select only Titles containing the text:

<ASP:TextBox id="txtFindText" runat="server" />

<ASP:Button id="cmdFind" Text="Find" runat="server" /><p />

<ASP:DataGrid id="MyDataGrid" runat="server"

EnableViewState="False"

CellPadding="5"

GridLines="None"

Trang 12

of the column names is clicked

The code section of the page contains three subroutines As well as the Page_Load event handler, we have a

BindDataGrid routine that is responsible for fetching the data sorted and filtered as required The third routine, named SortRows, is executed when the column headings are clicked You can see that it is attached to the DataGrid in the previous code listing as the OnSortCommand property The page also defines two global (Page-level) variables that will hold the current sort order and filter expression:

Dim gstrSortOrder As String 'to hold the sort order

Dim gstrFindText As String 'to hold the filter expression

Binding the DataGrid

The first of the subroutines, named BindDataGrid, uses the same custom user control as some of the earlier examples

to fetch a DataView object containing some book details from our data store It then binds this DataView to our DataGrid control However, it has a couple of other tasks to perform as well It uses the two global variables to set the sort order of the rows in the DataView (by setting the Sort property) and it applies a filter to the rows to control which ones will be displayed (by setting the RowFilter property):

Trang 13

The Page_Load Event Handler

The second subroutine is the Page_Load event handler This is executed when the page first loads, when the user clicks

a column heading to change the sort order, or clicks the Find button to filter the rows that are displayed In the event handler, if this is a postback, we change the global filter expression variable to reflect the value in the textbox If it's the first time that the page has been loaded, we set default values for the textbox and the global string that specifies the sort order of the rows

The result is that we start out with the value "ASP" in the textbox when we first load the page, and from then on the global string variable will always hold the expression used to filter the rows We also call our BindDataGrid subroutine (the one

we just examined) each time the page is loaded, so that the DataView object and the grid are recreated with the current sort order and row filter:

Trang 14

Sub Page_Load()

If Page.IsPostBack Then

'set the value to be used for the RowFilter on the DataView

gstrFindText = "Title LIKE '*" & txtFindText.Text & "*'"

Sorting the Rows in the DataGrid

When our page is first loaded, the Page_Load event handler sets the Page-level variable holding the sort order to the value "ISBN", so the rows will be sorted in the order of the ISBN column values But how do we change the sort order? Easy - the DataGrid control raises the SortCommand event whenever the user clicks on a column heading LinkButton

We specified our subroutine named SortRows as the handler for this event:

Sub SortRows(objSender As Object, objArgs As DataGridSortCommandEventArgs)

'runs when the column headings in the DataGrid are clicked

Trang 15

'get the sort expression (name of the column heading that was clicked)

Controlling the Size of the Viewstate

One issue that we really must be aware of when using the ASP.NET list controls is the effect that they have on the amount

of data being transmitted across the wire- with each postback and with each newly generated page As we briefly discussed in the previous chapter, an ASP.NET page containing a server-side <form> control automatically generates ViewState This is an encoded representation of all the values in all the controls on the page, and it is persisted across page loads using a HIDDEN-type <input> control If you view the source of the page in your browser, you'll see something like this:

<form name="ctrl0" method="post" action="mypage.aspx" id="ctrl0">

<input type="hidden" name=" VIEWSTATE" value="dDwxOTAwNDM2ODc1Ozs+" />

If we place a list control on a page and fill it with data, all that data is encoded into the ViewState and passed across the wire with each page load and postback In fact, it's even worse than that because, when the user loads the page, we're actually sending all the values twice - once as the visible output of the list control and once as the content of the ViewState

Of course, we might want this to occur as a feature of the way that the page works If we create the output for the list control and bind it only during the first page load (and not during each postback) we depend on the ViewState to maintain

Trang 16

the values in the list control If getting the values from the data source is an expensive process in terms of resources or time, then persisting them in the ViewState is a good idea

However, if we are limited in bandwidth, or perhaps serving devices such as mobile phones that can't cope with large volumes of form content, then we might instead decide to recreate the values on each postback, and not include them in the ViewState Bear in mind that this option requires a deliberate decision - if we take no action then the values will be included in the ViewState

Persisting List Control Values Automatically Across Postbacks

If we are persisting values across postbacks, we can use the IsPostback property of the Page object so that the values are only created when the page is being executed for the first time For example:

Sub Page_Load()

If Not Page.IsPostback Then

objDataView = GetDataView( ) 'get or build a DataView object

MyDataGrid.DataSource = objDataView 'specify the data source

MyDataGrid.DataBind() 'bind data to grid control

End If

End Sub

Now, when the page is reloaded, the values that are automatically included in the ViewState will be used to populate the control

Preventing List Control Values from Being Persisted Across Postbacks

There are occasions when we don't want to persist the values in a list control across postbacks As well as the concern over bandwidth, we might have other reasons for recreating the data set or rebinding the list control each time we load the page The simplest scenario is when the page does not actually include a <form> element Many of our previous examples were like this They are not interactive pages, and so there is no requirement to post values back to the server - we just load the page and view it In this case, there is no ViewState, but no user interaction either

Trang 17

However, if the page does contain a <form> section, the values from the list control are automatically included in the ViewState If the list control contains any interactive elements (such as buttons or edit controls where the value must be posted back to the server) the control has to be on an HTML <form> This is the case with the sorting and filtering example we've just been looking at, in which the column headings are automatically rendered as LinkButton controls

However, to sort and filter the rows, we have to rebind the data grid to the DataView object each time We're actually recreating the whole DataSet and DataView with each postback, so we have no need to maintain the values in the ViewState For this reason, we set the EnableViewState property of the DataGrid object to False in the control definition so that the contents of this control are not included in the ViewState:

<ASP:DataGrid id="MyDataGrid" runat="server"

EnableViewState="False"

We can always check how much data is included in the ViewState of a page by using page tracing In the Page directive, add Trace="True":

<%@Page Language="VB" Trace="True"%>

Then run the page locally (remove in a browser running on the web server itself) In the Control Tree section of the output

in our example below, you can see that the total size of the DataGrid control named MyDataGrid - including children -

is 1119 bytes The <form> itself (given the name ctrl0 because we didn't specify a name for it) shows the size of the entire ViewState is 1867 bytes:

Trang 18

Of course, the other way to see how much ViewState is in a page is just to view the source in the browser so that you can see the HIDDEN-type <input> control From that you can get a good idea of the amount of data being sent to the client each time

Automatic Paging in a DataGrid

Our final example of using the DataGrid control just to display data demonstrates the use of paging When there are a large number of rows to display, sending them all to the client in one go doesn't make sense The user will get impatient waiting for them all to arrive, and may find that they actually wanted to see something else instead To prevent this aggravation and waste of bandwidth, it is usual to divide the output into pages containing 10 or 20 rows (depending on the content), and then provide navigation controls so that users can view other pages of rows as required

The DataGrid control makes it easy to provide a paging feature It contains logic that can automatically create pages containing the number of rows we require, and it can render the navigation controls in a range of ways We can also take over paging entirely and implement all the features ourselves in order to provide a custom interface

To turn on the automatic paging feature, we simply need to set the AllowPaging property of the DataGrid control to True, and specify the name of an event handler that will run when the PageIndexChanged event occurs We usually set these properties when we define the control in the HTML of the page We can also specify the position of the "Pager" navigation controls By default they are located in the footer row of the grid, aligned on the left

Our example that uses the automatic paging feature is Using Automatic Paging with a DataGrid Control

Trang 19

(paging-datagrid.aspx) This example also contains controls that can be used to specify other properties of the paging feature For example we can specify the number of rows in each page, and the style of the navigation controls After changing any of the property values, just click on one of the navigation links to reload the page with the new options set:

How It Works

As usual, the HTML section of our page starts with the controls where we can specify how the DataGrid behaves:

<form runat="server">

'Previous' Link Text:

<ASP:TextBox id="PrevText" runat="server" /> &nbsp;

'Next' Link Text:

<ASP:TextBox id="NextText" runat="server" /><br />

Paging Style:

Trang 20

<ASP:RadioButton id="PageNumeric" GroupName="Style"

runat="server" /> Numeric &nbsp;

<ASP:RadioButton id="PageText" GroupName="Style"

runat="server" /> Text<br />

Number of rows per Page:

<ASP:TextBox id="PageRows" runat="server" /><p />

This is followed by the definition of the DataGrid control We set the three properties that control the paging behavior:

we set AllowPaging to True, specify that the paging controls should be right-aligned within the footer row, and specify that the event handler named ChangeGridPage (which we'll look at shortly) will be executed when the user selects a page using the paging controls:

<ASP:DataGrid id="MyDataGrid" runat="server"

The Page_Load Event Handler

When the page loads each time, either when the user opens the page for the first time or in response to a click by the user

on the paging controls, our Page_Load event handler is executed However, we only want to execute code when the page

is first opened so we check the value of the IsPostback property first If it's False, we can set the default values for the controls in the page, and then call the BindDataGrid subroutine to bind and display the source data values in the

Ngày đăng: 03/07/2014, 07:20

TỪ KHÓA LIÊN QUAN