Tutorial de ASP.NET
Vista Previa de ASP.NET 2.0

Escenarios de Datos Avanzados

Este apartado nos muestra cómo podemos usar algunas de las características menos obvias de los controles de datos para implementar escenarios.

Manejando Valores Nulos

Los controles de datos soportan varios tipos de formas para tratar los datos nulos o inexistentes. Para empezar, GridView, FormView y DetailsView soportan las propiedades EmptyDataText o EmptyDataTemplate, que podemos usar para especificar una representaxión para el control cuando la fuente de datos no devuelve ninguna fila de datos. Basta con fijar EmptyDataText o EmptyDataTemplate (EmptyDataTemplate predomina cuando se establecen ambos). También podemos especificar la propiedad ConvertEmptyStringToNull en BounFienld (y cualquier tipo derivado), en TemplateField o en objetos de parámetros de fuente de datos, para especificar dicha cadena. Los valores vacíos enviados desde el cliente deben convertirse a nulls antes de invocar la operación de la fuente de datos ascociada. ObjectDataSource también soporta la propiedad ConvertNullToDbNull que se puede establecer a "true" cuando el método asociado espera parámetros "DbNull" en lugar de "null" (las clases TableAdapter del DataSet de VisualStudio tienen este requerimiento).También podemos especificar la propiedad NullDisplayText en BoundField (y los tipos de campos derivados) para especificar un valor para el campo a mostrar cuando el campo "value" de la fuente de datos se devuelve como nulo. Si este valor no se cambia en el modo de edición, el valor se enviará de vuelte como "null" a la fuente de datos durante la operación de actualización. Por último, también podemos especificar la propiedad DefaultValue en los parámetros de la fuente de datos para especificar un valor por defecto para el parámetro cuando el valor pasado para él en nulo. Estas propiedades pueden encadenarse, por ejemplo, si se establece tanto ConvertEmptyStringToNull como DefaultValue, el valor String.Empty se convertirá primero a "null" y después al valor por defecto.

C# Trantanto con Valores Nulos



Podemos utilizar estas propiedades para manejar valores nulos para implementar un filtro para una DropDownList que inicialmente muestre todos los valores de la fuente de datos hasta que se seleccione un valor de filtrado. Ésto se consigue añadiendo un elemento a la DropDownList con un valor de cadena vacío y seleccionando la propiedad ConvertEmptyStringToNull en el ControlParameter asociado a la DropDownList en la fuente de datos. Después en el SelectCommand de la fuente de datos podremos buscar el valor nulo para devolver todos los valores (no filtrados). El siguiente ejemplo muestra esta técnica usando un sencillo comando SQL, aunque también podríamos buscar el valor nulo en la implementación de un procedimiento almacenado. Observad el uso de la propiedad AppendDataBoundItems del DropDownList, que permite agregar los valores obtenidos de la fuente de datos de la DropDownList al elemento "ALL", añadido estáticamente en el grupo de Items. Observad también que por defecto el SqlDataSource no realiza una operación de Select si alguno de los parámetros asociados al SelectCommand son nulos. Para permitir que la operación de "select" se ejecute aún cuando se le pase algún parámetro nulo, podemos establecer la propiedad CancelSelectOnNullParameter a false.

C# Mostrar Todos los Valores en una Selección Nula


"Master Details" Avanzados

En los anteriores capítulos de este tutorial hemos visto como se puede implementar un escenario de "master-details" asociando un ControlParameter a la propiedad SelectedValue del GridView. La propiedad SelectedValue devuelve el valor del primer campo especificado por la propiedad DataKeyNames. También podemos especificar múltiples valores de un campo, separándolos por comas, para la propiedad DataKeyNames, por ejemplo si necesitamos pasar más de un campo a la fuente de datos de detalles (Details) en un escenario master-details. Los valores de estos campos clave adicionales son accesibles a través de la propiedad SelectedDataKey, que devuelve un objeto DataKey de duplas nombre/valor para los campos clave. Un ControlParameter puede hacer referencia a estas claves estableciendo la propiedad PropertyName a una expresión, como SelectedDataKey.Values("title_id").
  <asp:ControlParameter Name="FirstKey" ControlID="MasterGrid" PropertyName="SelectedDataKey.Values[0]"/>
