The DetailsView Control

The GridView control we examined in the previous section is designed to display data as a table, with each row containing one data row (one record). However, sometimes it's useful to be able to display data one row at a time, especially when there is a large number of columns or when you want to be able to edit the values of each column without using the rather cramped in-line editing mode of the GridView .

To provide a one-row-per-page feature for displaying and editing data, ASP.NET 2.0 includes the new DetailsView control. It can be used stand-alone with paging controls that allow the user to scroll through the rows or combined with a GridView control to provide a master-detail display. In fact, you have already seen DetailsView -like rendering in action in the previous section of this chapter. When serving a page containing a GridView to a small-screen or mobile device, ASP.NET automatically uses DetailsView -like rendering to create the details page containing all the columns from the current row.

Using a Stand-Alone DetailsView Control

The declaration and attribute set for the DetailsView control is similar to that of the GridView . When used on its own, however, you will need to either enable the paging feature in order to display the paging controls or add your own custom paging feature so that users can navigate through the rows.

Listing 4.21 shows a declaration of a DetailsView control that turns on the paging features and specifies that the mode should be NextPrevFirstLast so that the usual four links are displayed (the default mode is Numeric , where a numbered link is displayed for each row). The declaration also specifies the relative URLs of the images to display for the paging controls and the text to use as the alt attribute of each one.

Listing 4.21 Declaring a DetailsView Control
 <asp:DetailsView id="details1" DataSourceID="dvs1" runat="server"   DataKeyNames="ShipperID" AllowPaging="True"   PagerSettings-Mode="NextPrevFirstLast"   PagerSettings-FirstPageImageUrl="f.gif"   PagerSettings-FirstPageText="First Row"   PagerSettings-PrevPageImageUrl="p.gif"   PagerSettings-PrevPageText="Previous Row"   PagerSettings-NextPageImageUrl="n.gif"   PagerSettings-NextPageText="Next Row"   PagerSettings-LastPageImageUrl="l.gif"   PagerSettings-LastPageText="Last Row" /> <asp:SqlDataSource id="dvs1" runat="server"   ConnectionString="server=localhost;database=Northwind;uid=x;pwd=x"   SelectCommand="SELECT ShipperID,CompanyName,Phone FROM Shippers"> </asp:SqlDataSource> 

After the DetailsView control comes the declaration of the data source control. You can see that this is identical to the way it is used with a GridView control. The result is shown in the compound screenshot in Figure 4.6, with the paging controls and the alternate text captions visible.

Figure 4.6. Navigating rows in a DetailsView control

graphics/04fig06.gif

The DetailsView control accepts the same styling attributes as the GridView control, so you can improve the appearance from the default shown here. You can also turn off automatic generation of the fields (by setting the AutoGenerateRows attribute to False ) and then specify the fields you want to display as well as their appearance and behavior. The DetailsView control uses a <RowFields> section in place of the <ColumnFields> section of the GridView control, but the same types of fields are used within it as in the GridView . You can declare your own sequence of BoundField , ButtonField , CheckBoxField , HyperLinkField , TemplateField , and CommandField controls within the <RowFields> section.

Creating a Master-Detail Page with GridView and DetailsView Controls

For rowsets that have a large number of columns, the one-row-per-page approach provided by the DetailsView control is useful. However, it does make it harder to navigate through and generally scan the data by eye. For that, the table layout provided by the GridView control is better. The ideal is to combine the two so that a few selected columns are displayed in the GridView , and the user can select a row to see it displayed with all the fields visible in the DetailsView .

The two controls provide features that link them together declaratively , without requiring any code to be written. Listing 4.22 shows how this works. In this example, the GridView is bound to a data source control named dgs1 , and the DataKeyNames attribute specifies that the ShipperID column in the rowset exposed by that data source control is the primary key for each row. The AutoGenerateSelectButton attribute is set to True to display a Select link in each row, and the first row is selected when the page first loads. This is necessary because the DetailsView must have a current row to display.

Listing 4.22 Master-Detail Pages: The GridView and SqlDataSource Controls
 <asp:GridView id="grid1" DataSourceID="dgs1" runat="server"      DataKeyNames="ShipperID" SelectedIndex="0"      AutoGenerateSelectButton="True" /> <asp:SqlDataSource id="dgs1" runat="server"   ConnectionString="server=localhost;database=Northwind;uid=x;pwd=x"   SelectCommand="SELECT ShipperID,CompanyName,Phone FROM Shippers" /> ... 
Linking a GridView and DetailsView Control

The DetailsView control is declared next (see Listing 4.23). It is bound to the second data source control on the page, named dvs1 , and again has the primary key column identified by the DataKeyNames attribute. The data source control has the same SelectCommand as the previous one, though it doesn't have toif you display a different selection of columns in the two controls, you can select just the columns you need.

The link between the two data source controls, which ensures that the row selected in the GridView is displayed in the DetailsView control, is the addition of a filter to the second data source control. The FilterExpression declares a parameter @ShipperID , and the FilterParameters section of the control contains a ControlParameter that is bound to the SelectedValue property of the GridView control. As the user selects rows in the GridView control, the SelectedValue is automatically set to the ID of that row and thus filters the data source control that powers the DetailsView control on that ID value.

Listing 4.23 Master-Detail Pages: The DetailsView and Filtered SqlDataSource Controls
 ... <asp:DetailsView id="details1" DataSourceID="dvs1" runat="server"      DataKeyNames="ShipperID" /> <asp:SqlDataSource id="dvs1" runat="server"   ConnectionString="server=localhost;database=Northwind;uid=x;pwd=x"   SelectCommand="SELECT ShipperID,CompanyName,Phone FROM Shippers"   FilterExpression="ShipperID=@ShipperID">   <FilterParameters>     <asp:ControlParameter Name="ShipperID" ControlID="grid1"                           PropertyName="SelectedValue" />   </FilterParameters> </asp:SqlDataSource> 

The result can be seen in Figure 4.7. A Select link appears in each row of the GridView control, and clicking one displays that row in the DetailsView control below it.

Figure 4.7. Selecting a row in a master-detail page

graphics/04fig07.gif

Inserting and Editing Rows with a DetailsView Control

A task that is regularly required when working with data rows, and which is quite complex to achieve in ASP.NET 1.0, is inserting a new row into the source data table. In ASP.NET 2.0, with a GridView control, this can be achieved by using a DetailsView control instance declared separately on the page. The technique is very similar to that just seen for creating a master-detail page. First, a GridView control is declared and then the associated data source control that supplies the rows (see Listing 4.24).

Listing 4.24 Inserting and Editing Rows: The GridView and SqlDataSource Controls for Lookups
 <asp:GridView id="grid1" DataSourceID="dgs1" runat="server"   DataKeyNames="ShipperID" SelectedIndex="0"   AutoGenerateSelectButton="True" /> <asp:SqlDataSource id="dgs1" runat="server"  ConnectionString="server=localhost;database=Northwind;uid=x;pwd=x"  SelectCommand="SELECT ShipperID,CompanyName,Phone FROM Shippers" /> ... 
Enabling Editing in a DetailsView Control

To enable row edits, row deletes, and/or row inserts in a DetailsView control, you just add the relevant attributes to the control declaration. The first four highlighted attributes in Listing 4.25 turn on display of the Insert, Edit, Delete, and Cancel links, respectively (the Update link always appears when editing is enabled). For the automatic no-code updates to work, you also have to provide the relevant SQL statements or stored procedures. The highlighted attributes for the data source control in Listing 4.25 show the UPDATE , DELETE , and INSERT statements that will push changes to the rows back into the database.

