|
Hyperlink Control".
This approach can be used with any of the list controls that are provided with ASP.NET 2.0, including those that were originally introduced in version 1.0 (for example, the DataGrid, DataList, Repeater, ListBox, and HtmlSelect controls). However, data source controls really come into their own when used with the new GridView, DetailsView and FormView controls.
Automatic Updates with the New Data Source Controls
The original version's (1.0) list and grid controls are effectively "read-only", in that you have to write code that is executed in response to events raised by controls within the list or grid (for example, when the user clicks an Update or Delete link). This code must collect the values in the relevant row and then execute some code you've written to push these values back into the data store - possibly using stored procedures or explicit SQL statements. In other words, data binding is only being used to populate the list or grid control.
In the GridView, DetailsView and FormView controls, this is no longer the case. As long as the data source is updateable, and you have provided the appropriate update, insert and delete commands, the control will automatically push changes to the values in the list or grid control to which it's attached back into the data source. You can specify the update, insert and delete commands as explicit SQL statements or use stored procedures if you need to interact with a more complex database table structure.
What's important with respect to the topic of this article, however, is how these new controls affect the syntax used for data binding. When the columns or rows for a GridView or DetailsView control are auto-generated, or specified using a the pre-defined field types such as BoundField, HyperLinkField, or CheckBoxField, the data source control can figure out what to do when it's time to push changes back into the data store by looking at which columns each of the field types is bound to.
But, if you use a TemplateField in a GridView or a DetailsView, you must declare all the content for that column or row yourself, just as you would when using a TemplateColumn in a DataGrid control. And, if you use a FormView control, you always have to declare all the content yourself. Like the v1.0 Repeater control, the FormView control does not support pre-defined column types - it uses only templates for content generation.
Inside the templates of a TemplateField, or in the templates of a FormView control, you use data binding statements to connect the controls you declare there with the columns in the data source control. The interesting point is that the data binding technology must, in this case, support both "read" and "write" operations, rather than being "read-only" as has always been the case in the past. This is termed two-way data binding, and is supported through a new method called Bind.
The Bind Method
As with the Eval method, the Bind method has two overloads, which means that it can be used with or without the "format" parameter:
<%# Bind("expression"[, "format"]) %>
In fact, other than specifying the new method name, the Bind method is used just like the Eval method. To bind an attribute of a control to the CompanyName column, you use:
<%# Bind("CompanyName") %>
If you want to bind an attribute of a control to a value that requires formatting, you add the format parameter:
<%# Bind("OrderDate", "{0:dddd d MMMM}") %>
To demonstrate the Bind method, the following code shows a SqlDataSource control with parameterized SQL statements specified for the UpdateCommand and InsertCommand property attributes. The data source control exposes a two-column rowset containing the ID and name of products from the SQL Server Northwind sample database:
<asp:SqlDataSource id="datasource1" runat="server"
SelectCommand="SELECT ProductID, ProductName FROM Products"
UpdateCommand="UPDATE Products SET ProductName=@ProductName
WHERE ProductID=@ProductID"
InsertCommand="INSERT INTO Products (ProductName)
VALUES (@ProductName)"
/>
The next listing shows how the templates of a FormView control can be declared to allow the product name to be edited or a new product to be added. For this to work, the FormView control must know which is the primary key column in the source data, and this is declared using the DataKeyNames attribute (multiple column primary keys are specified using a comma-delimited list of column names in the control declaration, or a String array of column names at runtime).
<asp:FormView id="formview1" DataSourceID="datasource1" runat="server"
DataKeyNames="ProductID" AllowPaging="True">
<ItemTemplate>
<b><%#Eval("ProductName")%></b><p />
<asp:LinkButton id="btnEdit" runat="server"
CommandName="Edit" Text="Edit Details" /><br />
<asp:LinkButton id="btnInsert" runat="server"
CommandName="New" Text="Add New Product" />
</ItemTemplate>
<EditItemTemplate>
<asp:Label id="lblEditID" runat="server"
Text='<%# Bind("ProductID")%>' />
<asp:TextBox id="txtEditName" runat="server"
Text='<%# Bind("ProductName") %>' />
<asp:LinkButton id="btnUpdate" CommandName="Update"
Text="Update" runat="server" />
<asp:LinkButton id="btnCancel" CommandName="Cancel"
Text="Cancel" runat="server" />
</EditItemTemplate>
<InsertItemTemplate>
<asp:TextBox id="txtInsertName" runat="server"
Text='<%# Bind("ProductName") %>' />
<asp:LinkButton id="btnAdd" CommandName="Insert"
Text="Add" runat="server" />
<asp:LinkButton id="btnAbandon" CommandName="Cancel"
Text="Cancel" runat="server" />
</InsertItemTemplate>
</asp:FormView>
Then each template section declares a control to either display or allow editing of the product name. In the ItemTemplate, where the value is just being displayed, the code can use the Eval method to bind to the ProductName column. In the EditItemTemplate and the InsertItemTemplate, the product name is displayed in a TextBox control, allowing it to be edited or entered. Because we want to push these values back into the database, the Bind method must be used here.
One important point to note is that the ProductID column is the primary key in the table, and so it is "read-only" and cannot be changed in the EditItemTemplate. However, it is required to populate the @ProductID parameter of the SQL UPDATE statement - which means it must be placed in an ASP.NET server control (in this case a Label) and bound to the source rowset using the Bind method. If the Eval method is used here, the control will not be able to populate the @ProductID parameter in the SQL statement.
The ProductID is not required in the InsertItemTemplate, because this is an IDENTITY column in the database - and so it will be populated automatically when a new row is added. For this reason, the SQL INSERT statement has no parameter for the ProductID; hence, there is no requirement to display the value in a server control within this template, or use the Bind method. The only value that is required is the new product name, and the Bind method used with the TextBox where this is entered will push the new value into the database table.
The screenshot below shows the results. This example, bind-method.aspx, is included in the samples you can download for this article from http://www.daveandal.net/articles/databinding-syntax/.
Figure 3
To cause an update, delete or insert operation to take place in a FormView control, you must provide the relevant links or buttons to initiate the process yourself. However, as long as you use the appropriate values for the CommandName property attributes ("Edit", "New", "Update", "Insert", "Delete" or "Cancel") the control will automatically wire them up to the events so that you don't have to write any code. For more details of the FormView control, see the System.Web.UI.WebControls namespace in the Reference section of the SDK installed with the .NET Framework, or available online from http://msdn.microsoft.com.
When To Use the Bind Method
When you use templates in a GridView, DetailsView or FormView control, you should be aware of a few points:
- The Bind method is responsible for providing the values for the parameters declared in the SQL statements that push changes to the data back into the database. Therefore, all the controls that provide values for the parameters in the SQL statement for the current operation must use the Bind method. In the earlier example, the control for the ProductID in the EditItemTemplate is a Label that doesn't allow the value to be edited (it is the primary key for the row). However, the value is required to populate the @ProductID parameter in the SQL UPDATE statement, and so the Bind method is used, rather than the Eval method. However, because ProductID is an IDENTITY column within the database, a value isn't required in the SQL INSERT statement - and a bound control is not required in the InsertItemTemplate section.
- In general, the Bind method should only be used in an EditItemTemplate and an InsertItemTemplate. It should not be used (or, in fact, required) in an ItemTemplate, AlternatingItemTemplate, or SelectedItemTemplate.
- A list control in which the Bind method is used must be populated by a data source control that is connected to the list control through the DataSourceID property or attribute. It cannot be used for controls that are populated (as in ASP.NET 1.x) by assigning a rowset to their DataSource property.
- Every control that uses the Bind method to populate one or more of its attributes must have a unique user-declared value for its ID property (as shown for the controls in the listing above).
- The Bind method cannot be used in a DataList or a Repeater control, or in any other type of control, and it cannot be used at Page level outside all of the controls. In effect, the only controls to where you can use the Bind method are the GridView, DetailsView and FormView controls.
The New Data Binding Syntax for XML Data >>
|