martes, 28 de julio de 2015
¿Cómo modificar el display name de una columna en una lista de SharePoint con C#?
lunes, 27 de julio de 2015
Programando la Ribbon en SharePoint 2010.
Introducción
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:
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
using (SPWeb mi_web = (properties.Feature.Parent as SPSite).OpenWeb())
{
// Agrego botones personalizados para la edición del Proyecto
mi_web.AllowUnsafeUpdates = true;
SPList lista = mi_web.GetList("/Lists/Proyectos");
var action = lista.UserCustomActions.Add();
action.Location = "CommandUI.Ribbon.EditForm";
action.Sequence = 10;
action.Title = "SURPOINT";
action.CommandUIExtension = @"
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:
CommandAction=""javascript:
elID = _spGetQueryParam('id');
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); } });
"" />
El siguiente es el código completo para agregar los botones
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
using (SPWeb mi_web = (properties.Feature.Parent as SPSite).OpenWeb())
{
// Agrego botones personalizados para la edición del Proyecto
mi_web.AllowUnsafeUpdates = true;
SPList lista = mi_web.GetList("/Lists/Proyectos");
var action = lista.UserCustomActions.Add();
action.Location = "CommandUI.Ribbon.EditForm";
action.Sequence = 10;
action.Title = "SURPOINT";
action.CommandUIExtension = @"
<CommandUIExtension>
<CommandUIDefinitions>
<CommandUIDefinition Location=""Ribbon.Templates._children"">
<GroupTemplate Id=""Ribbon.Templates.CustomTemplate"">
<Layout Title=""NewGroupInExistingTabOneLarge"" LayoutTitle=""NewGroupInExistingTabOneLarge"">
<Section Alignment=""Top"" Type=""OneRow"">
<Row>
<ControlRef DisplayMode=""Large"" TemplateAlias=""Button1"" />
<ControlRef DisplayMode=""Large"" TemplateAlias=""Button2"" />
<ControlRef DisplayMode=""Large"" TemplateAlias=""Button3"" />
</Row>
</Section>
</Layout>
</GroupTemplate>
</CommandUIDefinition>
<CommandUIDefinition Location=""Ribbon.ListForm.Edit.Scaling._children"">
<MaxSize
Id=""Ribbon.ListForm.Edit.MaxSize""
Sequence=""15""
GroupId=""Ribbon.ListForm.Edit.Groups.CustomGroup""
Size=""NewGroupInExistingTabOneLarge"" />
</CommandUIDefinition>
<CommandUIDefinition Location=""Ribbon.ListForm.Edit.Groups._children"">
<Group Id=""Ribbon.ListForm.Edit.Groups.CustomGroup""
Sequence=""100"" Title=""SURPOINT""
Description=""SURPOINT""
Template=""Ribbon.Templates.CustomTemplate"">
<Controls Id=""Ribbon.ListForm.Edit.Groups.CustomGroup.Controls"">
<Button
Id=""Ribbon.ListForm.Edit.Groups.CustomGroup.Controls.Button""
Alt=""Vincular a sitio de proyecto""
Sequence=""1""
Image32by32=""/_layouts/images/newweb32.png""
Image16by16=""/_layouts/images/SharePointFoundation10.png""
Command=""vincularSitio""
LabelText=""Sitio de proyecto""
TemplateAlias=""Button1""
CommandType=""General""/>
<Button
Id=""Ribbon.ListForm.Edit.Groups.CustomGroup.Controls.Button2""
Alt=""Agregar a informe de portfolio""
Sequence=""2""
Image32by32=""/_layouts/images/uploaddoc.png""
Image16by16=""/_layouts/images/SharePointFoundation10.png""
Command=""agregarInforme""
LabelText=""Agregar a portfolio""
TemplateAlias=""Button2""
CommandType=""General""/>
<Button
Id=""Ribbon.ListForm.Edit.Groups.CustomGroup.Controls.Button3""
Alt=""Quitar de informe de portfolio""
Sequence=""3""
Image32by32=""/_layouts/images/mewa_backb.gif""
Image16by16=""/_layouts/images/SharePointFoundation10.png""
Command=""quitarInforme""
LabelText=""Quitar de portfolio""
TemplateAlias=""Button3""
CommandType=""General""/>
</Controls>
</Group>
</CommandUIDefinition>
</CommandUIDefinitions>
<CommandUIHandlers>
<CommandUIHandler
Command=""vincularSitio""
CommandAction=""javascript:
elID = _spGetQueryParam('id');
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); } });
"" />
<CommandUIHandler
Command=""agregarInforme""
CommandAction=""javascript:
elID = _spGetQueryParam('id');
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); } });
"" />
<CommandUIHandler
Command=""quitarInforme""
CommandAction=""javascript:
elID = _spGetQueryParam('id');
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); } });
"" />
</CommandUIHandlers>
</CommandUIExtension>
";
action.Update();
mi_web.AllowUnsafeUpdates = false;
}
}
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:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Obtener el ID del proyecto recibido como parámetro
string proyecto = "";
proyecto = Page.Request.QueryString["ProjectId"];
// Datos del actual sitio elegido
string idSitio = "";
using (SPSite sitio = new SPSite(SPContext.Current.Site.Url))
(…)
Y lo más importante la parte final del evento OnClick del botón de nuestra página:
protected void vincularSitio(object sender, EventArgs e)
{
(..(
this.Page.Response.Clear();
this.Page.Response.Write("<script type='text/javascript'>window.frameElement.commonModalDialogClose(1, 1);</script>");
this.Page.Response.End();
}
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/
Publicado originalmente para revista COMPARTIMOSS
Diseño Gráfico en SharePoint Foundation 2010 Parte 3.
Introducción
En artículos anteriores hicimos una introducción acerca de cómo incorporar en SharePoint 2010 los estilos creados por un diseñador gráfico. Nos basamos en algunas hipótesis como el uso de SharePoint Foundation, páginas maestras, hojas de estilo y modelo de objetos de cliente para JavaScript. Se recomienda leer la parte 1 y la parte 2 antes de continuar. También les recomiendo leer los ejemplos de CAML con Client Object Model, porque los utilizo para obtener datos de listas.
En esta tercera etapa, vamos a trabajar con dos casos puntuales:
· Botonera gráfica en reemplazo del Inicio Rápido
· Tablero de control con indicadores gráficos
Qué lo disfruten!
Botonera gráfica en reemplazo del Inicio Rápido
Lo primero que vamos a mostrar es cómo agregar una botonera con imágenes que reemplace al tradicional Inicio Rápido. Esta botonera se verá en todas las páginas. Para ello modificamos la página maestra y agregamos algunos estilos. El resultado final se ve en esta imagen:
Imagen 1 – Botonera gráfica en reemplazo de Inicio Rápido
El siguiente código muestra el agregado de la botonera en la página maestra
<div id="botonera_izquierda">
<div id="menu">
<ul id="nav">
<li><a href="/"><img src="/internal/nav_inicio_static.jpg" width="90" height="90"></a></li>
<li><a href="/Lists/Noticias"><img src="/internal/nav_noticias_static.jpg" width="90" height="90"></a></li>
<li><a href="/Lists/Personal"><img src="/internal/nav_nuestras_static.jpg" width="90" height="92"></a></li>
<li><a href="/Polticas"><img src="/internal/nav_politicas_static.jpg" width="90" height="91"></a></li>
<li><a href="/Formularios"><img src="/internal/nav_formularios_static.jpg" width="90" height="91"></a></li>
<li><a href="/Lists/Busquedas"><img src="/internal/nav_busquedas_static.jpg" width="90" height="91"></a></li>
<li><a href="/Lists/Menu"><img src="/internal/nav_menu_static.jpg" width="90" height="91"></a></li>
<li><a href="/Revistas/"><img src="/internal/nav_revista_static.jpg" width="90" height="91"></a></li>
<li><a href="/"><img src="/internal/nav_remises_static.jpg" width="90" height="91"></a></li>
<li><a href="/Capacitaciones"><img src="/internal/nav_capacitaciones_static.jpg" width="90" height="92"></a></li>
</ul>
</div>
</div>
El código debe ser agregado justo antes de esta línea:
<div id="s4-leftpanel-content">
Por otro lado, agregamos los siguientes estilos en nuestra hoja de estilos:
#s4-leftpanel { width: 95px !important;}
#s4-leftpanel-content { display: none; }
.s4-ca { margin-left: 95px; }
Un detalle más, queremos que los botones cambien a otra imagen en el momento en que pasamos el mouse por sobre ellos (hover), tal como se ve en la siguiente imagen:
Imagen 2 – Efecto Hover en la botonera
Con ese fin agregamos en la página maestra, el siguiente código jQuery:
<script type="text/javascript">
$('#nav a img').hover(
function() {
$(this).attr('src', $(this).attr('src').replace('static', 'over') );
},
function() {
$(this).attr('src', $(this).attr('src').replace('over', 'static') );
}
);
</script>
Tablero de control con indicadores gráficos
Cómo segundo ejemplo del día, vamos a agregar unos indicadores gráficos que se vean como los de la siguiente imagen:
Imagen 3 – Ejemplo de Tablero de Control
Estos indicadores serán generados a partir de información en listas usando CAML. En este caso usaremos una página de aplicación en C# con código de servidor por un tema de rendimiento, pero también podría ser JavaScript con Cliente Object Model.
Dentro de nuestra página ASP.Net llamaremos a una hoja de estilos además de crear el DIV “contenido”:
<asp:Content ID="Main" runat="server" contentplaceholderid="PlaceHolderMain" >
<div runat="server" ID="contenido" />
<link href="agea_telefonia_dashboard.css" type="text/css" rel="stylesheet" id="stylesheet" />
</asp:Content>
<asp:Content ID="PageTitle" runat="server" contentplaceholderid="PlaceHolderPageTitle" >
Panel de Control
</asp:Content>
<asp:Content ID="PageTitleInTitleArea" runat="server" contentplaceholderid="PlaceHolderPageTitleInTitleArea" >
Panel de Control
</asp:Content>
Leeremos la información vía CAML. No voy a mostrar en el código la lectura de información porque está muy relacionada con la lógica del negocio y no es más que lecturas típicas en CAML. Lo que si mostraré es cómo incorporar esos valores dentro de dos DIVs pensados para estructurar la información:
· DIV dash01 para el valor del indicador 1
· DIV dash01_detalle para el detalle del indicador 1
· Y así sucesivamente…
contenido.InnerHtml = "<div class='semaforos'>";
contenido.InnerHtml += "<div id='dash01' class='" + luz_indicador_1 + " dash'><p class='titulo'>CALENDARIO</p><p class='valor'>" + x_equipos_sin_linea + "</p><p class='leyenda'>Tiempos del Proyecto</p></div>";
contenido.InnerHtml += "<div id='dash02' class='" +
Continuar el armado de DIVs para el resto de los indicadores.
contenido.InnerHtml += "</div>";
contenido.InnerHtml += "<div id='dash01_detalle' class='detalle'>" + detalle_indicador_1 + "</div>";
contenido.InnerHtml += "<div id='dash02_detalle' class='detalle'>" +
Continuar el armado de DIVs de detalle para el resto de los indicadores.
Agregaremos además algo de código jQuery para que al presionar sobre un indicador, nos muestre la información de detalle. Para ello llamamos a los scripts correspondientes de ASPX:
Page.ClientScript.RegisterClientScriptInclude("dash_jquery", ResolveUrl("./jquery-1.8.2.min.js"));
Page.ClientScript.RegisterClientScriptInclude("dash_script", ResolveUrl("./dashboard.js"));
Page.ClientScript.RegisterStartupScript(this.GetType(), "dash_script", "asignar_botones();", true);
Y este es nuestro código jQuery “dashboard.js”:
function asignar_botones () {
$( document ).ready(function() {
$(".dash").click(function() {
var panel = "#" + $(this).attr('id') + "_detalle";
$(".detalle").css("display","none");
$(panel).slideDown( "slow" ).css("overflow","visible");
$(".dash").removeClass("dash_selected");
$(this).addClass("dash_selected");
});
});
Por último nos queda incorporar nuestra hoja de estilo, cuidando que el diseño sea responsive y se adapte al ancho de la pantalla, como se ve en esta imagen (en una pantalla más angosta que la anterior):
Imagen 4 – Ejemplo de Tablero de Control con un ancho de pantalla más angosto
.dash { border: solid white 2px; }
.dash_selected { border: solid #333333 2px; }
.semaforos div {
float: left;
width: 22%;
margin: 3px;
padding: 15px 15px 10px 15px ;
}
.semaforos {
font-family: tahoma;
text-align: center;
cursor: pointer;
}
.verde { background-color: #8CC152; }
.rojo {background-color: #E9573F; }
.amarillo { background-color: #F6BB42;}
.gris{ background-color: #C8C8C; }
.valor {
color: #fff;
font-weight: 500;
font-size: 36px;
margin-top: 20px;
margin-bottom: 10px;
}
.titulo {
color: #fff;
font-size: 17px;
font-weight: 500;
}
.leyenda {
border-top: solid white 5px;
padding-top: 12px;
color: #fff;
font-size: 12px;
height: 65px;
}
.verde .leyenda { border-top-color: #76AD3E;}
.rojo .leyenda { border-top-color: #D1462C;}
.amarillo .leyenda { border-top-color: #E0A52C; }
.gris .leyenda { border-top-color: #737373; }
.detalle {
border-left: solid #E6E9ED 10px;
width: 95%;
height: 200px;
margin: 5px;
padding: 5px;
font-size: 11px;
font-family: tahoma;
clear: both;
display:none;
}
.detalle span {
font-size: 11px;
font-family: tahoma;
}
.detalle a {
padding: 5px;
font-size: 11px;
}
Conclusión
Esta fue la tercera entrega de esta colección de artículos dedicada a demostrar cómo se puede trabajar en SharePoint junto a un diseñador gráfico profesional. En mi opinión, esto es muy valorado por los clientes.
Les presento otra imagen del resultado final, ya vieron una en el artículo anterior. Espero como siempre que haya sido útil y cualquier duda me consultan. Saludos!
Imagen 5 – Diseño Gráfico aplicado a la página de inicio de SharePoint (caso 2)
Juan Pablo Pussacq Laborde
SharePoint MVP
Blog: http://surpoint.blogspot.com/
Facebook: http://facebook.com/surpointblog/
Twitter: http://twitter.com/jpussacq/
Publicado originalmente para revista COMPARTIMOSS
domingo, 26 de julio de 2015
¿Cómo verificar si un usuario tiene permisos de edición en una lista de SharePoint con C#?
viernes, 24 de julio de 2015
miércoles, 22 de julio de 2015
¿Cómo editar una vista de una webpart en una página en SharePoint con C#?
- Encontrar la página de inicio
- Buscar la webpart por título
- Instanciar su vista
- Cambiar el QUERY
¿Cómo ocultar una columna en un tipo de contenido en SharePoint con C#?
martes, 21 de julio de 2015
viernes, 17 de julio de 2015
¿Cómo ordenar campos en un tipo de contenido en SharePoint con C#?