Archive

Archive for 13 marzo 2011

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!