<asp:ControlParameter Name="SecondKey" ControlID="MasterGrid" PropertyName="SelectedDataKey.Values[1]"/>
El siguiente ejemplo muestra el código para enumerar el grupo de DataKeys y obtener los valores de los campos claves del SelectDataKey del GridView.

C# DataKeys


Los anteriores ejemplos de master-details de este tutorial nos mostraban el control "details" como un control separado del formulario, pero otra forma común de implementación de "master-details" es mostrando el control details como un control anidado que es parte de la representación del control "master". Para ésto, necesitamos que ambos controles, el "details" y su fuente de datos asociada estén contenidos en una plantilla del control "master", con un parámetro de la fuente de datos que obtiene su valor de un campo de la fuente de datos del "master". Debido a que no hay un objeto de parámetro declarativo que se pueda asociar de esta manera, tendremos que estableces el valor programándolo en código. Podermos hacer esto manejando un evento en el control "master" para establecer el valor del parámetro cuando un elemento del control "master" está enlazado a datos, por ejemplo en el evento DataBound del FormView. El siguiente ejemplo muestra esta técnica.

C# Master-Details Anidados



El siguiente ejemplo nos muestra una técnica similar usando DataList, manejando el evento ItemDataBound de DataList para establecer los detalles del valor del parámetro de la fuente de datos.

C# Master-Details Anidados (DataList)


Manejando Eventos de Controles de Datos

Ya hemos visto varios ejemplos de eventos de controles de datos en las anteriores secciones del tutorial. En teoría, los eventos de controles de datos nos proporcionan los lugares en los que podemos insertar nuestro propio código, en el ciclo de vida de la página. Los controles de datos dan acceso a eventos tanto antes como después de que se produzca una operación. Los eventos que se ejecutan antes de una operación se suelen nombrar con el sufijo -ing, mientras que los que se dan después de la operación se nombran con el sufijo -ed. Los eventos que soporta el GridView incluyen, por ejemplo:

  • PageIndexChanging y PageIndexChanged - Después de una operación de paginación
  • SelectedIndexChanging y SelectedIndexChanged - Antes y después de que se produzca una selección
  • Sorting y Sorted - Antes y después de una operación de clasificación
  • RowEditing y RowCancelingEdit - Antes de que una fila se ponga en modo edición o antes de la cancelación del modo de edición.
  • RowUpdating y RowUpdated - Antes y después de una operación de actualización
  • RowDeleting y RowDeleted - Antes y después de una operación de borrado
  • RowDataBound - Cuando una fila es enlazada a datos
  • RowCreated - Cuando una fila se crea para representación (como una TableRow)
  • RowCommand - Cuando se "lanza" un comando "button" desde el control

Los controles de la fuente de datos también hacen accesibles eventos, similares a los eventos de controles vinculados a datos. Tanto el SqlDataSource como el ObjectDataSource soportan los siguientes eventos:

  • Selecting y Selected - Antes y después de una operación de selección
  • Updating y Updated - Antes y después de una operación de actualización
  • Deleting y Deleted - Antes y después de una operación de borrado
  • Inserting y Inserted - Antes y después de una operación de inserción
  • Filtering - Antes de una operación de filtrado

El control ObjectDataSource también da acceso a eventos cuando el objeto que especificamos en la propiedad TypeName es creado o destruido. En realidad podemos fijar un objeto personalizado en el evento ObjectCreating estableciendo la propiedad ObjectInstance de los argumentos del evento que hemos pasado.

  • ObjectCreating y ObjectCreated - Antes y después de la creación del objeto
  • ObjectDisposing - Antes de que se elimine el objeto

Normalmente los eventos que se lanzan antes de que se produzaca una operación se utilizan para cancelar la operación, estableciendo la propiedad Cancel de los eventos a true, o para realizar una validación o manipulación de los parámetros. Los eventos que se lanzan después de una operación se usan para escribir código personalizado en respuesta a cierta operación, o para comprobar el éxito de la operación. Por ejemplo, podemos comprobar el RowsAffected producido por una operación de Actualización, Inserción o Borrado o comprobar la propiedad Exception para determinar si se ha producido una excepción durante el procesado. También podemos establecer la propiedad ExceptionHandled del evento args para prevenis que la excepción se pase a la página de control. El siguiente ejemplo muestra los diferentes eventos de GridView y SqlDataSource que se pueden manejar y el orden relativo en el que se crean.

C# El Evento RowUpdating de GridView


A continuación, se muestra un manejo más práctico del evento Inserting de DetailView para la obtención de una foto enviada desde un control FileUpload, de dentro del DetailsView, para guardar los contenidos al disco antes de que el DetailsView complete la operación de inseción del registro correspondiente dicha fotografía en la base de datos. Por motivos demostrativos, el verdadero código de guardado se ha descomentado, pero se puede seguir probando este ejemplo especificando el nombre de la imagen ya existente "Winter.jpg".

C# El Evento ItemInserting de DetailsView



De forma similar al ejemplo anterior, este ejemplo muestra el manejo del evento -- del FormView para eliminar el ficher fotográfico asociado del disco, cuando se elimina el registro de dicha fotografía de la base de datos. De nuevo, se ha descomentado el verdadero código por motivos demostrativos.

C# El Evento ItemDeleted de FormView


 

Trabajando Con Parámetros

Podemos manejar los eventos de la operaciones Select, Update, Insert, Delete y Filter para validar y menipular los valores de los parámetros que se pasan a dichas operaciones. Tanto los controles enlazados a datos como los controles de la fuente de datos nos dan acceso a los eventos apropiados para estos propósitos. Por ejemplo, en el evento de Actualización del GridView, podemos ver los nombres y valores de los parámetros en los diccionarios de "keys", "NewValues" y "OldValues" que se envían a la fuente de datos. En el lado de la fuente de datos podemos manejar el evento "Updating" de SqlDataSource para ver estos parámetros como se aplican al objeto de comandos subyacente, que se ejecutará para completar la operación.De forma similar podemos manejar un evento "Updating" de SqlDataSource para ver o cambiar los diccionario de parámetros que se usarán para resolver la sobrecarga apropiada del UpdateMethod. Podemos usar estos eventos para añadir o eliminar parámetros de los diccionarios o comandos, cambiar sus valores o simplemente validar que los parámetros tengan un formato correcto.

Importante: Deberíamos validar especiamente los parámetros de entrada para el evento Filtering, el cual no obtiene SQL codificado antes de aplicarlo a la FilterExpression asociada al objeto DataView.

El siguiente ejemplo muestra como tratar varios eventos de controles de datos para enumerar los grupos de parámetros pasados a través del evento args. Observad que este ejemplo fija a falso la propiedad InsertVisible del BoundField asociado a la campo OrderID de la clave primaria, porque el campo OrderID es una entidad columna en la base de datos subyacente  y no debe pasarse a las operaciones de Inserción (la base de datos incrementa su valor automáticamente cuando se produce una inserción). Además hay que observar que el campo OrderID se marca como la clave primaria en DataKeyNames, de forma que el valor original de este campo se retiene en el diccionario de Keys (claves) que pasado por el control enlazado a datos. Los valores introducidos por el usuario a los controles de entrada se pasan en un diccionario de NewValues, a excepción de aquellos campos marcados como ReadOnly=false. Los valores originales para los campos no-claves también son retienen en un diccionario de OldValues por parte de los controles enlazados a datos para pasarlos a la fuente de datos. Estos valores de parámetros son añadidos al comando por el SqlDataSource en siguiente orden: NewValues, Keys, OldValues. Sin embargo, la fuente de datos no añade OldValues cuando en ConflictDetection se establece OverwriteChanges. Para más información de la utilización de OldValues por parte de la fuente de datos, acudid a la sección Utilizando Detección de Conflictos.