Listing 4.25 Inserting and Editing Rows: The DetailsView and SqlDataSource Controls for Edits
 ... <asp:DetailsView id="details1" DataSourceID="dvs1" runat="server"      DataKeyNames="ShipperID"  AutoGenerateInsertButton="True" AutoGenerateEditButton="True"   AutoGenerateDeleteButton="True" AutoGenerateCancelButton="True"  OnItemDeleting="CheckDelete" OnItemUpdated="UpdateGrid"      OnItemInserted="UpdateGrid" OnItemDeleted="UpdateGrid" /> <asp:SqlDataSource id="dvs1" runat="server"   ConnectionString="server=localhost;database=Northwind;uid=x;pwd=x"   SelectCommand="SELECT ShipperID,CompanyName,Phone FROM Shippers"  UpdateCommand="UPDATE Shippers SET CompanyName=@CompanyName,   Phone=@Phone WHERE ShipperID=@ShipperID"   DeleteCommand="DELETE FROM Shippers WHERE ShipperID=@ShipperID"   InsertCommand="INSERT INTO Shippers (CompanyName, Phone)   VALUES (@CompanyName, @Phone)"  FilterExpression="ShipperID=@ShipperID" >   <FilterParameters>     <asp:ControlParameter Name="ShipperID" ControlID="grid1"                           PropertyName="SelectedValue" />   </FilterParameters> </asp:SqlDataSource> <asp:Label id="lblError" EnableviewState="False" runat="server" /> 

The screenshot in Figure 4.8 shows two views of the process of editing a row. The DetailsView displays the Edit, Delete, and New links. Clicking the Edit link switches the DetailsView into edit mode, and the values of the non-key fields can be edited.

Figure 4.8. Editing a row with a DetailsView control

graphics/04fig08.gif

It's also possible to insert a row by clicking the New link, entering the values, and then clicking the Insert link (see Figure 4.9). Notice that the primary key is displayed as a text box so that the user can enter an appropriate value.

Figure 4.9. Inserting a row with a DetailsView control

graphics/04fig09.gif

In our case, however, the primary key column within the database table is auto-generated (an IDENTITY column). You don't need to enter a value, and the INSERT statement declared for the InsertCommand property of the data source control does not attempt to apply any value that you might enter anyway. You could create the fields for the DetailsView control manually, by setting the AutoGenerateRows attribute to False and using a BoundField with the InsertVisible property set to False , or by using a TemplateField , so that the value is not editable.

Handling DetailsView Control Events

There are a couple of other issues to look at as well. Although the GridView and DetailsView controls are linked so that the DetailsView displays the row currently selected in the GridView , changes to the rows during editing (within the DetailsView ) are not automatically displayed in the GridView control.

However, like the GridView , the DetailsView control exposes events that occur as rows are being manipulated. By handling these events you can link the controls together so that each reflects any changes made in the other. The declaration of the DetailsView control shown in Listing 4.25 and repeated in Listing 4.26 for convenience includes four attributes that specify event handlers that will be executed in response to the ItemDeleting , ItemUpdated , ItemInserted , and ItemDeleted events.

Listing 4.26 The Event Attribute Declarations for the DetailsView Control
 <asp:DetailsView id="details1" DataSourceID="dvs1" runat="server"      DataKeyNames="ShipperID"      AutoGenerateInsertButton="True" AutoGenerateEditButton="True"      AutoGenerateDeleteButton="True" AutoGenerateCancelButton="True"  OnItemDeleting="CheckDelete" OnItemUpdated="UpdateGrid"   OnItemInserted="UpdateGrid" OnItemDeleted="UpdateGrid"  /> 
Preventing the Original Rows from Being Deleted

The ItemDeleting event occurs just before a row is deleted in the DetailsView control, and the page handles this to prevent attempts to delete the existing rows in the table (as shown earlier for the GridView control). Other than the fact that this event handler takes a DetailsViewDeleteEventArgs instance as the second argument, rather than the GridViewDeleteEventArgs instance used in the earlier example, the code is identical (see Listing 4.27).

