Buscador

Cómo modificar la Ribbon en SharePoint 2010

abr. 17

Written by:
17/04/2012  RssIcon

En este segundo Post sobre la Ribbon, quiero mostrar las principales personalizaciones que como desarrolladores suelen ser interesantes para aplicar en proyectos de adaptación.

Las más habituales son:

  • Agregar un botón a un grupo existente
  • Deshabilitar o cambiar el comportamiento de un botón
  • Agregar un nuevo grupo

Cómo empezar

Por supuesto, para comenzar, necesitamos Visual Studio 2010, donde comenzaremos con un Empty Sharepoint Project.

Añadimos una nueva Feature, y elegimos el ámbito (Site, Web, Web Application).

Añadimos un Empty Element al proyecto, de modo que tendremos su correspondiente Elements.xml, el cual será la base para implementar la definición de nuestra modificación de la Ribbon (o cinta, como suele ser el convenio de traducción).

Definición del fichero Elements.xml

En realidad, las modificaciones de la Ribbon se llevan a cabo dentro de un CustomAction, con su correspondiente ámbito de aplicación, y por tanto, nuestro esquema del XML será:

Base del documento Xml
Definiremos el ámbito de la modificación de la Ribbon (un Content Type, una List Definition, global, etc.)
Lo veremos más en detalle abajo
Uno o varios

Custom Action

Una de las primeras dudas que surgen es en qué ámbito vamos a aplicar la personalización de la Ribbon.

Aquí veremos la referencia de la MSDN:
http://msdn.microsoft.com/en-us/library/ms460194.aspx

Custom Action para modificar la Ribbon en Biblioteca de Documentos

Alternativa 1: la mostraremos en cualquier biblioteca que herede del Template de Document Library:

<CustomAction Id="Internav.CA.Ribbon.CheckGroups"
       RegistrationId="101"
       RegistrationType="List"
       Location="CommandUI.Ribbon">

Alternativa 2: nos basamos en el Content Type:

<CustomAction Id="Internav.CA.Ribbon.CheckGroups"
        RegistrationId="0x0101"
        RegistrationType="ContentType"
        Location="CommandUI.Ribbon">
 
 Alternativa no válida: omitir RegistrationId y RegistrationType. Veremos adelante que un CustomAction no vinculado a ninguna lista no ContentType sólo es válido para lugares que no estén vinculados directamente a ningún tipo de lista de Sharepoint.

En el ejemplo desarrollado abajo, que es la página de modificación de permisos, no debemos especificar ningún RegistrationType, ya que no estamos vinculando realmente a una lista.

CommandUIDefinition

En primer lugar, tengamos una cosa en cuenta: todos los Contextual Tabs, Tabs, Grupos y botones de la Ribbon están ya definidas en ..\14\template\global\xml\CMDUI.XML.

En realidad con un CommandUIDefinition lo que hacemos es de forma declarativa, modificar dicho fichero XML, por lo que cada elemento CommandUIDefinition lo que hará es modificar la definición estándar, añadiendo, o sobrescribiendo.

Así, por ejemplo, si un Location define RUTAXML._children, lo que hará es que el elemento definido dentro del CommandUIDefinition se insertará como hijo del elemento RUTAXML.

Así, por ejemplo:

Añadir un grupo al Ribbon.Permission

El padre es, por tanto, un Tab llamado Ribbon.Permission. Es interesante abrir siempre el CMDUI.XML, para copiar y pegar desde ahí el nombre del elemento padre.

Así pues, en este caso: Location=Ribbon.Permission.Groups._children

En el interior del CommandUIDefinition, tendremos pues que incluir, esta jerarquía:

  • Group
    • Controls
      • Button

Además, un grupo tiene que tener un determinado Scaling, con lo que habría que definir otro elemento adicional CommandUIDefinition con Location=Ribbon.Permission.Scaling._children, con este contenido:

  • MaxSize Id=”id_elegido_por_nosotros” Sequence=”101” GroupId=”GroupId_definido_anteriormente” Size=”LargeLarge”

En este caso, hacemos que nuestro grupo sólo se pueda mostrar con iconos grandes. La definición LargeLarge en realidad viene determinada por el Template que hayamos asignado a nuestro Group.

Consejo: usemos siempre, salvo que tengamos necesidades especiales, el mismo GroupTemplate que los grupos hermanos del que estamos añadiendo. Si usamos otro GroupTemplate, y no lo utiliza la Ribbon en otro grupo distinto, no funcionaría si no forzamos por servercode que se cargue explícitamente.

Añadir un botón a un grupo

Este caso es mucho más sencillo, ya que nuestro CommandUIDefinition será: Ribbon.Permission.Check.Controls._children

Cuidado: reitero la importancia de copiar y pegar desde el CMDUI.XML, ya que hay casos como el grupo de añadir permisos, cuyo Id tiene controls en minúscula, así que tengámoslo en cuenta. Los Id los podemos escoger libremente, pero en Location no puede haber errores.

En un ejemplo posterior veremos cómo personalizar la página de modificación de permisos.

Modificar la Ribbon en la página de modificación de permisos

Esta página es accesible mediante /_layouts/User.aspx, y en realidad tiene una Ribbon vinculada a una lista especial interna de Sharepoint que, por tanto, no podremos encontrar su definición en ninguna Feature estándar, con lo que buscarla no ayudará demasiado.

Este sería el fichero Elements.xml completo:

xml version="1.0" encoding="utf-8"?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <CustomAction Id="Evotec.CA.Ribbon.CheckGroups"
        Location="CommandUI.Ribbon"> <CommandUIExtension> <CommandUIDefinitions> <CommandUIDefinition Location="Ribbon.Permission.Check.Controls._children"> <Button Id="Evotec.CA.Ribbon.CheckGroups.BtnVerGrupos"
                        Command="Evotec.CA.Ribbon.VerGruposAction"
                        Sequence="101"
                        Image16by16="/_layouts/$Resources:core,Language;/images/formatmap16x16.png"
                        Image16by16Top="-176" Image16by16Left="-192"
                        Image32by32="/_layouts/$Resources:core,Language;/images/formatmap32x32.png"
                        Image32by32Top="-256" Image32by32Left="-64"
                        LabelText="Ver grupos"
                        Alt="Ver grupos"
                        ToolTipTitle="Ver grupos"
                        ToolTipDescription="Ver grupos"
                        TemplateAlias="o1"/> CommandUIDefinition> CommandUIDefinitions> <CommandUIHandlers> <CommandUIHandler Command="Evotec.CA.Ribbon.VerGruposAction"
                CommandAction="javascript: function AccionBoton() { var items = GetSelectedPrincipals(); var mensaje = items.strNames; mensaje = $.url.decode(mensaje); SP.UI.Notify.addNotification('Has seleccionado: ' + mensaje); } AccionBoton();"
                EnabledScript="javascript: function CheckBoton() { var items = GetSelectedPrincipals(); return (items.strIds.length > 0); } CheckBoton();"/> CommandUIHandlers> CommandUIExtension> CustomAction> Elements>
Éste es el resultado:

Ribbon

