​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
1Â2
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
1Â2
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
1Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â2
1               // Obtener el ID del proyecto recibido como parámetro2
1Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â string proyecto = "";2
1Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â proyecto = Page.Request.QueryString["ProjectId"];2
1Â2
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