Posts recientes

El contenido de este blog tiene una licencia Creative Commons.
Creative Commons

Paginación de DropDownList (ComboBox)

En el caso de que se encuentren con aplicaciones en las cuales haya un exceso de dato en los controles desplegables, una posible solución es paginar dicho control al estilo de un grid con las opciones de "Primera", "Anterior", "Siguiente" y "Última". Én este artículo muestro como se puede llegar a paginar dichos controles.
 
Definición del control:
Lo primero será definir el control derivado a partir del DropDownList genérico que estamos acostumbrados a usar.
 
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
using System.Data;
namespace WebControlLibrary
{
public class DDLPaginado : DropDownList
{
//Member to hold PagedDataSource
private PagedDataSource pds;
//flag variable to indicate if we should go to the last page
private bool goToLastPage=false;
/// <summary>
/// DataSource
/// </summary>
public override object DataSource
{
get
{
// Nos aseguramos que el PageddataSource ha sido creado
EnsureDataSource();
return pds;
}
set
{
// Si el DataSource es un DataReader no podemos usar este control porque
// no nos indica el nmero de elementos.
if(value is IDataReader)
throw new ArgumentException("DataReader isn't supported as data source","DataSource");
// El DataSource debe ser un DataTable, un DataView o un IEnumerable.
if(!((value is DataTable) || (value is DataView) || (value is IEnumerable)))
throw new ArgumentException("Data source not supported","DataSource");
// Nos aseguramos que el PageddataSource ha sido creado
EnsureDataSource();
// En caso de que el DataSource sea DataTable usamos DefaultView(DataView).
if(value is DataTable)
pds.DataSource =((DataTable)value).DefaultView;
// Si el DataSource es un DataView lo usamos directamente.
if(value is DataView)
pds.DataSource =(DataView)value;
// Si el DataSource es un IEnumerable lo usamos directamente.
if(value is IEnumerable)
pds.DataSource=(IEnumerable)value;
// Se asigna mediante la funcin de la clase base DataSource
base.DataSource =pds;
}
}
/// <summary>
/// "Page index" se usa en la paginacin.
/// </summary>
public int CurrentPageIndex
{
get
{
object o=ViewState[this.UniqueID + "CurrentPageIndex"];
return(o==null)? 0 : (int)o;
}
set
{
ViewState[this.UniqueID + "CurrentPageIndex"]=value;
}
}
/// <summary>
/// Mtodo para incrementar el "Page index".
/// </summary>
public void GoToNextPage()
{
EnsureDataSource();
if(!pds.IsLastPage)
CurrentPageIndex++;
}
/// <summary>
/// Mtodo para decrementar el "Page index".
/// </summary>
public void GoToPreviousPage()
{
EnsureDataSource();
if(CurrentPageIndex > 0)
CurrentPageIndex--;
}
/// <summary>
/// Mtodo para acceder a la primera pgina del DDL.
/// </summary>
public void GoToFirstPage()
{
CurrentPageIndex = 0;
}
/// <summary>
/// Mtodo para acceder a la ltima pgina del DDL.
/// </summary>
public void GoToLastPage()
{
goToLastPage = true;
}
/// <summary>
/// Nmero de elementos por pgina.
/// </summary>
public int PageSize
{
get
{
EnsureDataSource();
return pds.PageSize;
}
set
{
//El nmero de elementos no puede ser menor de 1.
if(value < 1 )
throw new ArgumentException("El nmero de elementos no puede ser menor de 1.");
EnsureDataSource();
pds.PageSize = value;
}
}
/// <summary>
/// Mtodo para asegurarnos que el PagedDataSource ha sido creado.
/// </summary>
private void EnsureDataSource()
{
if(pds ==null)
{
pds=new PagedDataSource();
pds.AllowPaging =true;
pds.PageSize = 10;
}
}
protected override void OnDataBinding(System.EventArgs e)
{
EnsureDataSource();
// Se cuenta el nmero mximo de pginas existentes.
// Slo se puede usar si existe DataSource.
if(base.DataSource == null)
throw new ArgumentException("DataSource no puede estar vaco.");
int countableindex;
try
{
// ndice es el DataSourceCount por PageSize
countableindex=(int)(pds.DataSourceCount / pds.PageSize);
// Si el mdulo es 0, el ndice se debe decrementar en 1
if(pds.DataSourceCount % pds.PageCount == 0)
{
countableindex--;
}
}
catch(Exception ex)
{
countableindex=0;
}
// Se verifica que el ndice no sobrepasa la ltima pgina existente
if(CurrentPageIndex > countableindex || goToLastPage == true)
{
pds.CurrentPageIndex = countableindex;
// Se asigna la propiedad CurrentPageIndex para que refleje el ndice correcto
CurrentPageIndex=countableindex;
}
else
{
// El ndice toma el valor del CurrentPageIndex
pds.CurrentPageIndex = CurrentPageIndex;
}
// Llamada de la clase base del OnDataBinding
base.OnDataBinding(e);
}
}
}
Uso del control:
El control funcionará igual que otros controles a los cuales se les asocia datos mediante un DataSource (data-bound control in ASP.NET).
 