Listing 4.27 The Event Handler for the ItemDeleting Event
 <script runat="server"> Sub CheckDelete(oSender As Object, _                 oArgs As DetailsViewDeleteEventArgs)   Dim iKey As Integer = oArgs.Keys(0)   If iKey < 4 Then     oArgs.Cancel = True     lblError.Text = "Cannot delete the original rows from the table"   End If End Sub </script> 
Updating the GridView Display with New or Changed Row Values

The other three event attribute declarations specify that the event handler named UpdateGrid will be executed after a row has been updated, inserted, or deleted. All the code has to do in this case is call the DataBind method of the GridView control so that it shows the changes to the rows made in the DetailsView control (see Listing 4.28). However, when a row is deleted, the currently selected row in the GridView is null, and this will cause an error when it tries to redisplay this row in the DetailsView control. To prevent this, the SelectedIndex property of the GridView is set to (the first row, which cannot be deleted).

Listing 4.28 Displaying the Changed Data
 Sub UpdateGrid(oSender As Object, oArgs As DetailsViewStatusEventArgs)   grid1.DataBind()   grid1.SelectedIndex = 0 End Sub 

Another situation where event handling might be useful is to highlight the current row in the GridView control when the user navigates through the rows using the DetailsView pager controls. The GridView would need to have a different style defined for the selected row (using the SelectedItemTemplate ). Code that handles the DataItemIndexChanged event for the DetailsView would just set the SelectedIndex property of the GridView to the appropriate row index. This automatically displays the new row in the appropriate way.

The DetailsView Control Interface

As noted earlier, and as you'll have seen from the examples above, the DetailsView control interface is similar to that of the GridView . This isn't surprising because they both do effectively the same thingdisplay rows of data. The main difference is that the GridView displays the rows horizontally as a table, with the fields in columns, while the DetailsView displays each row as a separate single page with the fields laid out vertically. However, for completeness, the following sections list the members of the DetailsView that are not found in the GridView .

Properties Specific to the DetailsView Control

The DetailsView control does not support sorting and thus has none of the properties associated with this feature that apply to the GridView control. And the different ways that the rows are displayed mean that there is no concept of a selected row in a DetailsView , so there is no AutoGenerateSelectButton or selected row style properties. Properties that are available for the DetailsView control, and not for the GridView control, include those listed in Table 4.13.

Table 4.13. The Properties of the DetailsView Control

Property

Description

AutoGenerateInsertButton

Sets or returns a Boolean value that indicates whether the control will automatically generate a New button for each row.

AutoGenerateRows

Sets or returns a Boolean value that indicates whether the control will automatically generate fields for each column in the output based on the structure of the data rows.

DataItemIndex

Sets or returns an Integer value that is the zero-based index of the DataItem (row) currently displayed.

HeaderText

Sets or returns a String that is the text to be displayed immediately above the fields in the output generated by the control.

DefaultMode

Sets or returns a value from the DetailsViewMode enumeration that specifies how the fields are displayed when the page loads and after Cancel, Update, Delete , or New is pressed. Valid values are ReadOnly (the default), Edit , and Insert .

DataItem

Returns an Object reference to the DataItem object currently displayed by the control.

DataItemCount

Returns an Integer value that is the total number of rows in the underlying data source bound to the control.

DataKey

Returns a DataKey instance containing the keys and values corresponding to the key names specified by the DataKeyNames attribute.

RowFields

Returns a DataControlFieldCollection instance that is a collection of all the DataControlField objects that generate the output for the control.

CurrentMode

Returns a value from the DetailsViewMode enumeration that indicates the current mode of the DetailsView .

Events Specific to the DetailsView Control

The DetailsView control has the same DataBinding and DataBound events as the GridView , but the remaining events are specific to the DetailsView control (see Table 4.14).

Table 4.14. The Events of the DetailsView Control

Event

Description

DataItemIndexChanging

