Inicio > Apunte, C#, Microsoft Office SharePoint Server, SharePoint, Windows SharePoint Services > Utiliza SPGridView para crear WebParts personalizados

Utiliza SPGridView para crear WebParts personalizados


Dada la cantidad de clases que contiene el API de SharePoint, a veces es imposible revisar cada uno de sus componentes, y desafortunadamente dejamos de lado algunos muy valiosos. Y cuando llega el momento, nos vemos en la necesidad de reinventar la rueda.

Un caso que me ha pasado seguido es cuando tengo que crear un WebPart que contenga una tabla donde se muestren datos. Al principio, mi insinto me decía: crea el HTML a mano. Con el paso del tiempo, mi instinto cambió su consejo: “no seas güey y mejor utiliza un GridView”. Eso está mucho mejor. Ambos enfoques, empero, presentan un problema primordial: no lucen como controles de SharePoint. Entonces hay que simularlo: al construir el HTML ó el GridView, hay que utilizar todas las clases de estilo (CSS) que el mismo SharePoint emplea.

Pues bien, hace poco para un proyecto tuve una situación similar. Y se me topé, torpe de mí, con un control similar al GridView de ASP.NET de toda la vida. De hecho, este control deriva de GridView, y se llama, sorprendentemente, SPGridView, dentro de Microsoft.SharePoint.WebControls, en la librería Microsoft.SharePoint.dll distribuída con Windows SharePoint Services 3.0 (y, presumo, con SharePoint Foundation 2010).

Utilizar SPGridView es exactamente igual a utilizar GridView, con algunas pequeñas diferencias. Vamos paso a paso. En primer lugar, tenemos la siguiente lista.

SPGridView1

Lo siguiente que debemos hacer es crearnos un miembro privado tipo SPGridView, cuyo espacio de nombres es Microsoft.SharePoint.WebControls. Posteriormente, sobreescribimos el método CreateChildControls. Nuestra clase, al momento, luce así.

using System;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;

namespace Fermasmas.Wordpress.Com.WebParts
{
    public class GridViewExample : WebPart
    {
        private SPGridView _gridView;
        private Literal _titleLiteral;

        public GridViewExample()
            : base()
        {
        }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            SPList list = SPContext.Current.Web.Lists["Asgard Pantheon"];

            _titleLiteral = new Literal();
            _titleLiteral.Text = string.Format("<br/><h2>{0}</h2>", list.Title);
            Controls.Add(_titleLiteral);
        }
    }
}

Después de instanciar SPGridView, necesitamos asignar algunas propiedades. En particular, AutoGenerateColumns debe ser falso, siempre, o si no el control lanzará una excepción.

protected override void CreateChildControls()
{
    base.CreateChildControls();

    SPList list = SPContext.Current.Web.Lists["Asgard Pantheon"];

    _titleLiteral = new Literal();
    _titleLiteral.Text = string.Format("<br/><h2>{0}</h2>", list.Title);
    Controls.Add(_titleLiteral);

    _gridView = new SPGridView();
    _gridView.ID = "_gridView";
    _gridView.AutoGenerateColumns = false;
    _gridView.Width = new Unit(100, UnitType.Percentage);
            
    Controls.Add(_gridView);
}

Ahora, necesitamos crear las columnas a las que estarán ligados. Para ello, cada columna deberá ser de tipo SPBoundField, y debemos establecer la propiedad DataField al nombre de la columna de la lista a la que queremos enlazar.

protected override void CreateChildControls()
{
    base.CreateChildControls();

    SPList list = SPContext.Current.Web.Lists["Asgard Pantheon"];

    _titleLiteral = new Literal();
    _titleLiteral.Text = string.Format("<br/><h2>{0}</h2>", list.Title);
    Controls.Add(_titleLiteral);

    _gridView = new SPGridView();
    _gridView.ID = "_gridView";
    _gridView.AutoGenerateColumns = false;
    _gridView.Width = new Unit(100, UnitType.Percentage);
            
    _gridView.Columns.Add(
        new SPBoundField { DataField = "Title", HeaderText = "Name" });
    _gridView.Columns.Add(
        new SPBoundField { DataField = "Gender", HeaderText = "Gender" });
    _gridView.Columns.Add(
        new SPBoundField { DataField = "Influence", HeaderText = "Influence" });
    _gridView.Columns.Add(
        new SPBoundField { DataField = "Mate", HeaderText = "Mate" });
            
    Controls.Add(_gridView);
}

También podemos establecer la propiedad HeaderText al nombre que queremos muestre nuestro grid.

Ahora, solo necesitamos enlazar el control con una fuente de datos. SPList tiene una propiedad Items, de tipo SPListItemCollection, la cual tiene un método llamado GetDataTable, el cual regresa –sorpresa sorpresa- un objeto tipo DataTable. Usaremos dicho objeto para el DataSource del grid, e invocaremos al método DataBind.

