ASP.NET AJAX Programmer’s Reference - Chapter 11 docx

50 351 0
ASP.NET AJAX Programmer’s Reference - Chapter 11 docx

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Data Classes Tabular data, such as relational data, plays a central role in today’s data-driven Web applications The NET Framework comes with three rich classes named DataColumn, DataRow, and DataTable that you can use in your NET code to represent and to program against tabular data The ASP.NET AJAX client-side framework comes with the same set of data classes — DataColumn, DataRow, and DataTable — that emulate their NET countparts You can use these data classes in your client-side code to represent and program against tabular data such as relational data This chapter discusses these three ASP.NET AJAX data classes All these classes belong to a namespace named Sys.Preview.Data: Type.registerNamespace(‘Sys.Preview.Data’); The ASP.NET AJAX DataTable class implements an interface named IData The chapter begins with this interface I Data Most ASP.NET AJAX client data classes, such as DataTable, implement an ASP.NET AJAX interface named IData, either directly or indirectly As a matter of fact, if none of the existing data classes meet your requirements, you can write a new data class that implements this interface Implementing this interface enables your custom data class to seamlessly integrate into the ASP.NET AJAX client-side framework For example, the ASP.NET AJAX Selector client control can bind to any data class that implements the IData interface (as discussed in more detail later) Listing 11-1 contains the definition of this interface As you can see, the IData interface exposes the following five methods: ❑ c11.indd 407 add: Your custom data class’s implementation of this method must add the specified data row to the internal collection where data rows are stored 8/20/07 8:14:13 PM Chapter 11: Data Classes ❑ clear: Your custom data class’s implementation of this method must clear the internal collection where data rows are stored ❑ get_length: Your custom data class’s implementation of this method must return an integer that specifies the total number of data rows in the internal collection where data rows are stored ❑ getRow: Your custom data class’s implementation of this method must return a reference to the specified data row ❑ remove: Your custom data class’s implementation of this method must remove the specified data row from the internal collection where data rows are stored Listing 11-1: The Definition of the IData Interface Sys.Preview.Data.IData = function Sys$Preview$Data$IData() { throw Error.notImplemented(); } function Sys$Preview$Data$IData$add() { throw Error.notImplemented(); } function Sys$Preview$Data$IData$clear() { throw Error.notImplemented(); } function Sys$Preview$Data$IData$get_length() { throw Error.notImplemented(); } function Sys$Preview$Data$IData$getRow() { throw Error.notImplemented(); } function Sys$Preview$Data$IData$remove() { throw Error.notImplemented(); } Sys.Preview.Data.IData.prototype = { add: Sys$Preview$Data$IData$add, clear: Sys$Preview$Data$IData$clear, get_length: Sys$Preview$Data$IData$get_length, getRow: Sys$Preview$Data$IData$getRow, remove: Sys$Preview$Data$IData$remove } Sys.Preview.Data.IData.registerInterface(‘Sys.Preview.Data.IData’); 408 c11.indd 408 8/20/07 8:14:14 PM Chapter 11: Data Classes DataColumn The instances of the NET DataColumn class are used to represent the columns of a data table For example, each column of a relational database table is represented by a DataColumn instance The ASP.NET AJAX client-side framework exposes an ASP.NET AJAX class named DataColumn, which emulates the NET DataColumn Listing 11-2 presents the internal implementation of this client class Listing 11-2: The ASP.NET AJAX DataColumn Client Class Sys.Preview.Data.DataColumn = function Sys$Preview$Data$DataColumn(columnName, dataType, defaultValue, isKey, isReadOnly) { this._columnName = columnName; this._dataType = dataType; this._defaultValue = defaultValue; this._readOnly = isReadOnly; this._key = isKey; } function Sys$Preview$Data$DataColumn$get_columnName() { return this._columnName; } function Sys$Preview$Data$DataColumn$get_dataType() { return this._dataType; } function Sys$Preview$Data$DataColumn$get_defaultValue() { return this._defaultValue; } function Sys$Preview$Data$DataColumn$get_isKey() { return this._key; } function Sys$Preview$Data$DataColumn$get_readOnly() { return !!this._readOnly; } function Sys$Preview$Data$DataColumn$dispose() { this._columnName = null; this._dataType = null; this._defaultValue = null; } (continued) 409 c11.indd 409 8/20/07 8:14:14 PM Chapter 11: Data Classes Listing 11-2 (continued) Sys.Preview.Data.DataColumn.prototype = { get_columnName: Sys$Preview$Data$DataColumn$get_columnName, get_dataType: Sys$Preview$Data$DataColumn$get_dataType, get_defaultValue: Sys$Preview$Data$DataColumn$get_defaultValue, get_isKey: Sys$Preview$Data$DataColumn$get_isKey, get_readOnly: Sys$Preview$Data$DataColumn$get_readOnly, dispose: Sys$Preview$Data$DataColumn$dispose } Sys.Preview.Data.DataColumn.parseFromJson = function Sys$Preview$Data$DataColumn$parseFromJson(json) { return new Sys.Preview.Data.DataColumn(json.name, typeof(json.dataType === ‘string’) ? eval(json.dataType) : json.dataType, json.defaultValue, json.isKey, json.readOnly); } Sys.Preview.Data.DataColumn.descriptor = { properties: [ { name: ‘columnName’, type: String, readOnly: true }, { name: ‘dataType’, type: Sys.Type, readOnly: true }, { name: ‘defaultValue’, readOnly: true }, { name: ‘isKey’, type: Boolean, readOnly: true }, { name: ‘readOnly’, type: Boolean, readOnly: true } ] } Sys.Preview.Data.DataColumn.registerClass(‘Sys.Preview.Data.DataColumn’, null, Sys.IDisposable); The constructor of the DataColumn class takes the following five parameters: ❑ columnName: This parameter is a string that contains the name of the data field that the DataColumn object represents For example, if you want to create a DataColumn object to represent the ProductName database field of the Products database table, you must pass the string value “ProductName” into the constructor of the DataColumn class as the first parameter ❑ dataType: This parameter references the data type of the data field that the DataColumn object represents For example, if you want to create a DataColumn object to represent the UnitPrice database field of the Products database table, you must pass Number into the constructor of the DataColumn class as the second argument ❑ defaultValue: This parameter contains the default value for the data field that the DataColumn object represents The type of this parameter depends on the type of data field ❑ isKey: This parameter is a Boolean value that specifies whether the data field that the DataColumn represents is a primary key field For example, if you want to create a DataColumn object to represent the ProductID primary key field of the Products database table, you must pass true into the constructor of the DataColumn class as the fourth argument ❑ isReadOnly: This parameter is a Boolean value that specifies whether the data field that the DataColumn represents is editable 410 c11.indd 410 8/20/07 8:14:15 PM Chapter 11: Data Classes As Listing 11-2 shows, the DataColumn client class exposes five properties with the same names as these parameters: columnName, dataType, defaultValue, isKey, and isReadOnly Like any other ASP.NET AJAX client class, this class exposes a static property named descriptor The descriptor property is set to an object literal that contains a single name/value pair describing the properties of the DataColumn class: Sys.Preview.Data.DataColumn.descriptor = { properties: [ { name: ‘columnName’, type: String, readOnly: true }, { name: ‘dataType’, type: Sys.Type, readOnly: true }, { name: ‘defaultValue’, readOnly: true }, { name: ‘isKey’, type: Boolean, readOnly: true }, { name: ‘readOnly’, type: Boolean, readOnly: true } ] } The DataColumn client class exposes five getter methods named get_columnName, get_dataType, get_defaultValue, get_isKey, and get_isReadOnly that return the values of the columnName, dataType, defaultValue, isKey, and isReadOnly properties of the class The DataColumn class does not expose any setter methods for these properties You must set the values of these properties through the constructor of the class when you’re instantiating the class This fact has also been reflected in the descriptor static property of the class, where all object literals describing the properties of the class contain the readOnly: true name/value pair In general, there are two ways to create a DataColumn object to represent the data field of a given data table One approach is to use the constructor of the DataColumn class directly as discussed earlier Another approach is to invoke the parseFromJson method on the DataColumn class As Listing 11-2 shows, the DataColumn class exposes this method as a static method, which means that you must call this method on the class itself: Sys.Preview.Data.DataColumn.parseFromJson = function Sys$Preview$Data$DataColumn$parseFromJson(json) { return new Sys.Preview.Data.DataColumn(json.columnName, typeof(json.dataType === ‘string’) ? eval(json.dataType) : json.dataType, json.defaultValue, json.isKey, json.readOnly); } This approach enables you to pass an object that contains the required information about a data field into the parseFromJson static method, and have this method instantiate and return the associated DataColumn object For example, the following code fragment presents the object literal representation of the Products database table’s UnitPrice data field: { columnName: ‘UnitPrice’, dataType: Number, defaultValue: 100, isKey: false, isReadOnly: true } As you can see, the object literal that represents a data field contains five name/value pairs that specify the data field name, type, and default value; whether the data field is a primary key; and whether the data field is editable 411 c11.indd 411 8/20/07 8:14:15 PM Chapter 11: Data Classes Now you can call the parseFromJson static method on the DataColumn class, passing in the object literal representation of the data field to instantiate and return the DataColumn object that represents the data field: var dataColumn = Sys.Preview.Data.DataColumn.parseFromJson ( { columnName: ‘UnitPrice’, dataType: Number, defaultValue: 100, isKey: false, isReadOnly: true } ); DataRow In NET, every data row is represented by an instance of a NET class named DataRow The ASP.NET AJAX client-side framework includes a client class named DataRow that emulates its NET counterpart The following sections discuss the members of this client class Constructor Listing 11-3 shows the constructor of the DataRow client class Listing 11-3: The DataRow Client Class Sys.Preview.Data.DataRow = function Sys$Preview$Data$DataRow(objectDataRow, dataTableOwner, index) { this._owner = dataTableOwner; this._row = objectDataRow; this._index = index; } DataRow takes the following three parameters: ❑ objectDataRow: This parameter references a JavaScript object that contains the data field names and values of the data row that the DataRow object being instantiated will represent An example of such an object is a JavaScript object literal that contains one name/value pair for each data field, where the name part of the pair is the name of the data field, and the value part is the value of the data field For example, the following JavaScript object literal represents a data row in the Products database table: {productName: ‘p1’, unitPrice: 30, distributor: ‘d1’} ❑ dataTableOwner: This parameter references the Sys.Preview.Data.DataTable object that owns the DataRow object being instantiated This DataTable object represents the data table that owns the data row the DataRow object represents (DataTable is discussed in more detail later.) 412 c11.indd 412 8/20/07 8:14:15 PM Chapter 11: Data Classes ❑ index: This parameter is an integer that specifies the index of the DataRow object being instantiated in the collection that contains all DataRow objects for a particular DataTable object This collection is maintained by the DataTable object (DataTable is discussed in more detail later.) The constructor of the DataRow client class respectively stores the values of the objectDataRow, dataTableOwner, and index parameters in three internal fields named _row, _owner, and _index for future reference In other words, every DataRow object maintains a reference to the DataTable object that owns it and knows its index in the underlying collection descriptor As Listing 11-4 shows, the DataRow client class exposes a static property named descriptor that describes the members of the class Listing 11-4: The descriptor Property of the DataRow Class Sys.Preview.Data.DataRow.descriptor = { properties: [ { name: ‘$isDirty’, type: Boolean, readOnly: true }, { name: ‘$index’, type: Number, readOnly: true }, { name: ‘$selected’, type: Boolean } ], events: [ { name: ‘propertyChanged’, readOnly: true } ] } The DataRow class exposes three properties and a single event as follows: ❑ $isDirty: This read-only property returns a Boolean value that specifies whether any of the data field values of the DataRow object has changed value Note that the name of this property begins with the dollar sign character As you’ll see later, when the ASP.NET AJAX JavaScriptSerializer class is serializing an object, it skips the properties with names that begin with a dollar sign ❑ $index: This read-only property returns an integer that specifies the index of the DataRow object in the underlying collection where the DataRow objects belonging to the same DataTable object are stored As mentioned earlier, this collection is maintained internally by the DataTable object itself ❑ $selected: This read/write property returns a Boolean value that specifies whether the current DataRow has been selected ❑ propertyChanged: The DataRow object raises this event when it’s selected or deselected and when its _row field or isDirty property changes value The DataRow class exposes the get_isDirty, get_index, and get_selected getter methods to allow its clients to access the values of these three properties Because the $selected property is writable, the class also exposes a setter method named set_selected to allow its clients to set the value of this property This setter method calls an internal method named _onPropertyChanged to raise the propertyChanged event 413 c11.indd 413 8/20/07 8:14:15 PM Chapter 11: Data Classes function Sys$Preview$Data$DataRow$get_isDirty() { return typeof(this._row._original) === “object”; } function Sys$Preview$Data$DataRow$get_index() { return this._index; } function Sys$Preview$Data$DataRow$get_selected() { return this._selected; } function Sys$Preview$Data$DataRow$set_selected(value) { if (this._selected !== value) { this._selected = value; this._onPropertyChanged(“$selected”); } } ICustomTypeDescriptor The DataRow class implements the ICustomTypeDescriptor interface as shown in the boldfaced portion of the following code fragment: Sys.Preview.Data.DataRow.registerClass(‘Sys.Preview.Data.DataRow’, null, Sys.Preview.ICustomTypeDescriptor, Sys.INotifyPropertyChange, Sys.IDisposable); An ASP.NET AJAX client class normally implements the ICustomTypeDescriptor to expose information that is not directly exposed through its properties, as if they were the values of its own properties This allows the clients of the class to access this information as if they were accessing the values of class properties A DataRow object represents a data row from a data table As such, it contains the names and values of the data fields of its associated data row What if the DataRow class could somehow expose the names and values of its constituent data fields as if they were the names and values of its own properties? For example, consider the following data row from the Products database table: ProductName Product1 UnitPrice Distributor 100 Distributor1 414 c11.indd 414 8/20/07 8:14:16 PM Chapter 11: Data Classes Now, let’s instantiate a DataRow object to represent this data row as follows: var dataRow = new Sys.Preview.Data.DataRow( {productName: ‘product1’, unitPrice: 100, distributor: ‘Distributor1’}); Wouldn’t it be great if the clients of this DataRow object could treat the productName, unitPrice, and distributor data fields as if they were the properties of the DataRow class itself? This would allow the clients to access the values of these data fields as if they were accessing the values of properties with the same names, which means that these clients could call the getProperty method directly on the DataRow object itself to access the value of a specified data field, like this: var productName = dataRow.getProperty(“productName”); var unitPrice = dataRow.getProperty(“unitPrice”); var distributor = dataRow.getProperty(“distributor”); The DataRow class implements the ICustomTypeDescriptor interface to achieve this goal In the previous chapter, you learned that this interface exposes three methods named getProperty, setProperty, and invokeMethod The following sections walk you through the DataRow class’s implementation of these methods to help you gain the experience you’ll need to implement the ICustomTypeDescriptor interface getProperty Listing 11-5 presents the DataRow class’s implementation of the ICustomTypeDescriptor interface’s getProperty method Listing 11-5: The getProperty Method function Sys$Preview$Data$DataRow$getProperty(name, key) { if (!name) return typeof(this._row._rowObject) !== “undefined” ? this._row._rowObject : this._row; switch(name) { case “$isDirty”: return this.get_isDirty(); case “$index”: return this._index; case “$selected”: return this.get_selected(); } return Sys.Preview.TypeDescriptor.getProperty(this._row, name, key); } This method first checks whether the property whose value is being queried is one of the DataRow class’s own properties: $isDirty, $index, or $selected If so, it returns the value of the associated property 415 c11.indd 415 8/20/07 8:14:16 PM Chapter 11: Data Classes Your custom type’s implementation of the ICustomTypeDescriptor interface’s getProperty methodmust the same — it must first check whether the property whose value is being queried is one of its own properties If so, it must return the value of the property Otherwise, the clients of your custom type would not be able to access the values of your type properties in a generic fashion via the getProperty method As Listing 11-5 shows, if the property whose value is being queried is not one of the DataRow class’s own properties, the DataRow class’s implementation of the getProperty method delegates the responsibility of returning the value of the specified property to the type of the _row field The constructor of the DataRow class stores the value of its first parameter in the _row field (as previously shown in Listing 11-3) This parameter references a JavaScript object that contains the names and values of the data fields of the data row that the DataRow object represents This means that the type of the JavaScript object that you pass into the constructor of the DataRow class as its first parameter must treat the names and values of its constituent data fields as its own properties For example, an object literal that contains one name/value pair for each data field is an example of a JavaScript object that exposes the names and values of its constituent data fields as its own properties setProperty Listing 11-6 presents the DataRow class’s implementation of the ICustomTypeDescriptor interface’s setProperty method As discussed earlier, the DataRow class exposes three properties named $isDirty, $index, and $selected The $selected property is the only property that the clients of the DataRow object can set As far as the clients of the class are concerned, the other two properties are read-only Listing 11-6: The DataRowState Enumeration Sys.Preview.Data.DataRowState = function Sys$Preview$Data$DataRowState() { throw Error.invalidOperation(); } Sys.Preview.Data.DataRowState.prototype = { Unchanged: 0, Added: 1, Deleted: 2, Detached: 3, Modified: } Sys.Preview.Data.DataRowState.registerEnum(‘Sys.Preview.Data.DataRowState’); The setProperty method first checks whether the property whose value is being set is the $selected property If so, it simply calls the set_selected setter method to set the property value and returns, as follows: if (name === “$selected”) { this.set_selected(value); return; } 416 c11.indd 416 8/20/07 8:14:17 PM Chapter 11: Data Classes ❑ The second name/value pair describes the collection that contains the new row objects The name part of this pair is the keyword inserted, and the value part references the _newRows array that contains the new row objects Therefore, you can use the following code fragment to get a reference to the _ newRows array: var dt; var jsonObj = dt.getChanges(); var newRows = jsonObj.inserted; for (var rowObject in newRows) { // Do something with the new row object } ❑ The third name/value pair describes the collection that contains the deleted row objects The name part of this pair is the keyword deleted, and the value part references the _deletedRows array that contains the deleted row objects Therefore, you can use the following code fragment to get a reference to the _deletedRows array: var dt; var jsonObj = dt.getChanges(); var deletedRows = jsonObj deleted; for (var rowObject in deletedRows) { // Do something with the deleted row object } getColumn As previously discussed, the DataTable class stores all its constituent DataColumn objects in an internal array named _columns As you can see in Listing 19-29, the getColumn method returns a reference to the DataColumn with the specified column name This method caches each requested DataColumn object in an internal cache named _columnDictionary to improve performance Subsequent requests for the same DataColumn objects are serviced from this cache Listing 11-29: The getColumn Method function Sys$Preview$Data$DataTable$getColumn(name) { var col = this._columnDictionary[name]; if (col) return col; for (var c = this._columns.length - 1; c >= 0; c ) { var column = this._columns[c]; if (column.get_columnName() === name) { 442 c11.indd 442 8/20/07 8:14:25 PM Chapter 11: Data Classes this._columnDictionary[name] = column; return column; } } return null; } raiseRowChanged The setProperty method of a DataRow object calls the raiseRowChanged method on the DataTable object that owns the DataRow object, passing in the updated row object (as previously shown in Listing 11-7) Listing 11-30 shows the raiseRowChanged method This method adds the updated row object to the _updatedRows array of the DataTable object and calls the _onPropertyChanged method to raise the propertyChanged event for the isDirty property Listing 11-30: The raiseRowChanged Method function Sys$Preview$Data$DataTable$raiseRowChanged(changedItem) { if ((Array.indexOf(this._updatedRows, changedItem) === -1) && (Array.indexOf(this._newRows, changedItem) === -1)) { var oldIsDirty = this.get_isDirty(); Array.add(this._updatedRows, changedItem); if (!oldIsDirty) this._onPropertyChanged(“isDirty”); } } parseFromJson The DataTable class exposes a static method named parseFromJson that creates a DataTable object from a JavaScript object, which is normally an object literal This object must contain the following two name/value pairs: ❑ The first name/value pair must describe the columns of the data table The name part of the pair must be the keyword columns, and the value part must be an array of object literals where each object literal describes a column In turn, each object literal must expose the following five name/value pairs: ❑ The first name/value pair must describe the column name The name part must be name, and the value part must be a string that contains the column name ❑ The second name/value pair must describe the data type of the column The name part must be dataType, and the value part must reference the actual data type ❑ The third name/value pair must describe the default value The name part must be defaultValue, and the value part must reference the actual default value 443 c11.indd 443 8/20/07 8:14:25 PM Chapter 11: Data Classes ❑ The fourth name/value pair must describe whether the column is a primary key column The name part of the pair must be isKey, and the value part must be a Boolean value ❑ The fifth name/value pair must describe whether the column is editable The name part must be readOnly, and the value part must be a Boolean value For example, the following three object literals describe the ProductId, ProductName, and UnitPrice columns of the Products data table: {name: ‘ProductId’, dataType: Number, defaultValue: 1, isKey: true, readOnly: true} {name: ‘ProductName’, dataType: String, defaultValue: ‘Unknown’, isKey: false, readOnly: true} {name: ‘UnitPrice’, dataType: Number, defaultValue: 50, isKey: false, readOnly: false} Note that the value part of the fourth name/value pair of the object literal that describes the ProductId column has been set to true to signal that this column is a primary key column If the primary key of a data table consists of multiple columns, you must set the value of the fourth name/value pair of all the object literals that describe the constituent columns of the primary key to true ❑ The second name/value pair must describe the data rows of the data table The name part of the pair must be rows, and the value part must be an array of object literals where each object literal describes a data row In turn, each object literal must contain one name/value pair for each data field of the data row The name part of each pair must be a string that contains the name of the data field, and the value part must reference the actual value of the data field For example, the following three object literals describe three data rows of the Products data table: {‘ProductId’: 1, ‘ProductName’: ‘Product1’, ‘UnitPrice’: 100} {‘ProductId’: 2, ‘ProductName’: ‘Product2’, ‘UnitPrice’: 50} {‘ProductId’: 3, ‘ProductName’: ‘Product3’, ‘UnitPrice’: 80} Here is an example of an object literal that can be passed into the parseFromJson static method of the DataTable class: { columns: [ {name: ‘ProductId’, dataType: Number, defaultValue: 1, isKey: true, readOnly: true}, {name: ‘ProductName’, dataType: String, defaultValue: ‘Unknown’, isKey: false, readOnly: true}, {name: ‘UnitPrice’, dataType: Number, defaultValue: 50, isKey: false, readOnly: false} ], rows: [ {‘ProductId’: 1, ‘ProductName’: ‘Product1’, ‘UnitPrice’: 100}, {‘ProductId’: 2, ‘ProductName’: ‘Product2’, ‘UnitPrice’: 50}, {‘ProductId’: 3, ‘ProductName’: ‘Product3’, ‘UnitPrice’: 80} ] } 444 c11.indd 444 8/20/07 8:14:25 PM Chapter 11: Data Classes ProductID ProductName UnitPrice Product1 100 Product2 50 Product3 80 This object literal describes the Products data table with three columns named ProductId, ProductName, and UnitPrice and three data rows, as shown in the following table Listing 11-31 shows the parseFromJson method Listing 11-31: The parseFromJson Method Sys.Preview.Data.DataTable.parseFromJson = function Sys$Preview$Data$DataTable$parseFromJson(json) { var columnArray = null; if(json.columns) { columnArray = []; for(var i=0; i < json.columns.length; i++) Array.add(columnArray, Sys.Preview.Data.DataColumn.parseFromJson(json.columns[i])); } return new Sys.Preview.Data.DataTable(columnArray, json.rows); } As discussed earlier, the object literal passed into the parseFromJson method contains two name/value pairs whose name parts are columns and rows The method uses columns to access its associated value part, which is an array of object literals where each object literal describes a column of the data table The method iterates through these object literals and passes each enumerated object literal into the parseFromJson static method of the DataColumn class: for(var i=0; i < json.columns.length; i++) Array.add(columnArray, Sys.Preview.Data.DataColumn.parseFromJson(json.columns[i])); The parseFromJson static method of the DataColumn class creates a DataColumn object from the specified object literal representation Note that Listing 11-31 stores all these DataColumn objects into a local array The parseFromJson method of the DataTable class then uses the rows on the object literal to access its associated value part, which is an array of object literals where each object literal describes a data row The method then passes this array and the local array that contains the DataColumn objects into the DataTable constructor to instantiate the DataTable object 445 c11.indd 445 8/20/07 8:14:26 PM Chapter 11: Data Classes Using DataColumn, DataRow, and DataTable This section provides an example of how you can use the DataColumn, DataRow, and DataTable client classes in your own client-side code In Chapter 10, we implemented a custom client control named CustomTable that uses the ASP.NET AJAX type inspection capabilities to display data records of any type This custom client control exposes a method named dataBind that iterates through the data records to display them, as shown in Listing 11-32 Listing 11-32: The dataBind Method of the CustomTable Client Control function CustomComponents$CustomTable$dataBind() { var sb = new Sys.StringBuilder(‘’); var propertyNames = []; for (var i=0; i

Ngày đăng: 09/08/2014, 06:23

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan