Server-Side Data Binding


So, we can display data from a database table, and exert very fine control over the way it is presented, but what's actually going on here? How does the data get from the table into the page? While you don't need to know all about this to use the controls, in the same way as you don't need to be a mechanic to drive a car, where we're going from here on in will require at least a basic appreciation of the topic. Maybe compare it to driving across a very large desert, where it would be quite useful to learn how to get sand out of a carburettor before you set off.

All the list controls we use in ASP.NET provide a feature called data binding. The idea is that we just tell a control what the data source is, and it fetches the data and builds up the appropriate section of the page containing that data. If you think about it, that's what the SqlDataSourceControl and MxDataGrid controls are doing in the examples we've seen so far in this chapter. The data is taken from the database, and used to fill the control on the server, then the resulting page is sent to the browser. We saw this in action briefly in Chapter 6 when working with collections. In this chapter, and the next chapter, we'll take this a bit further, and bind data from the database to different types of controls.

Data-Binding to .NET Server Controls

The way that we accomplish data binding varies, depending on the control we're applying it to. The different types of list control that are part of the .NET Framework have different capabilities, and so, apply different requirements to the process of setting up this binding. In the next chapter, we'll look in more depth at the different types of list controls that are provided with .NET, and see these differences.

Data binding is not limited to list controls either. We can bind a data source to almost any control, or even to the page itself. Again, we'll see more of this in the next chapter. What we want to look at here is a topic that is fundamental to the data binding process in many scenarios, and which requires a broad appreciation of data binding techniques. This topic is the use of templates.

Using a Template to Display Data

If you studied the list of column types that are available in the MxDataGrid control's field editor dialog while working through the previous Try It Out, you'll have seen the option for a using TemplateField column:

We didn't use this column type in our example, instead choosing a HyperlinkColumn so that we could display the value from the source data in that column as a hyperlink. What actually happens in this case is that the control automatically generates a normal HTML <a> element (the element used to create links), and the values we specify for the column's properties translate into the values used to make the link work.

So, we set the DataNavigateField and DataTextField properties to the name of the column, which means that the value of the column in each row is used to generate the <a> element for that row. Since the same value is used in both fields, the displayed text will match the link to the file. If you view the source of the page in the browser (by using the View | Source menu option from the browser menu bar), you'll see that we end up with the following code for the Cover column in the first row (we've added some line breaks to make it easier to see):

 ... <td>  <a href="http://oursite.com/covers/thisone.gif">  http://oursite.com/covers/thisone.gif  </a> </td> ... 

This is obviously an extremely useful technique for generating customized output. What about if we want to display the image itself in this column though, rather than a hyperlink that points to it? In this case, we would need to generate an <img>, which is an HTML image element, so we'd need Microsoft to build in an ImageColumn option, and what if we wanted to include an image and some text, or a pair of radio buttons, or a drop-down list? We could have so many column types that choosing one would take longer than building the rest of the website.

Using a TemplateField Column in the MxDataGrid Control

This is where the concept of a TemplateField column comes in. Basically, it's a column where you specify exactly what you want to be generated for that column as the output from the control is being created and sent to the browser. Web Matrix includes the tools we need to create these templates for most of the list controls in ASP.NET. We'll see how it works with the MxDataGrid control here, and then look at how the technique is applied to other list controls in the next chapter.

At the end of the previous Try It Out we had produced a page that lists the rows in the Discs table of our CAM database. The last column in the MxDataGrid we use to present the data is a HyperLinkField column, which displays the value of the CoverImageUrl as a hyperlink. In the next Try It Out we'll do better than this. We'll display the actual cover image in our page, and make it a hyperlink that opens a page from some fictitious online retailer that allows visitors to buy the disc.