C# Parámetros de Datos



Podemos cambiar el orden en el que SqlDataSource agrega los parámetros al comando, añadiendo objetos Parameter estáticos al grupo de parámetros para una operación de la fuente de datos, en el orden que queramos. SqlDataSource reordena de forma automática los parámetros pasados en el control enlazado a datos de acuerdo al orden de los objetos Parameter. Ésto es útil cuando la propiedad ProviderName de la fuente de datos se establece a System.Data.OleDb, el cual no tiene soporte para los parámetros "nombrados" (named), de forma que el orden en el que se agregan los parámetros al comando debe coincidir con el de los parámetros de substitución anónimos ('?') en el comando. Cuando usamos parámetros "nombrados" (named), el orden de los parámetros es irrelevante. Podemos especificar la propiedad Type de un objeto Parameter para forzar que los valores que pasa el control enlazado a datos se conviertan al tipo de datos apropiado antes de ejecutar el comando o método. Asimismo, podemos establecer la propiedad Size de un Parameter para imponer el tamaño (Size) de el DbParameter en un comando SqlDataSource (requerido para entrada/salida, salida y devolver parámetros de valores).

C# Tipos y Orden de Parámetros


La convención por defecto para los nombres de los parámetros requiere que los nuevos parámetros se nombren de acuerdo con los campos seleccionados por la operación Select de la fuente de datos. Es posible renombrar los parámetros de Keys o OldValues para diferenciarlos de NewValues, especificando la propiedad OldValuesParameterFormatString, por ejemplo a "original_{0}". También podemos personalizar los nombres de los parámetros manejando un evento apropiado para cambiar el valor de un parámetro antes de que se ejecute una operación de la fuente de datos. Por ejemplo, si la operación de actualización de un SqlDataSource se asocia a un procedimiento almacenado que coge nombres de parámetros diferentes a aquellos que coinciden con la convención por defecto, podremos modificar los nombres de los parámetros en el evento Updating del SqlDataSource antes de llamar al procedimiento almacenado. El siguiente ejemplo nos muestra esta técnica.

C# Renombrando Parámetros




ObjectDataSource no depende de un orden particular de los parámetros, pero en lugar de eso busca un método que concuerde con los nombres de los parámetros. Observad que ObjectDataSource no usa el Tipo o el Tamaño de un parámetro para resolver la sobrecarga de métodos. Sólo se comprueban los nombres de los parámetros, de forma que si tenemos dos métodos en el objeto de negocio que tienen los mismos nombres de parámetros, aunque sean de tipos diferentes, ObjectDataSource no podrá distinguirlos. Podemos cambiar los nombres y valores de los praámetros de ObjectDataSource en eventos, de forma parecida al anterior ejemplo. Sin embargo, si usamos DataObjectTypeName para especificar un objeto de datos particular para pasarlo a las operaciones de Actualización, Inserción y Borrado, no podremos modificar los nombres de los parámetros, sólo los valores. Si necesitamos modificar los nombres de los parámetros, no usaremos DataObjectTypeName y, en su lugar, contruiremos manualmente, mediante código, los objetos de datos apropiados en los eventos de la fuente de datos.

Todos los parámetros de la fuente de datos que hemos estado utilizando tiene parámetros Input (de entrada), que se usan para pasar valores en una operación de la fuente de datos. Los parámetros también pueden ser bidireccionales, como InputOutput, Output y ReturnValue. Podemos especificar la dirección de un parámetro mediante la propiedad Direction del objeto. Para recuperar los valores de dichos parámetros cuando se acabe la operación de la fuente de datos, se maneja el evento de "post-operación" adecuado (por ejemplo Selected, Updated, Inserted o Deleted) para obtener el valor del parámetro desde los argumentos del evento que hemos pasado a los eventos. El SqlDataSourceStatusEventArgs tiene una propiedad Command, qué podemos usar para obtener los valores devueltos y los prámetros de salida, cómo veremos en el siguiente ejemplo. Observad que es importante fijar la propiedad Size del objeto Parameter en el SqlDataSource para que los parámetros bidireccionales tenga un valor apropiado.

