Inicio- Presentaciones- Artículos- Utilidades- Links- Contacto- Acerca de...

Publicado el 09/Nov/2005

He estado probando un poco el desarrollo de aplicaciones Web con ASP.NET 2.0 y una de las cosas que más me gustan es el poder usar las capacidades de DataBinding de los controles para vincularlas a objetos en lugar de a bases de datos.

Una de las cosas que quería probar era ver si podía vincular un control de tipo GridView a unos objetos que creé hace tiempo que obtienen leen RSS. Estos objetos conectan con un documento RSS cualquiera y obtienen sus elementos en una colección, en el número que se le pida (por ejemplo los 3 últimos elementos).

Teniendo en cuenta esto, mi primera prueba fue intentar usar el asistente que trae Visual Studio 2005 para vincular controles a datos y seleccionar la plantilla de ObjectDataSource. Este asistente pide que se seleccione la clase que contiene los objetos a vincular, el nombre del método a llamar en esa clase y sus parámetros para obtener los datos que se mostrarán en el control deseado.

Esto aparentemente funciona sin más pero al intentar ejecutar la página apareció la excepción 'No parameterless constructor defined for this object'. En efecto, mi objeto no tiene un constructor por omisión sin parámetros. Mi objeto en concreto funciona pasándole unos parámetros al constructor que indican dónde está el documento RSS, el nombre de usuario y contraseña si son necesarios, etc. Una vez construida la instancia, se puede llamar al método que carga los datos.

Buscando en las propiedades del control proporcionado por Visual Studio no encontré ninguna forma de pasarle una instancia. Leyendo posteriormente la documentación, se indica que cuando se usa este origen de datos, el objeto ObjectDataSource crea una nueva instancia del componente que conecta a los datos llamando a su constructor sin parámetros. Después llama al método dado con los parámetros que se le pasen. Esto no me vale para mi objeto. Por otro lado parece bastante poco flexible ya que (al menos en mi caso) en la mayoría de los objetos que conectan a datos, antes de poder conectar establezco valores en propiedades que luego las instancias de los objetos usan para trabajar. Con el modelo planteado eso tampoco funcionaría.

Pero como no me gusta darme por vencido tan fácilmente, probé a usar el objeto ObjectDataSource directamente en el código de la página y ¡bingo!, existe un evento al que nos podemos suscribir para modificar la instancia que ObjectDataSource utiliza. El proceso es el siguiente:

• Crear una instancia de ObjectDataSource indicándole la clase  que ha de usar y el nombre del método a llamar que traerá los datos.
• Indicarle el nombre y valores de los parámetros que necesita el método anterior para traer los datos.
• Crear un handler para el evento ObjectDataSource.ObjectCreating. En este handler se tiene acceso a la instancia que se va a usar, pudiendo sustituirla.
• Usar la instancia que hayamos creado de ObjectDataSource como origen de datos del control que se vaya a usar.
• Llamar a DataBind en el control, esto hará que se ejecute el método que conecta con los datos

En código C# sería algo así:

protected void Page_Load(object sender, EventArgs e)
{
    // Una instancia de mi objeto
    _blogClient = new BlogClient(p1, p2, p3, p4);

    // Creo el ObjectDataSource indicándole la clase a usar
    ObjectDataSource ods = new ObjectDataSource("Caladan.BlogClient.BlogClient", "GetRssEntries");
    ods.SelectParameters.Add("ItemCount", "5");

    // Establezco el handler
    ods.ObjectCreating += new ObjectDataSourceObjectEventHandler(ods_ObjectCreating);

    // Vinculo al control Web (un DataList en este caso)
    dlBlog.DataSource = ods;
    dlBlog.DataBind();
}

void ods_ObjectCreating(object sender, ObjectDataSourceEventArgs e)
{
    // Aquí se tiene acceso a la instancia, que modifico por la mía ya creada
    e.ObjectInstance = _blogClient;
}

Y ya está, con estos simples pasos se pueden usar todas las técnicas de data binding del control Web pero con un origen de datos que no es una base de datos. Tengo que hacer notar que el resultado de la llamada a GetRssEntries (el método de mi objeto que lee el RSS) es una colección de tipo CollectionBase, con lo que la iteración entre los distintos elementos ya viene dada (por implementar IEnumerable).

No se a vosotros, pero a mí esto me ayuda bastante…

Archivado como: .NET