PARTE VISUAL (.ASCX)
<asp:Button ID="btnPrimera" Runat=server Text="Primera" />
<asp:Button ID="btnAnterior" Runat=server Text="Anterior" />
<asp:Button ID="btnSiguiente" Runat=server Text="Siguiente" />
<asp:Button ID="btnUltima" Runat=server Text="Última" />
<br/>
<cc1:DDLPaginado id=DDLPaginado1 runat="server" PageSize="10"></cc1:DDLPaginado>
 
CÓDIGO (.ASPX.CS)
 
private void Page_Load(object sender, System.EventArgs e)
{
	if(!Page.IsPostBack)
	{
		BindDDL();
	}
}

//Test data
private void BindDDL()
{
	SortedList sl=new SortedList();
	for(int i=1;i<51;i++)
		sl.Add(i,i);

	PagedDDL1.DataSource = sl;
	PagedDDL1.DataValueField ="Value";
	PagedDDL1.DataTextField ="Key";
	PagedDDL1.DataBind(); 
}

                      

private void btnFirst_Click(object sender, System.EventArgs e)
{
	PagedDDL1.GoToFirstPage();
	BindDDL();
}

private void btnPrevious_Click(object sender, System.EventArgs e)
{
	PagedDDL1.GoToPreviousPage();
	BindDDL();
}

private void btnNext_Click(object sender, System.EventArgs e)
{
	PagedDDL1.GoToNextPage();
	BindDDL();
}

private void btnLast_Click(object sender, System.EventArgs e)
{
	PagedDDL1.GoToLastPage();
	BindDDL();
}
 
Con este código ya estaría funcionando el DropdownList con paginación en vuestra aplicación.
Autor: David Acosta Lesmes
Publicado: 31/03/2010  17:10 | 0  Comentarios | 1  Enlaces a este post

Insertar código javascript dinámicamente

Muchas veces me he encontrado con la necesidad de insertar código javascript dinámicamente, por ejemplo, añadiendo eventos a algunos controles de mi página aspx. Para hacerlo siempre había utilizado el método Page.ClientScript.RegisterStartupScript(...). Funcionaba correctamente hasta que el script hacía referencia a un control que se encontraba dentro de un UpdatePanel. El código javascript no se ejecutaba.

Si te ocurre esto, la solución es substituir la llamada Page.ClientScript.RegisterStartupScript(...) por ScriptManager.RegisterStartupScript(...) y todo funcionará correctamente.

Autor: Anna Vilalta Gili
Publicado: 29/03/2010  11:00 | 0  Comentarios | 0  Enlaces a este post

Impersonación a la hora de trabajar con Exchange