C# Devolver Valores y Parámetros de Salida


El tipo ObjectDataSourceStatusEventArgs soporta un grupo de OutputParameters y devuelve la propiedad ReturnValue para este propósito, como veremos en el siguiente ejemplo. Observad que, en este caso, el valor devuelto por la operación Update se usa para determinar el número de filas afectadas por dicha operación. Para devolver este valor al control enlazado a datos (por ejemplo a través de la propiedad GridViewUpdatedEventArgs AffectedRows podemos establecer la propiedad AffectedRows del ObjectDataSourceStatusEventArgs a este valor de vuelta).

C# Devolver Valores y Parámetros de Salida (objeto)


Otro uso común de los parámetros de salida es obtener el valor de la clave primaria de una fila insertada en una base de datos qué es una columna Identify (en la que el valor clave no se especifica como un parámetro de insert, sinó que es generado automáticamente por el servidor de la base de datos cuando se produce una inserción). Este ejemplo muestra esta técnica.

C# Obteniendo la Identidad Después de una Inserción


Utilizando Detección de Conflictos

Cómo hemos dicho en anteriores secciones, el control enlazado a datos pasa valores a la fuente de datos en diccionarios de "Keys", "Values" (nuevos valores) y "OldValues" diferentes. Por defecto SqlDataSource y ObjectDataSource ignoran el diccionario de OldValues y, en su lugar, sólo aplican los de Keys y Values. Este comportamiento viene determinado por la propiedad ConflictDetection de la fuente de datos, que está fijada a OverwriteChanges por defecto. El modo OverwriteChanges consiste básicamente en que "sólo encontrar los valores de la claves primarias con el propósito de actualizar o eliminar un registro". Este comportamiento significa que el registro se actualiza o se elimina a pesar de si los valores subyacentes de dicho registro han cambiado. A menudo, es más deseable permitir la actualización o borrado cuando los valores de la fila coinciden exactamente con lo que se había seleccionado inicialmente. De esta forma, si otro usuario actualiza la fila mientras se selecciona la dila y se acualiza, nuestra operación de actualización fallará. Las fuentes de datos soportan ésto fijando la propiedad ConflictDetection a CompareAllValues. De esta forma, la fuente de datos aplica los parámetros OldValues al comando o método, qué los puede usar para asegurar que en las operaciones de actualización o borrado coinciden todos los valores del registro antes realizar las operaciones. También tendremos que establecer la propiedad OldValuesParameterFormatString a un formato de cadena del Framework .NET válido, por ejemplo "original_{0}", para indicar cómo se deberían renombrar los parámetros de los diccionarios de OldValues y Keys y poder diferenciarlos de los NewValues.

El siguiente código muestra los comandos SQL típicos para los modos OverwriteChanges y CompareAllValues del control SqlDataSource. El campo ID es la clave primaria. Observad que los comandos posteriores comparan los valores originarles de la fila en la claúsula WHERE, no en la clave primaria. En este caso, OldValuesParameterFormatString necesitaría establecerse a "original_{0}" en la fuente de datos.
SELECT [ID], [Name], [Address] from [Contacts]

-- OverwriteChanges
UPDATE [Contacts] SET [Name] = @Name, [Address] = @Address WHERE [ID] = @ID
DELETE FROM [Contacts] WHERE [ID] = @ID

-- CompareAllValues
UPDATE [Contacts] SET [Name] = @Name, [Address] = @Address WHERE [ID] = @original_ID
AND [Name] = @original_Name AND [Address] = @original_Address
DELETE FROM [Contacts] WHERE [ID] = @original_ID AND [Name] = @original_Name
AND [Address] = @original_Address
El siguiente ejemplo muestra las enumeraciones de parámetros en el nivel de los controles enlazados a datos y el de la fuente de datos, para los diccionarios de Keys, Values y OldValues, cuando ConflictDetection se establece a CompareAllValues. Por motivos demostrativos, las operaciones reales de Actualización, Borrado e Inserción se han cancelado. Observad también que no se requieren los OldValues para la operación de Inserción. ConflictDetection sólo tiene sentido para actualizaciones y Borrados.