Try It Out—Displaying an Image in the MxDataGrid Control
  1. At the moment, the last column in the MxDataGrid is a HyperLinkField column, which displays the value of the CoverImageUrl as a hyperlink. Open the field editor dialog by selecting the MxDataGrid in the page and clicking the "three dots" (ellipsis) button in the Fields property in the Properties window of the grid, just as we did in the previous Try It Out:

    click to expand

  2. Select the last column and click the Remove button to remove it from the grid, as shown in the previous screenshot. Then click the drop-down list arrow next to the Add button, and select TemplateField to add a TemplateField to the grid:

  3. The TemplateField appears in the list of columns for the grid. Select it in the left hand list, and change the HeaderText property to Cover. Notice that, unlike the other column types we've used previously, there are no properties such as DataField or DataTextField that we can use to tell the grid where the data for this column comes from:

    click to expand

    A TemplateField column demands that we provide all the information about the output that the control should create for that column ourselves, within a template. With the MxDataGrid, there is no fancy UI that we can use to generate this template, and we have to (shock, horror!) actually type it into the HTML window ourselves.

  4. Click the OK button to save the new grid configuration and close the field editor dialog. Then click the HTML tab at the foot of the main Web Matrix editor window to see the HTML that Web Matrix has created for us. You can see the definitions of the SqlDataSourceControl and the MxDataGrid. If you scroll the page to the right, you'll also see all the attributes that have been added to each one, which represent the properties we set:

    click to expand

  5. The definition of the MxDataGrid control includes a series of BoundField elements. These are the columns that Web Matrix defined for the grid, and they include attributes that define the various properties we set for these columns. At the end of the list of columns in the MxDataGrid definition is the new TemplateField column we added. You can see that this is empty, and so, we'll get no content generated for this column as it stands:

     <wmx:TemplateField HeaderText="Cover"></wmx:TemplateField> 
    Note

    You can try running the page to see the result. The Cover column appears, because there is a TemplateField declared for it, but it is empty; and, while you can see this column in Design view, you can't drag and drop controls from the Toolbar into it.

  6. We want to add an image that is also a hyperlink to the Cover column. So, in HTML view, type in the highlighted code shown below, between the opening and closing <wmx:TemplateField> elements:

    Important

    You must type the complete <asp:Hyperlink> element definition, including all the attributes, on one line, and not broken up with line breaks as we've had to do to get it on the page, and make it easier to read:

    <wmx:TemplateField HeaderText="Cover">  <ItemTemplate>  <asp:Hyperlink   ImageUrl='<% #DataBinder.Eval(Container.DataItem, "CoverImageURL") %>'  NavigateUrl='<% #DataBinder.Eval(Container.DataItem, "DiscID",  "http://somesite.com/buy.aspx?code={0}") %>'  ToolTip='<% #DataBinder.Eval(Container.DataItem, "Title",  "Buy {0} Online Now!") %>'  runat="server" />  </ItemTemplate> </wmx:TemplateField>

  7. We also want our new column to come at the left of the grid, so open the field editor dialog again (from the ellipsis button in the Fields property of the Design view), and use the arrows next to the list of columns to move it to the top of the list:

  8. Click OK to close the field editor dialog, and run the page. You might not get the images displayed, depending on the path to them you entered into the CoverImageURL column of the Discs table when you created it in the previous chapter. If this is wrong, you'll just get the "missing image" symbol. Either edit the values in the Discs table, or copy the images from the sample code into the folder that the CoverImageURL values point to:

    click to expand

How It Works

In our earlier examples of displaying data, we've relied on bound column controls to generate the output for a column. All we do is tell the column where the data comes from, what heading text we want for the column, and perhaps some formatting and styling details as well. It looks after extracting the appropriate values, and building the output for that column in the page.

However, many of the ASP.NET controls can accept a column definition that is made up of one or more templates. The MxDataGrid is just one of these, and we'll see more examples later in the book. Using a templated column effectively says to the control "leave it to me, I will create the content I want". We have to define the template and all its content. In the case of the MxDataGrid, we did this by manually typing it in. With some other list controls, there are UI dialogs that can help out.

The ASP.NET Hyperlink control that we used in this example is an interesting control that we'll look at in Chapter 11 in more detail. To see what effect it has, look at the generated page. Notice (in the status bar of the browser) that each image is also a hyperlink, and that it points to our fictitious site. Furthermore, it actually points to a specific page on that site – and it includes a query string that contains the DiscID value of the row containing the hyperlink. So, the hyperlink could open the page showing this specific disc, and you can also see that the pop-up tool-tip displayed when the mouse is over the image contains the disc title.

The Six Types of Template

There are six different kinds of template that we can include in a templated column of a list control. Not all list controls support all of these types of templates, but the MxDataGrid supports them all – as do the standard ASP.NET DataGrid, DataList, and Repeater controls we'll meet in the next chapter:

  • A HeaderTemplate is used to specify the content that we want the list control to display as the heading row, before any data rows.

  • A FooterTemplate is used to specify the content that we want the list control to display as the footer row, after all the data rows.

  • An ItemTemplate is used to specify the content that we want the list control to display for each row in the list when just displaying the contents.

  • An AlternatingItemTemplate is used to specify the content that we want the list control to display for each alternate row. If this template is not declared, the content of the ItemTemplate is used for every row.

  • A SelectedItemTemplate is used to specify the content that we want the list control to display for the row that is currently selected. A row can be selected by setting the SelectedItem property of the list control to the index of the row (starting from zero).

  • An EditItemTemplate is used to specify the content that we want the list control to display for the row that is currently being edited. A row can be displayed in "edit mode" by setting the EditItemIndex property of the list control to the index of the row (starting from zero).

To create the content for the TemplateField column in our example, we only defined an ItemTemplate. This is the content we used:

<wmx:TemplateField HeaderText="Cover">  <ItemTemplate>  <asp:Hyperlink  ImageUrl='<% #DataBinder.Eval(Container.DataItem, "CoverImageURL") %>'  NavigateUrl='<% #DataBinder.Eval(Container.DataItem, "DiscID",  "http://somesite.com/buy.aspx?code={0}") %>'  ToolTip='<% #DataBinder.Eval(Container.DataItem, "Title",  "Buy {0} Online Now!") %>'  runat="server" />  </ItemTemplate> </wmx:TemplateField>

You can see that the content of the template is an <asp:Hyperlink> control, which we'll examine in more detail in Chapter 11. What makes it look complicated is that we want the attributes of the control (the ImageUrl, NavigateUrl, and ToolTip) to reflect some of the values that are in the current row of the data. Remember that this template is processed (used) for each row in turn, as the list control creates the output to send to the browser. So, we need a way to get at the values in the columns of the current data row that was extracted from our database.

Accessing Row Values in a Template

To get at the contents of the current row in our template, we use the Eval() method that is exposed by the DataBinder object – the thing that actually carries out the binding of the data to the list control:

 DataBinder.Eval(Container.DataItem, "column-name" [, "format-string"]) 

The third parameter, format-string, is optional. If it is not provided, the simple string representation of the value is used. However, if we do provide it, we can exert a great deal of control over the appearance and content that is placed into the output for this column and row.

Setting the ImageUrl Attribute Value

To set the ImageUrl attribute value of our <asp:Hyperlink> element, we don't need to do any formatting, so we just use:

 ImageUrl='<% #DataBinder.Eval(Container.DataItem, "CoverImageURL") %>' 

Notice the special data-binding statement delimiters <% # ... %>. We wrap the statement between <% and %> to tell ASP.NET that this is server-side code that it should execute (the language it uses is defined in the Page directive at the top of the page). Then, to indicate that it's a data-binding statement, we precede it with the hash character, #. As the data-binding statement includes double-quotes, we use single quotes to enclose the whole thing and indicate that we want whatever it evaluates to be used as the ImageUrl property.

We could alternatively have used a simpler syntax for this attribute, because we don't need to format the values and we're working in Visual Basic .NET:

 ImageUrl='<% Container.DataItem("CoverImageURL") %>' 
Note

This is in fact marginally faster and more efficient at run time than using the Eval() method, but is only any good where we are using Visual Basic .NET, and where we don't need to format the value. For these reasons, most data binding statements use the Eval() method.

Formatting the Values

The simplest format strings are like those we used to format the ReleaseDate column of our grid earlier in this chapter. To display the value as "short-month and year", we used {0:MMM yyyy}. This simply means "Format the first value you come to (the column value) using the string after the colon, which represents the month as three letters and the year as four numbers."