Para invocar a los Web Services propios de Exchange 2007 es necesario crear un usuario de servicio que cuente con permisos de impersonación sobre las mailbox databases. Para cada entorno se creará el usuario llamado ExchangeWSuser (sin incluir en ningún grupo de seguridad, únicamente en “domain user” ) y desde el servidor de Exchange 2007 se deberán ejecutar estas dos sentencias en PowerShell. Estos comandos será preciso ejecutarse cada vez que se cree una BBDD de Exchange 2007.
1.------------------------------------------------------------------
Get-MailboxDatabase | ForEach-Object {Add-ADPermission -Identity $_.DistinguishedName -User ExchangeWSUser -ExtendedRights ms-Exch-EPI-May-Impersonate}
2.------------------------------------------------------------------
Add-ADPermission -Identity (get-exchangeserver -Identity SERVER_NAME).DistinguishedName -User (Get-User -Identity ExchangeWSUser | select-object).identity -extendedRight ms-Exch-EPI-Impersonation
El documento en el msdn es el que sigue:
http://msdn.microsoft.com/en-us/library/bb204095.aspx
Una vez tenemos el usuario ExchangeWSUser creado, se debe usar al instanciar el ExchangeServiceBinding de la siguiente forma:
ExchangeServiceBinding esb = new ExchangeServiceBinding();private static string usuarioEx;
// summary
// Crear el Objeto de enlace con Exchange 2007
// summary
// param name="UserName" Nombre de Usuario
// param name="Domain Dominio del usuario
// param name="Url" Url De Exchange. Parámetro opcional. Se cogerá la Url por defecto en caso de estar vacío.
private void CreateExchangeServiceBinding(string UserName, string Domain, string Url)
{
usuarioEx = UserName;
esb.ExchangeImpersonation = new ExchangeImpersonationType();
ServicePointManager.ServerCertificateValidationCallback = delegate(Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
// Replace this line with code to validate server certificate.
return true;
};
esb.ExchangeImpersonation.ConnectingSID = new ConnectingSIDType();
esb.ExchangeImpersonation.ConnectingSID.PrimarySmtpAddress = UserName + "@" + Domain;
if (Url != null && Url != string.Empty)
{
esb.Url = Url;
}
else
{
esb.Url = ConfigurationManager.AppSettings["EWSUrl"].ToString();
}
// Se identifica el enlace del servicio y el usuario Exchange que reealizará la impersonación
esb.Credentials = new NetworkCredential(ConfigurationManager.AppSettings["ExchangeWsUser"].ToString(), ConfigurationManager.AppSettings["ExchangeWsPass"].ToString(), ConfigurationManager.AppSettings["ExchangeWsUserDomain"].ToString());
}
Como se ve se accede al config en algunos casos:
ConfigurationManager.AppSettings["ExchangeWsUser"]
Obteniendo el username, pass y domain al que pertenece el usuario impersonador.
Espero les sirva de ayuda.
Autor: David Acosta Lesmes
Publicado: 27/03/2010  16:38 | 0  Comentarios | 0  Enlaces a este post

Especificar el idioma de un report a través de un parámetro

Los parámetros que espera un informe y que dependen de la referencia cultural, por ejemplo, los parámetros de fechas, se interpretan según el idioma del explorador. Es decir, aunque el servidor de informes tenga la configuración regional que se desea, si un usuario tiene el explorador establecido en otra configuración regional distinta, los valores de los parámetros que se envíen al servidor se interpretarán de forma incorrecta.

Para evitarlo, se puede especificar mediante el parámetro rs:ParameterLanguage añadido en la url el idioma con el que se debe interpretar, independientemente de la configuración regional que tenga el explorador del usuario que lo ejecute.

Ejemplo: http://[Nombre _servidor]/ReportServer?/Reports/NombreReport&rs:Command=Render&Fecha=10/03/2010&rs:ParameterLanguage=es-ES

Fuente: http://msdn.microsoft.com/es-es/library/ms155064.aspx

Autor: Anna Vilalta Gili
Publicado: 23/03/2010  17:11 | 3  Comentarios | 0  Enlaces a este post

¿Cómo maximizar la ventana?