C# Parámetros de Detección de Conflictos

 

El siguiente ejemplo muestra el comportamiento cuando se produce un conflicto. Para ejecutar este ejemplo, abrid dos instancias del ejemplo en ventanas diferentes del navegados (hacer clic en "Run It" dos veces). Después haced clic en el botón "Edit" para la misma fila en ambas ventanas, para que la fila se ponga en modo de edición. En la primera ventanacambiad un valor de la fila y haced clic en "Update", y observad como la actualización es exitosa. En la segunda ventana podéis entrar un nuevo valor para la misma fila y hacer clic en "update", pero la actualización no se producirá porque los valores de la fila se habían cambiado en la primera operación de actualización. El ejemplo comprueba que la propiedad AffectedRows del evento Updated o Deleted es 0 para confirmar que se ha producido un conflicto.

C# Detección de Conflictos (Update y Delete)



Cuando usamos UI basadas en plantillas para las actualizaciones o borrados, los valores antiguos se guardan en campos enlazados a datos en dos sentidos mediante sentencias Bind. Para los borrados, ésto significa que tendremos que usar sentencias Bind para enlazar a datos los valores en el ItemTemplate para guardar los antiguos valores para las operaciones de borrado. El siguiente ejemplo miestra esta técnica.

C# Detección de Conflictos Mediante Plantillas



Podemos manejar los erros en la detección de conflictos con elegancia dando al usuario la opción de realizar o abortar la operación cuándo la fila en implicada ha cambiado, mostrando los valores cambiados al usuario de forma que los pueda comparar con los de su actualización. El siguiente ejemplo muestra una posible aproximación al manejo de errores de la detección de errores. Observad que el evento RowUpdated del DetailsView pasa diccionarios que podemor utilizar para comprobar los valores introducidos por el usario. También podemos establecer la propiedad KeepInEditMode de este evento para mantener el DetailsView en modo de edición mientras que el usuari toma una decisión sobre cómo tratar el conflicto. Podéis ejercitar este ejemplo de la misma forma que el anterios, abriendo dos ventanas para crear un conflicto de actualizaciones.

C# Manejando Actualizaciones Conflictivas


El siguiente ejemplo muestro el mismo escenario utilizando ObjectDataSource. Observad que debido a que la propiedad ConflictDetection de la fuente de datos está establecida a CompareAllValues, la fuente de datos busca una sobrecarga de UpdateContact que accepte los valores originales para cada campo del objeto Contact.

C# Detección de Conflictos w/ObjectDataSource


También podemos usar la propiedad DataObjectTypeName conjuntamente con CompareAllValues. En este caso, ObjectDataSource busca una sobrecarga de UpdateContact que aceta exactamente dos parámetros, ambos del tipo Contact. El primet parámetro será un objeto Contact que contendrá los nuevos valores para la actualización, mientras que el segundo será un objeto Contact con los valores originales.

C# Detección de Conflictos w/ObjectDataSource (DataObjectTypeName)




Paginación/Clasificación Avanzada

La selección en el control GridView es un concepto puramente de UI, dónde la propiedad SelectedIndex corresponfe al índice de la fila seleccionada actualmente entre las filas visibles de la rejilla. Si permitimos la paginación y clasificación en la rejilla, el SelectedIndex de la rejilla se mantiene después de las operaciones de paginación o clasificación, de forma que una nueva fila se seleccionará después de dichas operaciones. En algunas circunstancias es mejor mantener la selección de una determinada fila incluso cuando esa fila no esté visible en la actual página de la rejilla. El siguiente ejemplo muestra una técnica para mantener la fila seleccionada después de las operaciones de clasificación o paginación.

C# Maintaniendo la Selección Después de la Clasificación



