Unveil the Data Binding Architecture inside Microsoft ASP.NET Ajax 1.0 - Part 2
page 5 of 7
by Xianzhong Zhu
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 32645/ 48

Sample 2 - database binding

Now, turns up the comparatively complex database binding sample. According to what we have discussed above, we find out the typical scenarios on using DataSource; and also, in Sample 1, we used an in-memory data source to simulate the web service calling with state. In practice, however, this is not recommended. In this section, we are to create a sample much closer to the enterprise development environment.

Introduction

1. Create the sample

Launch Visual Studio 2005 and then create a sample website named DatabaseBinding using the "ASP.NET AJAX CTP-Enabled Web Site" template, as well as choose Visual C# as the built-in language. Next, modify page Default.aspx as illustrated in Figure 4.

Figure 4: The design-time sample web page

2. Behind the scene

Here are the HTML elements definitions in page Default.aspx.

Listing 6

<!--------------------------------------------------->
        <div id="detailsView"></div>
        <!--------------------------------------------------->
        <input type="button" id="previousButton" value="Previous" title="Go to
 previous row" style="width: 67px; height: 30px;" />
        <span id="rowIndexLabel"></span>
        <input id="nextButton" type="button" value="Next" title="Go to next row"
 style="width: 67px; height: 30px;" />
        
        <input type="button"
 id="addButton" value="Add" title="Create a new row" style="width: 67px; height: 30px;" />
        <input type="button"
 id="delButton" value="Delete" title="Delete the current row" style="width: 67px; height: 30px;" />
        <input type="button"
 id="saveButton" value="Save" title="Save all pending changes" style="width: 67px; height: 30px;" />
        <input type="button"
 id="refreshButton" value="Refresh" title="Discard pending changes and get the latest data from the server"
 style="width: 73px; height: 30px" />
        <!--------------------------------------------------->
        <div style="visibility:hidden;display:none" >
            <div id="detailsTemplate" class="ListWindow">
                Name: <input id="nameField" size="30" /><br />
                Address:<br />
                <textarea id="addressField" style="width: 428px; height: 130px" rows="4"
 cols="4"></textarea><br />
            </div>
            <div id="emptyTemplate">
                Loading Data...
            </div>
        </div>

According to the layout in Figure 4 and the code above, we first define two navigator buttonspreviousButton and nextButton, which are used to navigate between the records of the client-side (NOT the server side!) data source of control ItemView. Next, we define two buttons (addButton, delButton) to modify the records in the database. The next two buttons, saveButton and refreshButton, are directly corresponding with the save and load methods of the MS AJAX client-side control DataSource. After that, a group of divs tags are used to describe MS AJAX control ItemView, with each div tag in response to each template of control ItemView. You can compare the layout and mappings for ItemView here with those for ListView in Sample 1.

Create a Web Service connected with the database

1. Create a sample databaseDataBind.mdf

By right click the project and select "Add new Item…" and then choose the template "SQL Database," you can easily create an empty databasehere we name it DataBind.mdf. Then, we add to it only one table named Employees with three fieldsId (int, primary key), Name (nvarchar(50), not empty), and Address (nvarchar(50), not empty). And also, we have created four simple stored procedures: DeleteRecord, GetAllRecords, InsertRecord, UpdateRecord, which are associated with the typical CRUD database operation. Here we will not talk more about this trivial since our interests do not lie in here.

2. Create a classEmployee

This class is very much like class Employees in Sample 1, which acts as the OOP packing with its attribute DataObjectField decorated member variables mapped to the fields defined in table Employees.

3. Two Helper classesSqlHelper (borrowed from Microsoft) and SqlTaskProvider

To make things easier and reusable, we have set up two helper classes: one is SqlHelper borrowed from Microsoft sampleTaskList, the other is SqlTaskProvider. Since these contents are far from our attention, we do not explain them either, and you can refer to the source code for details.

Now with the groundwork done, let us create a DataService (derived from Web Service) connected with the database.

2. Create a DataService to connect with database

Here is the key code snippet of file MyDataService.asmx.

