15.4. Data BindingVarious technologies have offered programmers the opportunity to bind controls to data so that as the data was modified, the controls responded automatically. As Rocky used to say to Bullwinkle, "But that trick never works." Bound controls often provided the developer with severe limitations in how the control looked and performed. The ASP.NET designers set out to solve these problems and provide a suite of robust data-bound controls, which simplify display and modification of data, sacrificing neither performance nor control over the UI. In Version 2.0 they have expanded the list of bindable controls and provided even more out-of-the-box functionality. In the previous section, you hardcoded radio buttons onto a form, one for each of three shippers in the Northwind database. That can't be the best way to do it; if you change the shippers in the database, you have to go back and rewire the controls. This section shows how you can create these controls dynamically and then bind them to data in the database. You might want to create the radio buttons based on data in the database because you can't know at design time what text the buttons will have, or even how many buttons you'll need. To accomplish this, you'll bind your RadioButtonList to a data source. Create a new web site called DisplayShippers and drag a RadioButtonList onto the form. This time, instead of choosing EditItems from the Common RadioButtonList Tasks, click Choose Data Source.... The Choose Data Source dialog opens, as shown in Figure 15-8. Figure 15-8. Choosing a data sourceDrop down the Select a data source menu, and choose <New Data Source>. You are then prompted to choose a data source from the datatypes on your machine. Select Database, and the Configure Data Source dialog box opens, as shown in Figure 15-9. Figure 15-9. Configuring a data sourceChoose New to configure a new data source, and the Connection Properties Dialog opens. Fill in the fields: choose your server name, how you want to log into the server, and the name of the database. Be sure to click Test Connection to test the connection. When everything is working, click OK as shown in Figure 15-10. Figure 15-10. Setting the connection propertiesAfter clicking OK, the connection properties will be filled in for the Configure Data Source dialog. Review them and if they are OK, click Next. On the next wizard page, name your connection (e.g., NorthWindConnectionString) if you want to save it to a configuration file that can be reused. When you click Next, you'll have the opportunity to specify the columns you want to retrieve, or to specify a custom SQL statement or stored procedure for retrieving the data. Drop the Table list and scroll down to shippers. Select the ShipperID and CompanyName fields, as shown in Figure 15-11. Figure 15-11. Configuring the data source
Click Next and test your query to see that you are getting back the values you expected, as shown in Figure 15-12. Figure 15-12. Testing the queryIt is now time to attach the data source you've just built to the RadioButtonList. A RadioButtonList (like most lists) distinguishes between the value to display (e.g., the name of the delivery service) and the value of that selection (e.g., the delivery service ID). Set these fields in the wizard, using the drop down, as shown in Figure 15-13. Figure 15-13. Binding fields to the radio button controlYou can improve the look and feel of the radio buttons by binding to the Shippers table, clicking the Radio Button list, and then setting the list's properties in the Properties window. 15.4.1. Examining the CodeBefore moving on, there are a few things to notice. When you press F5 to run this application, it appears in a web browser, and the radio buttons come up as expected. Choose View Source and you'll see that what is being sent to the browser is simple HTML, as shown in Figure 15-14. Figure 15-14. Examining the HTML that ASP.NET sends your browserNotice that the HTML has no RadioButtonList; it has a table, with cells, within which are standard HTML input objects and labels. ASP.NET has translated the developer controls to HTML understandable by any browser.
15.4.2. Adding Controls and EventsBy adding just a few more controls, you can create a complete form with which users can interact. You will do this by adding a more appropriate greeting ("Welcome to Northwind"), a text box to accept the name of the user, two new buttons (Order and Cancel), and text that provides feedback to the user. Figure 15-15 shows the finished form. Figure 15-15. The completed shipper formThis form won't win any awards for design, but its use will illustrate a number of key points about Web Forms.
Example 15-1 is the complete HTML for the .aspx file. Example 15-1. The .aspx file<%@ Page Language="C#" CompileWith="Shipper.aspx.cs" ClassName="Shipper_aspx" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Choose Shipper</title> </head> <body> <form runat="server"> <table style="width: 166px; height: 33px"> <tr> <td colspan="2" style="height: 20px">Welcome to NorthWind</td> </tr> <tr> <td>Your name:</td> <td><asp:TextBox Runat=server></asp:TextBox></td> </tr> <tr> <td>Shipper:</td> <td> <asp:RadioButtonList Runat="server" DataSource DataTextField="CompanyName" DataValueField="ShipperID"> </asp:RadioButtonList> <asp:SqlDataSource Runat="server" SelectCommand="SELECT [ShipperID], [CompanyName] FROM [Shippers]" ConnectionString= "<%$ ConnectionStrings:NorthWindConnectionString %>"> </asp:SqlDataSource> <br /> </td> </tr> <tr> <td><asp:Button Runat=server Text="Order" /></td> <td><asp:Button Runat=server Text="Cancel" /></td> </tr> <tr> <td colspan="2"><asp:Label runat=server></asp:Label></td> </tr> </table> </form> </body> </html> When the user clicks the Order button, you'll check that the user has filled in his name, and you'll also provide feedback on which shipper was chosen. Remember, at design time you can't know the name of the shipper (this is obtained from the database), so you'll have to ask the listbox for the chosen name (and ID). To accomplish all of this, switch to Design mode and double-click the Order button. Visual Studio will put you in the code-behind page, and will create an event handler for the button's Click event.
You add the event-handling code, setting the text of the label to pick up the text from the text box and the text and value from the RadioButtonList: void btnOrder_Click( object sender, EventArgs e ) { lblMsg.Text = "Thank you " + txtName.Text.Trim( ) + ". You chose " + rblShippers.SelectedItem.Text.ToString( ) + " whose ID is " + rblShippers.SelectedValue.ToString( ); } When you run this program you'll notice that none of the radio buttons is selected. Binding the list did not specify which one is the default. There are a number of ways around this, but the simplest is to override the OnLoad event and set the first radio button to be selected. Return to Shipper.aspx.cs and type protected override. You will see a scrolling list of all the overrideable methods, properties, etc., as shown in Figure 15-16. Figure 15-16. Overriding OnLoadStart typing OnLoad; when it is highlighted press Tab. The stub for the overridden method is created, but its default body throws the NotImplementedException. Delete the exception and replace it with this code: rblShippers.SelectedIndex = 0; This sets the RadioButtonList's first radio button to selected. The problem with this solution is subtle. If you run the application, you'll see that the first button is selected, but if you choose the second (or third) button and click OK, you'll find that the first button is reset. You can't seem to choose any but the first selection. This is because each time the page is loaded, the OnLoad event is run, and in that event handler you are (re-)setting the selected index. The fact is that you only want to set this button the first time the page is selected, not when it is posted back to the browser as a result of the OK button being clicked. To solve this, wrap the setting in an if statement that tests if the page has been posted back: protected override void OnLoad(EventArgs e) { if ( !IsPostBack ) { rblShippers.SelectedIndex = 0; } } When you run the page the IsPostBack property is checked. The first time the page is posted, this value is false and the radio button is set. If you click a radio button and then click OK, the page is sent to the server for processing (where the btnOrder_Click handler is run) and then the page is posted back to the user. This time the IsPostBack property is true, and thus the code within the if statement isn't run, and the user's choice is preserved, as shown in Figure 15-17. Figure 15-17. The user's choice is preserved on postbackThe complete code-behind form is shown in Example 15-2. Example 15-2. Code-behind form for Shipper.aspx.csusing System; using System.Data; using System.Configuration; using System.Text; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; public partial class Shipper_aspx { protected override void OnLoad(EventArgs e) { if ( !IsPostBack ) { rblShippers.SelectedIndex = 0; } } void btnOrder_Click( object sender, EventArgs e ) { lblMsg.Text = "Thank you " + txtName.Text.Trim( ) + ". You chose " + rblShippers.SelectedItem.Text.ToString( ) + " whose ID is " + rblShippers.SelectedValue.ToString( ); } }
|