CustomAction Como lo que queremos modificar no es una lista realmente, el ámbito está vacío y sólo incluiremos la Location CommandUI.Ribbon
CommandUIDefinition.Location Este es el parámetro más importante cuando definimos una modificación/añadido sobre una Ribbon.En nuestro caso lo que hacemos es añadir un elemento sobre la colección Ribbon.Permission.Check.Controls.El último token: _children es especial, e indica que el contenido interior del CommandUIDefinition se añadirá como un nuevo miembro en una colección ya definida previamente en el CMDUI.XML.
Id Los Id en general son libres y los podemos usar como queramos con la convención interna de nuestro proyecto. Suele ser buena práctica usar Namespaces separados con puntos, comenzando con el nombre de nuestra empresa, para evitar colisiones. Importante no confundirnos con los Location mencionados antes, ya que estos nos tenemos que ceñir.
Command El Command definido dentro del “Button” tiene que coincidir con el definido en el CommandUIHandler. En este caso también es una notación interna nuestra, con lo que no hay ninguna regla a seguir.
EnabledScript Este será el código ECMAScript a ejecutar para verificar si el botón estará o no deshabilitado. El patrón más habitual es habilitar el botón si hay algún elemento seleccionado en la lista.Habitualmente esta operación se consigue haciendo referencia a la ECMAScript Class Library que incluye Sharepoint 2010: SP.ListOperation.Selection.getSelectedItems()…Sin embargo, en una página de edición de permisos no es una lista normal, y este método devuelve siempre un Array vacío.

Por supuesto, siempre hay alternativa, y de hecho, la ApplicationPage /_layouts/user.aspx incluye definida una función que los propios de Microsoft utilizan para habilitar o no el resto de botones de la Ribbon: esta es GetSelectedPrincipals(), que nos devuelve un objeto con los Ids y con los nombres, separados con comas.

CommandAction En nuestro ejemplo, simplemente tomaremos los nombres seleccionados, los descodificamos (recordemos, están URLEncoded).En este ejemplo, usamos la librería jQuery $.url.decode, que previamente hemos incluido mediante otro proyecto que nos permite utilizar jQuery y cualquier otra libraría JS necesaria en Sharepoint 2010.
Iconos:Image16by16TopImage16by16Left

Image32by32Top

Image32by32Left

Quien haya manejado ya a nivel de desarrollo algo en Sharepoint 2010, se habrá percatado de que la mayor parte de las imágenes utilizan ya la técnica de “Sprites” para minimizar lo más posible el número de GETs a la hora de cargar una página. La mayor parte de los botones de la Ribbon utilizan la imagen /_layouts/$Resources:core,Language;/images/formatmap32x32.png, y añaden un offset vertical y horizontal para situar el punto de inicio del icono en cuestión.

Consejos importantes

La ribbon es un componente que depende 100% de ECMAScript, y por tanto, muy sensible a cualquier error u omisión. Es decir, si activamos nuestra Feature y tiene algún error, nos podemos encontrar que la Ribbon completa deja de funcionar, o está deshabilitada. Probablemente nunca encontremos error de compilación, ni al activar la Feature (salvo tengamos un Elements.xml mal formado, claro).

Cuidado con las cachés

Mención especial son las cachés del navegador. Consejo importante al desarrollar: usemos el modo privado de Internet Explorer (o Firefox), y entre prueba y prueba cerramos la sesión InPrivate de Internet Explorer y volvemos a abrirlo, ya que hay Scripts de ECMAScript que se quedan en caché en memoria y un Control + F5 no es suficiente, puesto que hay muchos JS que se cargan en diferido.

De forma alternativa, podemos usar la DevBar de Internet Explorer, o Firebug, y deshabilitar toda caché del navegador. Esto nos puede ahorrar muchas horas de problemas.

¿Ribbon o Menú ECB (Edit Control Block)?

Desde el punto de vista de usabilidad, especialmente cuando hablamos de una biblioteca de documentos, un usuario está acostumbrado a realizar acciones tanto desde el menú ECB como desde la Ribbon. Esto nos lleva a una cuestión importante: si añadimos un botón en la Ribbon, probablemente sea pertinente incluirlo también en el ECB. Este último caso se resuelve fácilmente mediante una Custom Action.


Your name:
Gravatar Preview
Your email:
(Optional) Email used only to show Gravatar.
Your website:
Title:
Comment:
Security Code
CAPTCHA image
Enter the code shown above in the box below
Add Comment   Cancel 
© Evotec Consulting S.L. Gestión de Sistemas Informáticos