Listing 7

//……(omitted)
using System.ComponentModel;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Data;
using System.Web.Script.Services;
using Microsoft.Web.Preview.Services;
using Demos.Employee; //defines class SqlTaskProvider
[WebService(Namespace = "http://tempuri.org/")][WebServiceBinding(ConformsTo =
  WsiProfiles.BasicProfile1_1)][ScriptService]
public class MyDataService: DataService
{
  [WebMethod][DataObjectMethod(DataObjectMethodType.Delete)]
  public void DeleteRecord(Employee emp)
  {
    if (emp.Name == null)
    {
      throw new AccessViolationException();
    }
    new SqlTaskProvider().DeleteRecord(emp);
  }
  [WebMethod][DataObjectMethod(DataObjectMethodType.Select)]
  public List < Employee > GetAllRecords()
  {
    return new SqlTaskProvider().GetAllRecords();
  }
  [WebMethod][DataObjectMethod(DataObjectMethodType.Insert)]
  public void InsertRecord(Employee emp)
  {
    if (emp.Name == null)
    {
      throw new AccessViolationException();
    }
    new SqlTaskProvider().InsertRecord(emp);
  }
  [WebMethod][DataObjectMethod(DataObjectMethodType.Update)]
  public void UpdateRecord(Employee emp)
  {
    if (emp.Name == null)
    {
      throw new AccessViolationException();
    }
    new SqlTaskProvider().UpdateRecord(emp);
  }
}

With a little study, you can make clear the calling relations as shown in Figure 5.

Figure 5

Next, let us see how the data bindings are accomplished on the client side. Note here we still use the xml-script mode instead of the manual JavaScript programming.

Declarative programming on the client side

As with Sample 1, we first set up the mapping relationships between the HTML elements defined above and the templates of control ItemView.

Listing 8

<components>
                <dataSource id="EmployeeDataSource" serviceURL="MyDataService.asmx" >
                </dataSource>
                
                <itemView id="detailsView">
                    <bindings>
                      <binding dataContext="EmployeeDataSource" dataPath="data" property="data" />
                        <binding dataContext="EmployeeDataSource" dataPath="isReady"   
  <p class=Code-ASPXCxSpMiddle>property="element" propertyKey="enabled"/>
                    </bindings>
                    
                    <itemTemplate>
                        <template layoutElement="detailsTemplate">
                            <textBox id="nameField">
                                <bindings>
                                    <binding dataPath="Name" property="text" direction="InOut"/>
                                </bindings>
                            </textBox>
                            <textBox id="addressField">
                                <bindings>
                                    <binding dataPath="Address" property="text" direction="InOut"/>
                                </bindings>
                            </textBox>
                        </template>
                    </itemTemplate>
                    <emptyTemplate>
                        <template layoutElement="emptyTemplate" />
                    </emptyTemplate>
                </itemView>

Here, there are some points to be noticed. First, control ItemView is typically used for showing one record with MS AJAX client-side data binding solution, while control ListView is used for many records in some range. Second, control ItemView uses two bindings: the first binding will bind the data returned from DataSource to property data of control ItemView to ensure the ItemView can get its required integrated dataset from the data source; the second binding binds the property enabled of ItemView to the property IsReady of DataSource, which means that when the data source has not get ready, e.g. the data source is just reading/writing data from/to the server, the ItemView will be set disabled. Third, we have used two-way bindings, which means that not only will the changing of properties of the source control (the one pointed to by dataContext property) update the corresponding properties of the target control, but also the changing of the target control will affect the source control. So, in this example not only will the data changing in DataSource affect the data to be shown in the Textbox controls but contents of these Textbox controls affect the data of the DataSource. And also, we should notice that the changing of DataSource will make the data dirty - the property isDirty of the DataSource control will be set to true.

Next, come the definitions of the two navigator buttons.