protected override void CreateChildControls()
{
    base.CreateChildControls();

    SPList list = SPContext.Current.Web.Lists["Asgard Pantheon"];

    _titleLiteral = new Literal();
    _titleLiteral.Text = string.Format("<br/><h2>{0}</h2>", list.Title);
    Controls.Add(_titleLiteral);

    _gridView = new SPGridView();
    _gridView.ID = "_gridView";
    _gridView.AutoGenerateColumns = false;
    _gridView.Width = new Unit(100, UnitType.Percentage);
    _gridView.DataSource = list.Items.GetDataTable();
    _gridView.Columns.Add(
        new SPBoundField { DataField = "Title", HeaderText = "Name" });
    _gridView.Columns.Add(
        new SPBoundField { DataField = "Gender", HeaderText = "Gender" });
    _gridView.Columns.Add(
        new SPBoundField { DataField = "Influence", HeaderText = "Influence" });
    _gridView.Columns.Add(
        new SPBoundField { DataField = "Mate", HeaderText = "Mate" });
            
    _gridView.DataBind();
    Controls.Add(_gridView);
}

Ya por último, comentar que puedes agregar cualquier otro tipo de columna, como por ejemplo, un CommandField para poder agregar comandos. De hecho, agregaremos uno para poder seleccionar las filas, es decir, un select command.

protected override void CreateChildControls()
{
    base.CreateChildControls();

    SPList list = SPContext.Current.Web.Lists["Asgard Pantheon"];

    _titleLiteral = new Literal();
    _titleLiteral.Text = string.Format("<br/><h2>{0}</h2>", list.Title);
    Controls.Add(_titleLiteral);

    _gridView = new SPGridView();
    _gridView.ID = "_gridView";
    _gridView.AutoGenerateColumns = false;
    _gridView.Width = new Unit(100, UnitType.Percentage);
    _gridView.DataSource = list.Items.GetDataTable();
    _gridView.Columns.Add(new CommandField {
        ButtonType = ButtonType.Image,
        ShowSelectButton = true,
        SelectImageUrl = "/_layouts/images/arrowright_light.gif"
    });
    _gridView.Columns.Add(
        new SPBoundField { DataField = "Title", HeaderText = "Name" });
    _gridView.Columns.Add(
        new SPBoundField { DataField = "Gender", HeaderText = "Gender" });
    _gridView.Columns.Add(
        new SPBoundField { DataField = "Influence", HeaderText = "Influence" });
    _gridView.Columns.Add(
        new SPBoundField { DataField = "Mate", HeaderText = "Mate" });
            
    _gridView.DataBind();
    Controls.Add(_gridView);
}

Así, solo resta añadir el WebPart a nuestro sitio. Así es como luce en mi máquina virtual.

SPGridView2

Y be done with it!

  1. Alan
    diciembre 11, 2012 a las 11:36 am

    Excelente tu blog!!! Y no te sientas mal, yo creo que todos los que trabajamos en IT en algún momento tenemos ese sentimiento de aaaaa que guey estoy, cómo pude hacer eso jajaja Recientemente me tope con un requerimiento de tener Grupos y Sub-Grupos en una sola vista, por ejemplo:

    Continente Americano
    Pais Mexico
    Ciudad Guadalajara
    Ciudad Monterrey
    Ciudad Hermosillo

    País Estados Unidos
    Ciudad Chicago
    Ciudad Houston
    Ciudad Madison

    De tal forma que el continente es el Grupo Mayor y los Paises son los Sub-Grupos.

    Como es sabido el SPGridView no da la opción de sub-grupos, y después de buscar y buscar solo encontré referencias a poner otro Grid View (Hijo) dentro de una columna del Grid View Padre.

    Es posible anidar un Grid View como un ROW de la tabla? Hay alguna forma que no requiera crear la Tabla en HTML desde cero?

  2. diciembre 13, 2012 a las 9:28 pm

    Jejeje gracias por tus comentarios! En principio, es posible añadir un SPGridView a una celda, al final es cuestión de hacer el Controls.Add sobre la celda. Pero el problema es que el SPGridView mete mucho código, más que una simple tabla HTML, incluyendo scripts, por lo que el HTML generado va a salir muy mal.

    Ante esto, lo que te recomendaría es que usaras un objeto Table e hicieras un DataBind. El Table va a meter puro código HTML de tabla (un panel por ahí, pero básicamente es una tabla HTML) y creo que podrías controlar bien el display mediante propiedades CSS. Pero con el DataBind ya no es necesario que crees la tabla desde cero, y haces el Controls.Add sobre el table para que se genere en automático.

    ¡Saludos!

  1. mayo 30, 2011 a las 1:37 pm

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s