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:
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:
¿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
12
1 // Agrego botones personalizados para la edición del Proyecto2
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:
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
12
1 // Agrego botones personalizados para la edición del Proyecto2
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 <MaxSize2
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 <Button2
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 <Button2
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 <Button2
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 <CommandUIHandler2
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 <CommandUIHandler2
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&ProjectId='+elID, dialogReturnValueCallback:function(res, val) { if (res == 1) window.frameElement.commonModalDialogClose(1, 0); } });2
1 "" />2
1 <CommandUIHandler2
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&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
12
1 // Obtener el ID del proyecto recibido como parámetro2
1 string proyecto = "";2
1 proyecto = Page.Request.QueryString["ProjectId"];2
12
1 // Datos del actual sitio elegido2
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