<html>
<head>
<title>Untitled Document</title>
<script language="JavaScript">
function maximiza()
{
window.moveTo(0,0);
if (document.all)
{
top.window.resizeTo(screen.availWidth,screen.avail Height);
}
else if (document.layers||document.getElementById)
{
if (top.window.outerHeight<screen.availHeight||top.window.outerWidth<screen.availWidth){
top.window.outerHeight = screen.availHeight;
top.window.outerWidth = screen.availWidth;
}
}
</script>
</head>
 
<body>
<button onclick=maximiza()>Maximizar</button>
</body>
</html>
 
Al pulsar el botón la ventana se maximiza. Si se desea que la ventana se maximize al entrar , sólo hace falta poner <body onload=maximiza()>
Autor: David Acosta Lesmes
Publicado: 22/03/2010  16:35 | 0  Comentarios | 0  Enlaces a este post

Consejos para mejorar el rendimiento de tu Entity Framework (VI)

Cargar objetos con el EF.
Desde el framework puedes cargar relaciones usando  include. Por cada uno, el framework añadirá un join que puede originar consultas complejas, y que sean devueltas grandes cargas de datos. A este tipo de cargas se les llama "Eager loading".
Sin embargo, esto puede ser evitado usando el método Load para hacer "lazy or explicit loading”, que abre una conexión a base de datos para recuperar la información necesaria.
Así nos aseguramos de que la consulta  sólo ejecutará una petición a un objeto relacionado mediante una petición explícita.
Por ejemplo:
// Get a specified customer by contact ID.
Contact customer = context.Contact.Where("it.ContactID = @customerId", 
                   new ObjectParameter("customerId", customerId)).First();
// Load the orders for the customer
if (!customer.SalesOrderHeader.IsLoaded)
{
    customer.SalesOrderHeader.Load();
}
El código completo  de este ejemplo se  encuenta en este artículo del msdn de Microsoft.
 
Filtra los datos.
Cuando se usa este tipo de carga (con Load o con LoadWith) se reciben todos los datos asociados con la clave primaria, pero la mayoría de los casos se deben aplicar filtros adicionales. Para ello se usa el método  DataLoadOptions.AssociateWith, que toma el criterio al cargar los datos como parámetro y aplica la consulta.  
using (DataContext context = new DataContext())
{
  DataLoadOptions options = new DataLoadOptions();
  options.AssociateWith(cat=> cat.Products.Where(prod => !prod.Discontinued));
  context.LoadOptions = options;
}
 
Autor: Isabel Cabezas
Publicado: 19/03/2010  9:23 | 0  Comentarios | 0  Enlaces a este post

Custom SiteMap

Muchas son las veces que hemos detecado que el SiteMap que nos ofrece Microsoft, se nos queda corto cuando deseamos crear dinamismos en función de variables, como podría ser un QueryString o un varible de sessión.

En este post, vamos a descubrir como crear un SiteMap customizable en función de varias variables, en nuestro ejemplo utilizaremos una QueryString.

Imaginemos que queremos cambiar el título de un nodo, en función de su QueryString como en este caso:

<siteMapNode title="Departamentos" url="~/Dpto/Default.aspx" >

<
siteMapNode title="Nuevo Departamento" editTitle="Editar Departamento" url="~/Dpto/Dpto.aspx"  queryStringToInclude="EntId" ></siteMapNode>

</
siteMapNode>
Como vemos en este ejemplo, queremos cambiar el nodo de Nuevo Departamento en función del QueryString en el caso que exista EntId para que quede de la siguiente manera
Departamentos > Nuevo Departamento
o
Departamentos > Editar Departamento

En primer lugar, crearemos un proyecto de Biblioteca de clases que lo llamaremos ExtendedSiteMapProvider donde crearemos el siguiente código
 
Imports System.Collections.Specialized
Imports System.Web

Namespace Configuration


    Public Class ExtendedSiteMapProvider
        Inherits XmlSiteMapProvider

        Public Overrides Sub Initialize(ByVal name As String, ByVal attributes As NameValueCollection)
            MyBase.Initialize(name, attributes)
            Dim resolveHandler As New SiteMapResolveEventHandler(AddressOf SmartSiteMapProvider_SiteMapResolve)
            AddHandler Me.SiteMapResolve, resolveHandler
        End Sub

        Function SmartSiteMapProvider_SiteMapResolve(ByVal sender As Object, ByVal e As SiteMapResolveEventArgs) As SiteMapNode
            If (SiteMap.CurrentNode Is Nothing) Then Return Nothing

            Dim this As New XmlSiteMapProvider
            Dim temp As SiteMapNode
            temp = SiteMap.CurrentNode.Clone(True)
            Dim u As Uri = New Uri(e.Context.Request.Url.ToString())
            Dim tempNode As SiteMapNode = temp

            While Not tempNode Is Nothing
                Dim qs As String = GetQueryString(tempNode, e.Context)
                If Not qs Is Nothing Then
                    If Not tempNode Is Nothing Then
                        tempNode.Url += qs
                        tempNode.Title = tempNode("editTitle")

                        Return tempNode
                    End If
                End If

                tempNode = tempNode.ParentNode
            End While

            Return temp
        End Function


        

        Private Function GetQueryString(ByVal node As SiteMapNode, ByVal context As HttpContext) As String
            If node("queryStringToInclude") Is Nothing Then Return Nothing

            Dim values As NameValueCollection = New NameValueCollection
            Dim vars() As String = node("queryStringToInclude").Split(",".ToCharArray())
            Dim s As String

            For Each s In vars
                Dim var As String = s.Trim()
                If context.Request.QueryString(var) Is Nothing Then Continue For
                values.Add(var, context.Request.QueryString(var))
            Next

            If values.Count = 0 Then Return Nothing

            Return NameValueCollectionToString(values)
        End Function

        Private Function NameValueCollectionToString(ByVal col As NameValueCollection) As String
            Dim parts(col.Count - 1) As String
            Dim keys() As String = col.AllKeys

            For i As Integer = 0 To keys.Length - 1
                parts(i) = keys(i) & "=" & col(keys(i))
            Next

            Dim url As String = "?" & String.Join("&", parts)

            Return url
        End Function      
    End Class

End Namespace

Si nos fijamos, utilizamos el método GetQueryString que nos evaluará si existe el atributo queryStringToInclude del nodo y si existe, nos validará que esté informado ese atributo en el QueryString.

Ya por último, nos queda por decirle a nuestro Web.Config que utilize nuestro proveedor de SiteMap en lugar del estándar de Microsoft.
Para ello pondremos en nuestro web.config lo siguiente

<siteMap defaultProvider="ExtendedSiteMapProvider" enabled="true">

<
providers>

<
clear />
<
add name="ExtendedSiteMapProvider" type="OpenSky.UI.Utils.Configuration.ExtendedSiteMapProvider" siteMapFile="web.sitemap" securityTrimmingEnabled="true" />
</
providers>
</
siteMap>
Autor: Javier Tirado Pampín
Publicado: 18/03/2010  16:14 | 0  Comentarios | 0  Enlaces a este post

CTP de Report Builder 3.0

En noviembre de 2009 Microsoft nos deleita con la CTP (Community Technology Preview) de su herramienta de "usuario" para la creación de informes, Report Builder, en su versión 3.0. Esta nueva versión viene con novedades importantes relacionadas a nuevas funcionalidades de SQL Server 2008 y Sharepoint, como las ReportParts (trozos reutilizables de informes, la posibilidad de disponer las listas de Sharepoint como origen de datos (SharePoint List Data Extension), la posibilidad de representar datos geoespaciales sobre un mapa dentro del informe, etc.

Podeies ver una lista completa de las novedades en http://technet.microsoft.com/en-us/library/ee633667(SQL.105).aspx

Autor: Rubén Claramunt Vicente
Publicado: 18/03/2010  12:32 | 0  Comentarios | 0  Enlaces a este post

Consejos para mejorar el rendimiento de tu Entity Framework (V)

Pequeños ficheros EDMX.

El DataContext representa una unidad de trabajo, no toda la base de datos.

El tamaño del esquema .xml es proporcional al número de tablas de la base de datos desde el que se genera, y como el tamaño del archivo aumenta, también aumentará el tiempo que tarda en crear el modelo en memoria para este metadata. Además el diseñador del Visual Studio también comienza a navegar en la peor eficiencia cuando el número de entidades es muy alta.
Si tienes un modelo muy interconectado puedes tener problemas de rendimiento, y hay que pensar en la posibilidad de dividirlo en varios archivos edmx, cuando tienes del orden de 100 entidades.

La desventaja de tener varios pequeños modelos de datos es que tendrás que mantener varios .edmx sincronizados cuando haces cambios en la base de datos.

Autor: Isabel Cabezas
Publicado: 12/03/2010  9:23 | 0  Comentarios | 0  Enlaces a este post

Lanzamiento SharePoint 2010

Microsoft ya ha anunciado la fecha de lanzamiento de SharePoint 2010 & Office 2010. Stephen Elop, Presidente de la División de Negocios de Microsoft, hará público el lanzamiento a las 11:00am del 12 de Mayo del 2010. Igualmente comunican que el RTM estará disponible en el mes de Abril.
 
Autor: Emilio Martín
Publicado: 10/03/2010  17:13 | 0  Comentarios | 0  Enlaces a este post

 Siguiente >>