Listing 9

                <button id="previousButton">
                    <click>
                        <invokeMethodAction target="detailsView" method="movePrevious" />
                    </click>
                    <bindings>
                          <binding dataContext="detailsView" dataPath="canMovePrevious" 
 property="element" propertyKey="disabled"
 transform="Invert" />
                    </bindings>                        
                </button>
                <label id="rowIndexLabel">
                    <bindings>
                        <binding dataContext="detailsView" dataPath="dataIndex"
 property="text" transform="Add" />
                    </bindings>
                </label>
                <button id="nextButton">
                    <click>
                        <invokeMethodAction target="detailsView" method="moveNext" />
                    </click>
                    <bindings>
                          <binding dataContext="detailsView" dataPath="canMoveNext" 
 property="element" propertyKey="disabled"
 transform="Invert" />
                    </bindings>                        
                </button>

Here, control ItemView supplies some methods and properties to be used to navigate between the records loaded into it. If the user is browsing the first record, then property canMovePrevious is set to false; or else true. In this example, when the user is browsing the first record, button previousButton is set disabled automatically. In addition, we specify a corresponding action for the click event of button previousButton: call method movePrevious of control ItemView. As for button nextButton, things are just the same. Moreover, we read the index value of current record in the dataset through property dataIndex, and bind it to a label control.

Now comes the most interesting and important part with database CRUD operations.

Listing 10

                <button id="addButton">
                    <click>
                        <invokeMethodAction target="detailsView" method="addItem" />
                    </click>
                    <bindings>
                          <binding dataContext="EmployeeDataSource" dataPath="isReady" 
 property="element" propertyKey="disabled" transform="Invert" />
                    </bindings>                        
                </button>
                
                <button id="delButton">
                    <click>
                        <invokeMethodAction target="detailsView" method="deleteCurrentItem" />
                    </click>
                    <bindings>
                          <binding dataContext="EmployeeDataSource" dataPath="isReady" 
 property="element" propertyKey="disabled"
 transform="Invert" />
                    </bindings>                        
                </button>
                
                <button id="saveButton">
                    <click>
                        <invokeMethodAction target="EmployeeDataSource" method="save" />
                    </click>
                    <bindings>
                          <binding dataContext="EmployeeDataSource"
 dataPath="isDirtyAndReady"  property="element"
 propertyKey="disabled" transform="Invert" />
                    </bindings>                        
                </button>
                
                <button id="refreshButton">
                    <click>
                        <invokeMethodAction target="EmployeeDataSource" method="load" />
                    </click>
                    <bindings>
                          <binding dataContext="EmployeeDataSource" dataPath="isReady" 
 property="element" propertyKey="disabled"
 transform="Invert" />
                    </bindings>                        
                </button>

When you need to add a new record to the dataset, you should call method addItem of control ItemView - only when the data source get ready can you call this method. As for button delButton, things are very similar. When the data source is ready, method deleteCurrentItem of control ItemView can be called; or else, button delButton is set disabled with data binding.

As for button saveButton, things become a bit complicated. Only when the dataset becomes dirty and the data source gets ready, can we save the data. You should recall that the TextBox controls defined inside the ItemTemplate of ItemView are all bond with two directions. So, when the user alters contents of any of the TextBox controls the dataset in control ItemView will be updated automatically, as well as the dataset in its data source. As a result, the data source becomes dirty, and at the same time, the data source gets ready, so property isDirtyAndReady will be set to true. And so, when the data source becomes dirty and gets ready, button saveButton is enabled or else disabled.

When you click button refreshButton there will occur a SELECT query, which will in turn trigger all the bindings and load the newest data into the controls on the web page. Note that the refresh operation occurs in the AJAX way (asynchronously), so only control ItemView is updated without traditional flickering on the whole web page.

4. Running the sample

Without any trouble, press F5 and you will see the runtime screenshot like Figure 6.

Figure 6:

In this screen you can operate with the records (possibly from a faraway database with the DataService as the intermedia) as those done in a traditional application. Is it easy?


View Entire Article

User Comments

Title: binding the listview   
Name: silo
Date: 2010-08-02 8:14:52 AM
Comment:
the sample code has a crc error when i try to extract it.






Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-19 3:07:07 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search