Raised before the DetailsView control changes from one row to the next. Passes a DetailsViewItemEventArgs instance to the event handler, which exposes the following properties:

  • Cancel : A Boolean property that can be set to True to prevent the control from changing to the new row.

  • NewDataItemIndex : The zero-based Integer index of the row that will be displayed next.

DataItemIndexChanged

Raised after the DetailsView control changes from one row to the next. Passes a standard EventArgs instance to the event handler.

ItemCommand

Raised when any control in the DetailsView causes a postback. Passes a DetailsViewCommandEventArgs instance to the event handler, which exposes the following properties:

  • CommandArgument : The value of the CommandArgument property of the button that raised the event.

  • CommandName : The CommandName property of the control that caused the postback as a String .

  • CommandSource : An Object reference to the control that caused the postback.

ItemCreated

Raised when a new row is created in the DetailsView control. Passes a standard EventArgs instance to the event handler.

ItemDeleting

Raised before the data source control bound to the DetailsView deletes a row. Passes a DetailsViewDeleteEventArgs instance to the event handler, which exposes the following properties:

  • Cancel : A Boolean property that can be set to True to cancel the delete operation.

  • Keys : An IOrderedDictionary instance containing the primary key values for the row.

  • RowIndex : An Integer value indicating the index of the row within the data source rowset.

  • Values : An IOrderedDictionary instance containing the values currently in the row. These values will not be passed to the DataSource control unless you move them into the Keys IOrderedDictionary .

ItemDeleted

Raised after the data source control bound to the DetailsView deletes a row. Passes a DetailsViewStatusEventArgs instance to the event handler, which exposes the AffectedRows property indicating the number of rows affected by the delete operation.

ItemInserting

Raised before the data source control bound to the DetailsView inserts a new row. Passes a DetailsViewInsertEventArgs instance to the event handler, which exposes the following properties:

  • Cancel : A Boolean property that can be set to True to cancel the insert operation.

  • CommandArgument : The value of the CommandArgument property of the control that raised the event.

  • Values : An IOrderedDictionary instance containing the values for the new row.

ItemInserted

Raised after the data source control bound to the DetailsView inserts a new row. Passes a DetailsViewStatusEventArgs instance to the event handler, which exposes the AffectedRows property indicating the number of rows affected by the insert operation.

ItemUpdating

Raised before the data source control bound to the DetailsView updates a row. Passes a DetailsViewUpdateEventArgs instance to the event handler, which exposes the following properties:

  • Cancel : A Boolean property that can be set to True to cancel the update operation.

  • CommandArgument : The value of the CommandArgument property of the button that raised the event.

  • Keys : An IOrderedDictionary instance containing the primary key values for the row.

  • NewValues : An IOrderedDictionary instance containing the values that will be placed into the row.

  • OldValues : An IOrderedDictionary instance containing the values currently in the row. These values will not be passed to the DataSource control unless you move them into the NewValues IOrderedDictionary.

ItemUpdated

Raised after the data source control bound to the DetailsView has updated a row. Passes a DetailsView StatusEventArgs instance to the event handler, which exposes the AffectedRows property indicating the number of rows affected by the update operation.

ModeChanging

Raised before the DetailsView changes from one mode to another ( ReadOnly , Edit , or Insert ). Passes a DetailsViewModeEventArgs instance to the event handler, which exposes the following properties:

  • Cancel : A Boolean property that can be set to True to prevent the control changing to the new mode.

  • CancellingEdit : A Boolean value that is True if the mode change was caused by the user clicking the Cancel button while in edit mode.

  • NewMode : The new mode as a value from the DetailsViewMode enumeration. The value can be changed to display a different mode.

ModeChanged

Raised after the DetailsView has changed from one mode to another ( ReadOnly , Edit , or Insert ). Passes a standard EventArgs instance to the event handler.



A First Look at ASP. NET v. 2.0 2003
A First Look at ASP. NET v. 2.0 2003
ISBN: N/A
EAN: N/A
Year: 2004
Pages: 90

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