GridView y DetailsView soportan un modo especial para paginar y clasificar que aprovecha las llamadas del lado del cliente hacia el servidor para obtenes los datos para la nueva página o los datos clasificados recientemente. Para poder usar esta funcionalidad, tenemos que establecer la propiedad EnableSortingAndPagingCallbacks a true. Observad que cuando se realiza una operación de paginación o clasificación, la página no necesita enviar de vuelta para conseguir los nuevos valores (aunque se cree un script de callback hacia el servidor). Esta característica no está soportada cuando GridView o DetailsView contienen campos que siguen una plantilla. También se puede mostrar el botón en un CommandField cuando se permite esta característica.

C# Clasificar y Paginar Mediante Callbacks



Aunque GridView, DetailsView y FormView proporcionan una representación por defecto para la UI de paginación, también podemos personalizar la representación del paginador estableciendo la propiedad PagerTemplate. Dentro de esta plantilla podemos colocar controles Button con la propiedad CommandName fijada a Page, y la propiedad CommandArgument fijada a First, Prev, Next, Last o <number>, dónde <number> es un valor de un índice de página específico . Es siguiente ejemplo muestra un PagerTemplate definido tanto para el control GridView como para ed control DetailsView.

C# Plantilla de Paginador

Enlazando a Datos en Código

Cómo se dijo en la sección Datos en Plantillas, ASP.NET incluye una sintaxis declarativa de enlazado a datos para asociar los campos de la fuente de datos con las propiedades de los controles de una plantilla de enlazado a datos. También podemos usar la sintaxis <%# ... > para enlazar a datos valores arbitrarios en el código, como las propiedades Page y control, grupos, expresiones e, incluso, resultados devueltos por las llamadas a métodos. Para forzar el enlazado a datos a ser evaluado, tendremos que llamar al método DataBind en la página o control que contiene las expresiones de enlazado a datos. La siguiente tabla muestra algunos ejemplos de la sintaxis de enlazado a datos en ASP.NET.

Simple property Customer: <%# custID %>
Collection Orders: <asp:ListBox id="List1" datasource='<%# myArray %>' runat="server">
Expression Contact: <%# ( customer.FirstName + " " + customer.LastName ) %>
Method result Outstanding Balance: <%# GetBalance(custID) %>

Aunque esta sintaxis se parezca a la abreviatura de ASP para Response.Write (<%= %>) su comportamiento es totalmente diferente. Mientra que el ASP Response.Write se evalua cuando la página se procesa, la sintaxis de enlazado a datos de ASP.NET se evalua sólo cuando se invoca el método DataBind.

DataBind es un método de Page y todos los controles de servidor. Cuando llamamos a DataBind desde el control padre, él llamara a todos los "hijos" del control. Por ejemplo, DataList1.DataBind() invoca el método DataBind en cada uno de los controles de la plantilla del DataList. Llamando a DataBind en Page (Page.DataBind() o simplemente DataBind()) provoca que todas las expresiones de enlazado a datos de la página se evalúen. DataBind se suele llamar desde el evento Page_Load, cómo veremos en el siguiente ejemplo.
protected void Page_Load(Object Src, EventArgs E) {
DataBind();
}
Podemos utilizar una expresión de enlazado en prácticamente cualquier sitio de una sección declarativa de una página .aspx, siempre que evalúe el tipo de datos esperado en tiempo de ejecución. Los ejemplos de  propiedad, expresión y método simples mostrados arriba muestran texto al usuario cuando se evalúan. En estos casos, la expresión de enlazado a datos debe evaluarse a un valor del tipo String. En ejemplo de grupo, la expresión de enlazado a datos se evalúa a un valor de un tipo válido para la propiedad DataSource del ListBox. Encontraremos necesario obligar al tipo de valor en nuestra expresión de enlazado a producir el resultado deseado. Por ejemplo, si count es un integer:
Number of Records:  <%# count.ToString() %>
a sintaxis de enlazado a datos de ASP.NET soporta enlazar a variables públicas, propiedades de la Page y propiedades de otros controles de la página. El siguiente ejemplo muestra cómo enlazar a una variable pública y una propiedad simple de la página. Observad que estos valores se inicializan antes de llamar a DataBind().
The ASP.NET data binding syntax supports binding to public variables, properties of the Page, and properties of other controls on the page. The following example illustrates binding to a public variable and simple property on the page. Note that these values are initialized before DataBind() is called.

