Programando la Ribbon en SharePoint 2010

Escrito por  Juan Pablo Pussacq

​Es bastante común que se necesiten agregar botones a la barra de herramientas de SharePoint 2010 (RIBBON). Muchas veces esto se resuelve en forma declarativa o con SharePoint Designer, pero otras veces necesitamos ir un poco más allá, por ejemplo, ejecutar código C# luego de presionar un botón o lograr que el botón este asociado a una lista específica y no a un tipo de lista. En este artículo veremos un ejemplo de cómo lograr este tipo de programación con Visual Studio. ¡Que lo disfruten!

El objetivo

Nuestro objetivo es agregar tres botones a la página de edición de una lista en particular. Esos tres botones estarán agrupados bajo un mismo título tal como muestra la imagen 1:

Imagen 1.- Botones agregados a la Ribbon.

Al presionar el botón, se abre una página ASPX en C# que nos permite trabajar con la API de SharePoint tal como muestra la imagen 2:

Imagen 2 .- Página de aplicación llamada desde el botón de la Ribbon.

¿Cómo agregar los botones?

Los botones suelen agregarse en forma declarativa, pero en este caso lo haremos mediante código C# para poder agregarlos en una lista en particular, y no en un tipo de lista. En este caso lo haremos a través de un evento de activación de feature. Esto puede verse en esta parte del código:

1public override void FeatureActivated(SPFeatureReceiverProperties properties)
2
1        {
2
1            using (SPWeb mi_web = (properties.Feature.Parent as SPSite).OpenWeb())
2
1            {
2
1 
2
1                // Agrego botones personalizados para la edición del Proyecto
2
1                mi_web.AllowUnsafeUpdates = true;
2
1                SPList lista = mi_web.GetList("/Lists/Proyectos");
2
1                var action = lista.UserCustomActions.Add();
2
1                action.Location = "CommandUI.Ribbon.EditForm";
2
1                action.Sequence = 10;
2
1                action.Title = "SURPOINT";
2
1                action.CommandUIExtension = @"
2

Observar especialmente como agregar los botones en la página de edición de la lista: "CommandUI.Ribbon.EditForm".

Dos puntos adicionales:

  • Los botones estarán dentro de un grupo
  • Al presionar el botón ejecutamos código JavaScript para llamar a una página ASPX.

Esa página ASPX se carga en una ventana modal. Además, se controla el resultado de esa ventana para decidir si se cierra o no la pantalla de Edición del ítem. Esto puede verse en esta línea de código:

1CommandAction=""javascript:
2
1elID = _spGetQueryParam('id');
2
1       var dlg=SP.UI.ModalDialog.showModalDialog({url: '{SiteUrl}/_Layouts/EMP_Procesos/VincularProyecto.aspx?ProjectId='+elID, dialogReturnValueCallback:function(res, val) { if (res == 1) window.frameElement.commonModalDialogClose(1, 0); } });
2
1"" />
2

El siguiente es el código completo para agregar los botones:

1public override void FeatureActivated(SPFeatureReceiverProperties properties)
2
1        {
2
1            using (SPWeb mi_web = (properties.Feature.Parent as SPSite).OpenWeb())
2
1            {
2
1 
2
1                // Agrego botones personalizados para la edición del Proyecto
2
1                mi_web.AllowUnsafeUpdates = true;
2
1                SPList lista = mi_web.GetList("/Lists/Proyectos");
2
1                var action = lista.UserCustomActions.Add();
2
1                action.Location = "CommandUI.Ribbon.EditForm";
2
1                action.Sequence = 10;
2
1                action.Title = "SURPOINT";
2
1                action.CommandUIExtension = @"
2
1                <CommandUIExtension>
2
1                      <CommandUIDefinitions>
2
1                        <CommandUIDefinition Location=""Ribbon.Templates._children"">
2
1                          <GroupTemplate Id=""Ribbon.Templates.CustomTemplate"">
2
1                            <Layout Title=""NewGroupInExistingTabOneLarge"" LayoutTitle=""NewGroupInExistingTabOneLarge"">
2
1                              <Section Alignment=""Top"" Type=""OneRow"">
2
1                                <Row>
2
1                                  <ControlRef DisplayMode=""Large"" TemplateAlias=""Button1"" />
2
1                                  <ControlRef DisplayMode=""Large"" TemplateAlias=""Button2"" />
2
1                                  <ControlRef DisplayMode=""Large"" TemplateAlias=""Button3"" />
2
1                                </Row>
2
1                              </Section>
2
1                            </Layout>
2
1                          </GroupTemplate>
2
1                        </CommandUIDefinition>
2
1                        <CommandUIDefinition Location=""Ribbon.ListForm.Edit.Scaling._children"">
2
1                          <MaxSize
2
1                            Id=""Ribbon.ListForm.Edit.MaxSize""
2
1                            Sequence=""15""
2
1                            GroupId=""Ribbon.ListForm.Edit.Groups.CustomGroup""
2
1                            Size=""NewGroupInExistingTabOneLarge"" />
2
1                        </CommandUIDefinition>
2
1                        <CommandUIDefinition Location=""Ribbon.ListForm.Edit.Groups._children"">
2
1                          <Group Id=""Ribbon.ListForm.Edit.Groups.CustomGroup""
2
1                            Sequence=""100"" Title=""SURPOINT""
2
1                            Description=""SURPOINT""
2
1                            Template=""Ribbon.Templates.CustomTemplate"">
2
1                            <Controls Id=""Ribbon.ListForm.Edit.Groups.CustomGroup.Controls"">
2
1                                <Button
2
1                                Id=""Ribbon.ListForm.Edit.Groups.CustomGroup.Controls.Button""
2
1                                Alt=""Vincular a sitio de proyecto""
2
1                                Sequence=""1""
2
1                                Image32by32=""/_layouts/images/newweb32.png""
2
1                                Image16by16=""/_layouts/images/SharePointFoundation10.png""
2
1                                Command=""vincularSitio""
2
1                                LabelText=""Sitio de proyecto""
2
1                                TemplateAlias=""Button1""
2
1                                CommandType=""General""/>
2
1                                <Button
2
1                                Id=""Ribbon.ListForm.Edit.Groups.CustomGroup.Controls.Button2""
2
1                                Alt=""Agregar a informe de portfolio""
2
1                                Sequence=""2""
2
1                                Image32by32=""/_layouts/images/uploaddoc.png""
2
1                                Image16by16=""/_layouts/images/SharePointFoundation10.png""
2
1                                Command=""agregarInforme""
2
1                                LabelText=""Agregar a portfolio""
2
1                                TemplateAlias=""Button2""
2
1                                CommandType=""General""/>
2
1                                <Button
2
1                                Id=""Ribbon.ListForm.Edit.Groups.CustomGroup.Controls.Button3""
2
1                                Alt=""Quitar de informe de portfolio""
2
1                                Sequence=""3""
2
1                                Image32by32=""/_layouts/images/mewa_backb.gif""
2
1                                Image16by16=""/_layouts/images/SharePointFoundation10.png""
2
1                                Command=""quitarInforme""
2
1                                LabelText=""Quitar de portfolio""
2
1                                TemplateAlias=""Button3""
2
1                                CommandType=""General""/>
2
1                            </Controls>
2
1                          </Group>
2
1                        </CommandUIDefinition>
2
1                      </CommandUIDefinitions>
2
1                      <CommandUIHandlers>
2
1                        <CommandUIHandler
2
1                         Command=""vincularSitio""
2
1                         CommandAction=""javascript:
2
1                                elID = _spGetQueryParam('id');
2
1                                var dlg=SP.UI.ModalDialog.showModalDialog({url: '{SiteUrl}/_Layouts/EMP_Procesos/VincularProyecto.aspx?ProjectId='+elID, dialogReturnValueCallback:function(res, val) { if (res == 1) window.frameElement.commonModalDialogClose(1, 0); } });
2
1                                "" />
2
1                        <CommandUIHandler
2
1                         Command=""agregarInforme""
2
1                         CommandAction=""javascript:
2
1                                elID = _spGetQueryParam('id');
2
1                                var dlg=SP.UI.ModalDialog.showModalDialog({url: '{SiteUrl}/_Layouts/EMP_Procesos/proyectoInforme.aspx?Accion=agregar&amp;ProjectId='+elID, dialogReturnValueCallback:function(res, val) { if (res == 1) window.frameElement.commonModalDialogClose(1, 0); } });
2
1                                "" />
2
1                        <CommandUIHandler
2
1                         Command=""quitarInforme""
2
1                         CommandAction=""javascript:
2
1                                elID = _spGetQueryParam('id');
2
1                                var dlg=SP.UI.ModalDialog.showModalDialog({url: '{SiteUrl}/_Layouts/EMP_Procesos/proyectoInforme.aspx?Accion=quitar&amp;ProjectId='+elID, dialogReturnValueCallback:function(res, val) { if (res == 1) window.frameElement.commonModalDialogClose(1, 0); } });
2
1                                "" />
2
1                      </CommandUIHandlers>
2
1                    </CommandUIExtension>
2
1                ";
2
1                action.Update();
2
1                mi_web.AllowUnsafeUpdates = false;
2
1            }
2
1        }
2

Las páginas de aplicación

Las páginas que son llamadas desde la RIBBON son páginas de aplicación típicas de SharePoint. Ejecutan el código C# que necesitemos. Sólo tenemos que tener en cuenta que deben encargarse de cerrar la pantalla modal. A modo ilustrativo, muestro parte del código de carga de la página:

1protected void Page_Load(object sender, EventArgs e)
2
1        {
2
1            if (!IsPostBack)
2
1            {
2
1               
2
1                // Obtener el ID del proyecto recibido como parámetro
2
1                string proyecto = "";
2
1                proyecto = Page.Request.QueryString["ProjectId"];
2
1 
2
1                // Datos del actual sitio elegido
2
1                string idSitio = "";
2
1                using (SPSite sitio = new SPSite(SPContext.Current.Site.Url))
2

(…)

Y lo más importante la parte final del evento OnClick del botón de nuestra página:

1protected void vincularSitio(object sender, EventArgs e)
2
1        {
2
1(..(
2
1            this.Page.Response.Clear();
2
1            this.Page.Response.Write("<script type='text/javascript'>window.frameElement.commonModalDialogClose(1, 1);</script>");
2
1            this.Page.Response.End();
2
1        }
2

Utilizamos commonModalDialogClose  para cerrar la ventana.

Conclusión

En este breve artículo vimos que no es tan complejo agregar componentes avanzados en la RIBBON de SharePoint. La posibilidad de ejecutar código C# de servidor, nos abre un abanico de posibilidades para extender nuestros sitios. Y lo que es más importante, se hace de una forma que resulta bastante amigable para el usuario, ya que la RIBBON es una barra que se ha acostumbrado a utilizar.

¡Hasta la próxima!

Juan Pablo Pussacq Laborde SharePoint MVP Blog: http://surpoint.blogspot.com