So, if we were using the template to display the release date, we would write something like this:

 <% #DataBinder.Eval(Container.DataItem, "ReleaseDate", "{0:MMM yyyy}") %>' 

Other common format strings are {0:C} (currency), {0:D} (standard date), and {0:P} (percentage). A full list, and descriptions of their use, can be found in the local .NET SDK at ms help://MS.NETFrameworkSDK/cpguidenf/html/cpconformattingtypes.htm, or online at http://msdn.microsoft.com/library/en us/cpguide/html/cpconformattingtypes.asp.

Setting the NavigateUrl and ToolTip Attribute Values

Now we know how we can format the values in a data row, but the format string we use can also include literal characters. In other words, we can specify the text that we want to appear in the page, and then insert the column value within that text.

This is what our example does for the NavigateUrl of the hyperlink. We want it to include the URL of the site that sells our discs, the name of the page that displays them, and a query string that specifies which disc the user selected (by clicking on the cover). The following string:

 "http://somesite.com/buy.aspx?code={0}" 

tells ASP.NET to use the string value http://somesite.com/buy.aspx?code=, and add onto the end the value from the column – but from which column? We don't want the value from the current column (the URL of the cover image), we want to value from the DiscID column. No problem, we just specify this column in the Eval statement:

  NavigateUrl='<% #DataBinder.Eval(Container.DataItem, "DiscID",  "http://somesite.com/buy.aspx?code={0}") %>' 

Note

This must be on one line in Visual Basic .NET. If you have to wrap the contents of the Eval statement, as shown above, you must use the underscore line continuation character, like the following:

  NavigateUrl='<% #DataBinder.Eval(Container.DataItem, "DiscID", _                     "http://somesite.com/buy.aspx?code={0}") %>'

The result, as you saw in the status bar of the browser at the end of the previous Try It Out is something like http://somesite.com/buy.aspx?code=3. Likewise, we create the value for the ToolTip property using a format string. This time, the value comes from the Title column (the disc title), and we insert it into the middle of the literal characters in the format string:

  ToolTip='<% #DataBinder.Eval(Container.DataItem, "Title",  "Buy {0} Online Now!") %>' 

If you look at the code that the page we used in the previous Try It Out creates in your browser (by viewing the source in your browser using the View | Source menu), you'll see the content that is generated by our TemplateField column and the hyperlink we defined within it:

 <a title="Buy Another One Online Now!"   href="http://somesite.com/buy.aspx?code=3">  <img title="Buy Another One Online Now!"  src="/books/3/257/1/html/2/http://localhost/covers/nextone.gif" border="0" /> </a> 

Using a Template to Edit Data

To show you how we can use one of the other types of column in a grid control, and how we can use another of the types of template that we mentioned earlier in the preceding section of this chapter, we'll finish this chapter with a short Try It Out that demonstrates both. We aren't in a position to be able to actually update the database contents yet, but we can see how we build the parts of the interface (the web page) that allow the user to enter new values for the columns in a table.

We'll add an EditItemTemplate to the Cover column of our MxDataGrid control, and see how the display for that row changes when we put that row into "edit mode".

Try It Out—Adding an EditItemTemplate to a Grid Control

  1. Open the field editor dialog again, by clicking on the ellipsis in the Fields property when the MxDataGrid control is selected on the page. Click the drop down button next to the Add button, and add an EditCommandField column to the grid:

  2. In the list of properties in the right-hand section of the dialog, select PushButton for the ButtonType property (the default is LinkButton), and type in the text captions that will appear on the buttons as the values of the CancelText, EditText, and UpdateText properties, as follows:

    click to expand

  3. We want this new column to be the first one in the grid (on the left when displayed), so use the arrow button next to the list of Members to move it to the top of the list:

  4. Click OK to save the new grid design and close the field editor dialog. In the ASP.NET page in Design view, you can see the new column displayed:

    click to expand

  5. Now we need to tell the grid what to do when this button is clicked. In an EditCommandColumn, the Edit button raises the EditCommand event when it is clicked. The first step is to open the list of event properties by selecting the grid control in the page and clicking the Events icon at the top of the Properties dialog:

  6. Then, find the EditCommand event and double-click on the EditCommand text itself. This switches the main Web Matrix editor window to Code view, and automatically inserts the outline of the event handler we need to write. We only have to add one line of code, which will tell the grid control that the row that was clicked should be the one that is shown in "edit mode". We get the index of the current row from the ItemIndex property of the Item object that is exposed by the arguments to the event handler, and we just have to assign this index value to the EditItemIndex property of the grid control:

    Sub MxDataGrid1_EditCommand(   source As Object, e As MxDataGridCommandEventArgs)  MxDataGrid1.EditItemIndex = e.Item.Itemindex End Sub
    Note

    The first line of code above, generated by Web Matrix automatically, is actually on one single line with no line breaks – we just can't physically fit it all on the page!

  7. Now we have to add an appropriate template to the TemplateField column that displays the image of the cover. We need an EditItemTemplate, and you can see this as the highlighted section of the next listing. Switch to HTML view in Web Matrix, and add these lines to your TemplateField column definition:

    <wmx:TemplateField HeaderText="Cover">   <ItemTemplate>     <asp:Hyperlink ... />   </ItemTemplate>  <EditItemTemplate>  <asp:TextBox  Text='<% #DataBinder.Eval(Container.DataItem, "CoverImageURL") %>'  runat="server" />  </EditItemTemplate> </wmx:TemplateField> 

    Note

    As with the <asp:Hyperlink> element in the <ItemTemplate>, the complete <asp:TextBox> element is on one single line, with no line breaks.

  8. Click the Save icon on the main Web Matrix toolbar to save the page, and click the Start button to view it in your browser. You'll see the new column with an Edit button in each row:

    click to expand

  9. Click the Edit button in the first row. The page is posted back to the server and the new page contains two different buttons, Update and Cancel, and all the values in the row are now presented in textboxes. You can edit any of them:

    click to expand

    Click the Cancel button, and the row goes back to the way it was. Or click the Edit button in a different row. The first row goes back to "normal", but the other row is now shown in "edit mode".

How It Works

You've just seen how easy it is to build editing into the interface when we use the ASP.NET MxDataGrid control. We haven't seen how to save these changes yet – the Update button won't work – but we'll add this feature in the next section.

All we had to do in this example was add a column that contains the buttons to switch the grid into "edit" mode, and link up the buttons in this column to an event handler that sets the EditItemIndex of the grid control. Then we added an EditItemTemplate to the templated column that specifies what we want the column to contain when that row is in "edit mode".

We specified that, instead of the <asp:Hyperlink> that displays the cover image, the column should display the value in a textbox. However, we don't have to use a textbox here. If we have a list of possible values, we can use an <asp:DropDownList> or <asp:ListBox>. Or, if there are only a small number of possible values for the column, we might use a set of radio buttons. The great thing about using a TemplateField column is that we are free to include whatever controls we need to generate the output we want in the page.

OK, that looks clever… but it's not very useful yet. Let's see how to make the Update button work. It's easy to do, but the inner workings are fairly complex.

Try It Out—Updating the Database
  1. Return to the Design view, and select the MxDataGrid. Now click the lightening bolt icon in the Properties pane, and double-click the BeforeUpdate event. Web Matrix will create a new event handler procedure for you, and assign it to MxDataGrid.BeforeUpdate event.

  2. Add the following code (remember that I've had to break lines in two to fit on the page):

    Sub MxDataGrid1_BeforeUpdate(source As Object, _                                           e As MxDataGridUpdateEventArgs)  e.NewValues.Add("@Title", _  CType(e.Item.Cells(2).Controls(0), TextBox).Text)  e.NewValues.Add("@ReleaseDate", _  CType(e.Item.Cells(3).Controls(0), TextBox).Text)  e.NewValues.Add("@Notes", _  CType(e.Item.Cells(4).Controls(0), TextBox).Text)  e.NewValues.Add("@Label", _  CType(e.Item.Cells(5).Controls(0), TextBox).Text)  e.NewValues.Add("@CoverImageURL", _  CType(e.Item.Cells(1).Controls(1), TextBox).Text)  e.NewValues.Add("@DiscID", _  MxDataGrid1.DataSource.DataSource.Tables(0).Rows(e.Item.DataSetIndex)(0)) End Sub 

  3. Now try running the page. You'll be able to make a change to a record and save it.

How It Works

We really didn't need to do very much to get that working. This is because Web Matrix and ASP.NET are doing the hard work for us. Even so, to understand the code we really do need to understand what's going on.

The key to this update is the UpdateCommand property of the SqlDataSourceControl. It's a SQL string used to update the database – and it was generated automatically when we dragged the table onto the page:

UPDATE [Discs] SET [Title]=@Title, [ReleaseDate]=@ReleaseDate, [Notes]=@Notes, [Label]=@Label, [CoverImageURL]=@CoverImageURL WHERE [DiscID]=@DiscID

SQL is pretty close to English, and this really doesn't take a lot of explanation. The Update [Discs] part means, "Update the table called Discs." The SET keyword indicates that what follows a series of column name and value pairs. The WHERE clause indicates that we don't want to update every record in the table – only the ones that conform to the WHERE clause. This works just like the WHERE clause in a SELECT statement. In our case we only want to update one record – the record that the user has edited. We can identify this uniquely using the DiscID for the chosen record.

So, Web Matrix and ASP.NET have done that work for us. All we need to do is assign values to every variable in the SQL string, and that's what our code does. Let's take a closer look at it now. We'll start with the first line we typed:

  e.NewValues.Add("@Title", _                          CType(e.Item.Cells(2).Controls(0), TextBox).Text)

This is all based around the e object. In Chapter 4 we learned a bit about what e is for in an event handler. In this particular case we're using it to assign values to our SQL variables. The two important properties of e are NewValues and Item. NewValues is a collection of name-value pairs we use to assign values to variable names. Item contains details about our MxDataGrid, so we use it to read the values from the TextBox controls in the grid. The part of the line that says:

CType(e.Item.Cells(2).Controls(0), TextBox).Text 

Simply boils down to finding out what the Textbox in the Title column contains. Let's break this segment down to see how it works. e.Item.Cells(2).Controls(0) means "return the content of the first control in the third cell in the active row." Remember, arrays are zero-based so Cells(2) means "the third cell". This cell only contains one control, the TextBox, so we access it.

As we saw in Chapter 5, CType is a function that will try to convert the value passed in as the first argument into the type passed in as the second argument. So here the CType function converts the control into a fully-functional TextBox object. We then return the Text property of the TextBox, which of course contains the value the user typed.

ReleaseDate, Notes, and Label work in the same way – taking the first control in the relevant cell, and assigning it to the @ReleaseDate, @Notes, or @Label variables.

Note

Although I'm calling these variables, it's only SQL that sees them that way. VB.NET sees them as normal strings, which is why we enclose them in quote marks – something we don't do with VB.NET variable names.

The CoverImageURL column works slightly differently because it's not a regular text value. Instead of specifying Controls(0), we specify Controls(1). This is because the TextBox is not the first control held in this particular cell:

  e.NewValues.Add("@CoverImageURL",                           CType(e.Item.Cells(1).Controls(1), TextBox).Text)

It's not easy to tell when there are 'hidden controls', and some trial-and-error changes may be required in cases where you have templated edit columns like this one.

The DiscID column is quite different again. Remember that this value is not editable, but we need it to uniquely identify the row that we're editing. The difference in how we use it here is because it is not displayed in our MxDataGrid, but it is present in the underlying data source – the SqlDataSourceControl. Here's the code:

  e.NewValues.Add("@DiscID", MxDataGrid1.DataSource.DataSource.                             Tables(0).Rows(e.Item.DataSetIndex)("DiscID"))

The expression first of all accesses the MxDataGrid DataSource property, which is the SqlDataSourceControl itself. We then access this control's DataSource property, which is a DataSet – something we'll hear more about in the next chapter. We then access the first (and only) Table in the DataSet. So we're gradually zooming in on the part of the DataSet that we're interested in – we've got to the correct table, but haven't yet identified what row we want, or what column. This is what Rows(e.Item.DataSetIndex)("DiscID") does. Rows is a collection of DataRow objects – each DataRow is a single complete row in the table. The expression in the first set of brackets defines what row we want, and the expression in the second set of brackets defines the column. e.Item.DataSetIndex gives us the row number of the selected row in the underlying DataSet. We then request a specific column by name. The end result is that the "@DiscID" and the value for that particular DiscID are paired up in NewValues.

The SqlDataSource will use these pairs to execute its UpdateCommand. There's a lot going on under the hood here, but the practicalities of making it work are elegant and quite easy.

Default Behavior with No Templates

One point you may have noticed in the previous example is that all the other columns in the row that we switched into "edit mode" also showed textboxes. We didn't configure this, or create any templates for these columns. However, because they are BoundField columns (which are linked, or bound, to the other columns in our table), they automatically display a default-sized textbox when the row is in "edit mode", unless we set the ReadOnly property of the column to True. The default is False.

Meanwhile, the appearance of the columns (including read-only ones) can also change when the row is in "edit mode". It depends on the setting of the EditItemStyle property of the grid control.

Taking it Further – Using a SelectedItemTemplate

We can do much the same by adding a button that switches the row into "selected mode". We would use the more general ButtonField in this case (rather than an EditCommandField), which displays a button in each row of that the column to create a column that contains a LinkButton or a PushButton. The caption for the button goes into the Text property, but we also have to be sure to set the CommandName property as well – in general we use the same as the Text value, but with no spaces:

click to expand

Then, we would link this button up to an event handler for the ItemCommand event that sets the SelectedIndex property of the grid control (rather than the EditItemIndex) to the index of the row containing the button that was clicked.

One point to watch when using a ButtonField column is that the ItemCommand event is actually called by all the controls in a grid that cause a postback. So any Edit, Update, and Cancel buttons that also exist in the grid will cause the ItemCommand event to execute as well as their "own" event. This means that, if we have both types of column (a ButtonField and an EditCommandField), we have to include some code in the ItemCommand event to check which button was clicked. We look for the CommandName property value that we specified for the button when we added the ButtonField column to the grid, so our ItemCommand event handler would look like this:

Sub MxDataGrid1_ItemCommand( _   source As Object, e As MxDataGridCommandEventArgs)  ' see if it was button with CommandName "Select" that was clicked  If e.CommandName = "Select" Then  ' set SelectedIndex of grid to index of item that was clicked  ' obtained from properties of second parameter to event handler  MxDataGrid1.SelectedIndex = e.Item.ItemIndex  End If End Sub

Plus, when we have both types of column (so that the grid can be switched into "selected mode" and "edit mode") we should add a line of code to each event handler that sets the "other" grid property to -1. In other words, in the EditCommand event handler, which runs when an Edit button is clicked, we would set the SelectedIndex property of the grid to -1 so that no rows are selected. Likewise in the ItemCommand event handler, which runs when the "select" button is clicked, we would set the EditItemIndex to -1 so that there are no rows in "edit mode".

 Sub MxDataGrid1_EditCommand( _  source As Object, e As MxDataGridCommandEventArgs)  MxDataGrid1.SelectedIndex = -1  MxDataGrid1.EditItemIndex = e.Item.Itemindex End Sub Sub MxDataGrid1_ItemCommand( _  source As Object, e As MxDataGridCommandEventArgs)  If e.CommandName = "Select" Then  MxDataGrid1.EditItemIndex = -1  MxDataGrid1.SelectedIndex = e.Item.ItemIndex  End If End Sub 

You'll also find that the columns in a "selected row" generated by a BoundField column, like all the other columns of our example grid, automatically highlight the values in that column of the selected row, and can even change the background color of the column. The actual highlight effects depend on the settings of the SelectedItemStyle property of the grid control.

click to expand




Beginning Dynamic Websites with ASP. NET Web Matrix
Beginning Dynamic Websites: with ASP.NET Web Matrix (Programmer to Programmer)
ISBN: 0764543741
EAN: 2147483647
Year: 2003
Pages: 141

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