C# Enlazando a Datos a una Propiedad en la Página



El siguiente ejemplo muestra el enlace de un apropiedad de otro control.

C# Enlazando a Datos a una Porpiedad de Control de Servidor



Los controles de servidor del tipo lista, como DropDownList, ListBox y HTMLSelect utilizan un grupo como fuente de datos. El siguiente ejemplo muestra el enlazado a tipos de grupos usuales del lenguaje en tiempo de ejecución. Estos controles se pueden enlazar a grupos que soporten las interfaces IEnumerable, ICollection o IListSource. Más comunmente, enlazaremos a ArrayList, Hashtable, DataView y DataReader. El siguiente ejemplo muestrs el enlace a ArrayList.

C# Enlazando a Datos el DropDownList



El siguiente ejemplo muestra el enlazado a un DataView. Observad que la clase DataView se define en el espacio de nombres System.Data.

C# Enlazando a Datos a un DataView



El siguiente ejemplo muestra el enlazado a un Hashtable.

C# Enlazando a Datos a un Hashtable



A menudo queremos manipular los datos antes de enlazarlos a nuestra página o control. El siguiente ejemplo muestra el enlazafo a una expresión y el valor que devuelve un método.

C# Enlazando a Datos a Métodos y Expresiones



El Framework ASP.NET proporciona un método estático que evalua expresiones de enlazado a datos "late-bound" y opcionalmente da el formato de string al resultado. DataBinder.Eval es útil porque elimina gran parte del "casting" explícito que el desarrollador deber hacer para hacer que los valores sean del tipo deseado. Es particularmente útil cuando enlazamos a datos lo controles a una lista, ya que muchas veces los datos tanto de las filas como de los campos deben sufrir una conversión de tipos.

Considerad el siguiente ejemplo, en el que un integer se mostrará como un string. Con la sintaxis de enlaxzado a datos stándar de ASP.NET, debemos convertir el tipo de datos de la fila para poder obtener los datos del campo, IntegerValue. A continuación, es pasado como argumento al método String.Format.
 
<%# String.Format("{0:c}", ((DataRowView)Container.DataItem)["IntegerValue"]) %>

Esta sintaxis puede ser compleja y difícil de recordar. En cambio, DataBinder.Eval simplemente es un método con tres argumentos: en contenedor de nombre para el elemento de datos, el nombre del campo de datos y la cadena de formateo. En un control basado en plantilla como FormView, GridView, DetailsView, DataList o Repeater, el contenedor de nomre siempre es Container.DataItem. Page es otro contenedor de nombre que puede usarse con DataBinder.Eval. Cómo se ha dicho en la sección anterior, ASP.NET 2.0 también incluye una nueva sintaxis simplificada para DataBinder.Eval, simplemente Eval, que puede usarse dentro de una plantilla de un control enlazado a datos para resolver a un Container.DataItem automáticamente. La sintaxis simplificada de Eval se discute en la sección anterior, Enlazando d Datos en Plantillas.

<%# DataBinder.Eval(Container.DataItem, "IntegerValue", "{0:c}") %>
<%# Eval("IntegerValue", "{0:c}") %>

El argumento de formato de cadena es opcional. Si se omite, DataBinder.Eval devuelve un valor de clase objeto, como se muestra a continuación:
<%# (bool)DataBinder.Eval(Container.DataItem, "BoolValue") %>

Es importante observar que DataBinder.Eval puede acarrear un perjuicio notable en el rendimiento respecto a la sintaxis estándar de enlazado, debido a que usa reflexión "late-bound". Tenemos que tilizar DataBinder.Eval juiciosamente, especialmente cuando no necesitamos formateo de cadenas.

C# Enlazando a Datos Mediante DataBinder.Eval