Buscar este blog

domingo, 28 de febrero de 2010

Linea de guía en Visual Studio

Una linea guia es una linea vertical en el editor de texto de cualquier lenguaje que sirve para que marques un limite de columnas de texto del que no te quieres pasar, si te pasas de la linea puedes presionar enter y comenzar una linea nueva como se ve en la imagen:

Linea guia

Para obtener esto en Visual Studio 2003 en adelante se debe abrir el registro de windows con regedit y llegar a la siguiente clave HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Text Editor y añadir una nueva clave de tipo cadena llamada Guides con el valor RGB (256,0,0), 80.

La primera parte indica el color (en rgb) y la segunda parte indica la columna en que se vera la linea.

Estos son las claves del registro donde se deben poner las guias en diferentes versiones de Visual Studio:

2003: HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\7.1\Text Editor

2005: HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\Text Editor

2008: HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Text Editor

2008 Express: HKEY_CURRENT_USER\Software\Microsoft\VCExpress\9.0\Text Editor

Al parecer también funciona en SQL Server 2005 y otras versiones

Desde Visual Studio 2010 hay un complemento que permite obtener estas guias sin modificar el registro:
Productivity Power Tools
Solo pones el cursor en la columna donde quieres la guia das click derecho y escoges Add Guideline.

viernes, 26 de febrero de 2010

Como funciona el DataPager

El control DataPager nos permite añadir paginación a controles que muestran conjuntos de datos, sin embargo para que el control DataPager funcione con un control este debe implementar la interfaz IPageableItemContainer y hasta el .Net framework 3.5 el único control que implementa esta interfaz es el control ListView, por lo tanto es el único control con el que funcionara el DataPager sin modificaciones.
Para usar un DataPager con un ListView se puede usar ya sea dentro del mismo o control o colocándolo después e indicando cual es el control que se va a paginar.
Es muy sencillo a continuación se muestran los dos ejemplos:
Para usar el control dentro del ListView en que lo vamos a usar (se pone el DataPager en el LayoutTemplate:
<asp:ListView ID="ListView1" runat="server" DataSourceID="companyDS" 
            onitemcreated="ListView1_ItemCreated" >
        <LayoutTemplate>        
            <table runat="server" cellspacing="0" border="1" style="border-collapse:collapse;">
                <tr>
                    <th runat="server"><asp:Literal ID="Literal1" runat="server"
                        Text="<%$ Resources:Labels, CompanyName %>" />
                    </th>
                    <th runat="server"><asp:Literal ID="Literal2" runat="server"
                        Text="<%$ Resources:Labels, State %>" />
                    </th>
                    <th runat="server"><asp:Literal ID="Literal3" runat="server"
                        Text="<%$ Resources:Labels, Industry %>" />
                    </th>
                </tr>
                <tr runat="server" id="itemPlaceholder" />
            </table>
        <asp:DataPager ID="DataPager1" runat="server" QueryStringField="pageNumber"
            PageSize="20">
            <Fields>
                <asp:NextPreviousPagerField ButtonType="Link"
                    FirstPageText="<%$ Resources:Labels, First %>" 
                    LastPageText="<%$ Resources:Labels, Last %>"
                    NextPageText="<%$ Resources:Labels, Next %>"
                    PreviousPageText="<%$ Resources:Labels, Previous %>" 
                    ShowFirstPageButton="True" ShowNextPageButton="False" 
                    ShowPreviousPageButton="False" />
                <asp:NumericPagerField />
                <asp:NextPreviousPagerField ButtonType="Link"
                    FirstPageText="<%$ Resources:Labels, First %>" 
                    LastPageText="<%$ Resources:Labels, Last %>"
                    NextPageText="<%$ Resources:Labels, Next %>"
                    PreviousPageText="<%$ Resources:Labels, Previous %>" 
                    ShowLastPageButton="True" ShowNextPageButton="False" 
                    ShowPreviousPageButton="False" />
            </Fields>
        </asp:DataPager>
        </LayoutTemplate>
        <ItemTemplate>
            <tr runat="server">
                <td>
                    <asp:HyperLink ID="nameOutput" runat="server"
                        Text='<%# Bind("Name") %>'
                        NavigateUrl='<%# "Company.aspx?CompanyName=" + Server.UrlEncode((String)Eval("Name")) %>' />
                </td>
                <td>
                    <asp:Label ID="Label2" runat="server"
                        Text='<%# Bind("State") %>' />
                </td>
                <td>
                    <asp:Label ID="Label3" runat="server"
                        Text='<%# Bind("Industry") %>' />
                </td>
            </tr>
        </ItemTemplate>
    </asp:ListView>

O con el DataPager fuera del control, solo indicamos el control a paginar con el atributo PagedControlID:
<asp:ListView ID="ListView1" runat="server" DataSourceID="companyDS" OnItemCreated="ListView1_ItemCreated">
        <LayoutTemplate>
            <table runat="server" cellspacing="0" border="1" style="border-collapse: collapse;">
                <tr>
                    <th runat="server">
                        <asp:Literal ID="Literal1" runat="server" Text="<%$ Resources:Labels, CompanyName %>" />
                    </th>
                    <th runat="server">
                        <asp:Literal ID="Literal2" runat="server" Text="<%$ Resources:Labels, State %>" />
                    </th>
                    <th runat="server">
                        <asp:Literal ID="Literal3" runat="server" Text="<%$ Resources:Labels, Industry %>" />
                    </th>
                </tr>
                <tr runat="server" id="itemPlaceholder" />
            </table>
        </LayoutTemplate>
        <ItemTemplate>
            <tr runat="server">
                <td>
                    <asp:HyperLink ID="nameOutput" runat="server" Text='<%# Bind("Name") %>' NavigateUrl='<%# "Company.aspx?CompanyName=" + Server.UrlEncode((String)Eval("Name")) %>' />
                </td>
                <td>
                    <asp:Label ID="Label2" runat="server" Text='<%# Bind("State") %>' />
                </td>
                <td>
                    <asp:Label ID="Label3" runat="server" Text='<%# Bind("Industry") %>' />
                </td>
            </tr>
        </ItemTemplate>
    </asp:ListView>
    <asp:DataPager ID="DataPager1" runat="server" QueryStringField="pageNumber" PageSize="20"
        PagedControlID="ListView1">
        <Fields>
            <asp:NextPreviousPagerField ButtonType="Link" FirstPageText="<%$ Resources:Labels, First %>"
                LastPageText="<%$ Resources:Labels, Last %>" NextPageText="<%$ Resources:Labels, Next %>"
                PreviousPageText="<%$ Resources:Labels, Previous %>" ShowFirstPageButton="True"
                ShowNextPageButton="False" ShowPreviousPageButton="False" />
            <asp:NumericPagerField />
            <asp:NextPreviousPagerField ButtonType="Link" FirstPageText="<%$ Resources:Labels, First %>"
                LastPageText="<%$ Resources:Labels, Last %>" NextPageText="<%$ Resources:Labels, Next %>"
                PreviousPageText="<%$ Resources:Labels, Previous %>" ShowLastPageButton="True"
                ShowNextPageButton="False" ShowPreviousPageButton="False" />
        </Fields>
    </asp:DataPager>

Nótese el uso de la propiedad QueryStringField si no se usa los botones del paginador usan postbacks y con la propiedad establecida se usan links normales la diferencia es muy importante si se se esta optimizando para buscadores (que por lo general) no siguen los postbacks pero en una aplicación privada no es necesaria esa optimización.
También en los ejemplos vemos que se puede cambiar la apariencia y funcionamiento del DataPager con los controles Field que se colocan en el Template Fields, en el ejemplo se muestran Fields para un paginador numérico  y controles de página anterior y siguiente a los lados, si quisiéramos solo el paginador numérico por ejemplo solo usaríamos el Field NumericPagerField.
Hay que notar que el DataPager al utilizarse dentro del ListView prácticamente no se puede modificar gráficamente después de crearlo por lo que lo mejor es modificarlo a mano en el html de la pagina.

Para aprender más sobre el control DataPager busca en la lista de artículos sobre el control DataPager en este blog.

jueves, 25 de febrero de 2010

Optimizando Asp.Net con la eliminación del ViewState

En Asp.Net las páginas usan el ViewState como una forma de mantener el estado entre postbacks, sin embargo el ViewState se manda junto con la página usando un campo de tipo input hidden y suele ser de un tamaño considerable.
Una buena técnica para reducir el tamaño de la página generada por Asp.Net es eliminar el ViewState de los controles siempre que se pueda, esto es posible con las siguientes condiciones entre otras:
1.- La página no generara postbacks, se puede eliminar el ViewState de la página por completo.
2.- El contenido de un control se carga desde una base de datos y se puede eliminar el ViewState del control.

Una forma sencilla de comprobar si necesitamos el ViewState es eliminarlo de la página y ver cómo se comporta la página sin el mismo, si algo no funciona bien lo reactivamos en la página y lo vamos desactivando en los controles individuales (contenedores primero) hasta tener el resultado esperado.

Se puede eliminar el ViewState declarativamente o prográmaticamente por medio del atributo booleano EnableViewState o la propiedad booleana también EnableViewstate aquí vemos como quitar el ViewState de la página por completo lo que incluye todos los controles en ella y como quitarlo de un solo control:

ASP:

   1:  <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="PruebaW._Default" EnableViewState="false" %>
   2:   
   3:  <asp:Label ID="Label1" runat="server" EnableViewState="false" Text="hola" />
C#


   1:  EnableViewState = false;
   2:  Label1.EnableViewState = false;

Es de notarse que los controles aparte del ViewState tienen el ControlState el cual se almacena el mismo Input que el ViewState y no se puede eliminar por lo que nunca podremos eliminar el ViewState por completo pero si podemos reducirlo en forma bastante significativa.

miércoles, 24 de febrero de 2010

Cómo leer un ConnectionString del web.config mediante código

Existen varias maneras de guardar y usar cadenas de conexión en el web.config aquí mencionare las que conozco, si conocen otras no duden en enviarlas para incluirlas.

La primera es la más recomendada para aplicaciones sencillas ya que es la que proporciona el mismo Asp.Net para guardar las cadenas de conexión, se guarda la cadena en la sección connectionStrings del web.config, esta sección va directo en la sección configuration que es la raíz del web.config.


   1:  <connectionStrings>
   2:      <add connectionString="Data Source=Servidor\INSTANCIASQL;Initial Catalog=MiBaseDeDatos;Persist Security Info=True;User ID=NombreDeusuario;Password=xxxxxxxxxx" name="MiConnectionString" providerName="System.Data.SqlClient"/>
   3:  </connectionStrings>

y se usa de la siguiente manera:


   1:  string SuperSecreto = System.Web.Configuration.WebConfigurationManager.ConnectionStrings["MiConnectionString"].ConnectionString;

También podemos usar la sección appSettings, pero no es tan recomendado pues esta sección esta reservada para configuraciones sin categorizar, en realidad es cuestión de gusto:


   1:  <appSettings>
   2:      <add key="ConnectionString"
   3:                   value="Data Source=Servidor\INSTANCIASQL;Initial Catalog=MiBaseDeDatos;Persist Security Info=True;User ID=NombreDeusuario;Password=xxxxxxxxxx"/>
   4:  </appSettings>

La ultima forma es creando secciones de configuración personalizadas, esta es mas recomendable cuando creamos una ddl reutilizable que queremos configurar desde el web.config o el app.config y usamos esa dll desde nuestra aplicación web.
En esta entrada solo mostrare como se ve esta opción en el web.config y no mostrare su uso y creación ya que es mas complicada y prefiero mostrar el ejemplo completo en otra entrada.
Así se usa en el web.config, añadimos un sectionGroup en la seccion configSections del web.config y en la seccion configuration añadimos la sección que acabamos de configurar:


   1:  <configSections>
   2:      <sectionGroup name="miaplicacion">
   3:          <section name="connectionStrings" type="MiAplicacion.ConnectionStringsSection" allowLocation="true" allowDefinition="Everywhere"/>
   4:      </sectionGroup>
   5:  </configSections>
   6:  <miaplicacion>
   7:      <connectionStrings
   8:          ConnectionString="Data Source=Servidor\INSTANCIASQL;Initial Catalog=MiBaseDeDatos;Persist Security Info=True;User ID=NombreDeusuario;Password=xxxxxxxxxx">
   9:      </connectionStrings>
  10:  </miaplicacion>

martes, 23 de febrero de 2010

Obtener el nombre de un elemento de Enum

Aquí les dejo un truco rápido para obtener una cadena con el nombre de un elemento de un Enum:

   1:  class Program {
   2:      enum PruebaEnum {
   3:          Enum1,
   4:          Enum2
   5:      }
   6:      static void Main(string[] args) {
   7:          string enumName = Enum.GetName(typeof(PruebaEnum), PruebaEnum.Enum2);
   8:          Console.WriteLine("Nombre de elemento de Enum: {0}", enumName);
   9:          Console.ReadLine();
  10:      }
  11:  }

La clase Enum también tiene otros métodos muy prácticos: obtener todos los nombres del enum, leer un enum desde una cadena obtener todos los miembros del enum en un arreglo.
Aquí esta el ejemplo completo:

   1:  class Program {
   2:      enum PruebaEnum {
   3:          Enum1,
   4:          Enum2
   5:      }
   6:      static void Main(string[] args) {
   7:          string enumName = Enum.GetName(typeof(PruebaEnum), PruebaEnum.Enum2);
   8:          Console.WriteLine("Nombre de elemento de Enum: {0}", enumName);
   9:          PruebaEnum parsed = (PruebaEnum)Enum.Parse(typeof(PruebaEnum), enumName);
  10:          string[] names = Enum.GetNames(typeof(PruebaEnum));
  11:          Console.WriteLine("Todos los elementos del Enum");
  12:          foreach(string i in names) {
  13:              Console.WriteLine(i);
  14:          }
  15:          Console.WriteLine("Desde GetValues");
  16:          Array enums = Enum.GetValues(typeof(PruebaEnum));
  17:          for(int i = 0; i < enums.Length; i++) {
  18:              Console.WriteLine("Valor {0}", Enum.GetName(typeof(PruebaEnum)
  19:                  , (PruebaEnum)enums.GetValue(i)));
  20:          }
  21:          Console.ReadLine();
  22:      }
  23:  }

lunes, 22 de febrero de 2010

Leyendo y Escribiendo XML con Linq en c#

En este ejemplo uso Linq para crear XML desde un árbol de objetos y después poder leer de nuevo el XML con Linq y crear de nuevo los objetos.
Por supuesto para correr los ejemplos hay que crear los tipos de datos necesarios, todas las colecciones son de tipo List<>
Escribir (Linq a XML):


   1:  List<Pelicula> peliculas = new PeliculaTA().Retrieve();
   2:  var xmlArch =
   3:      new XElement("Peliculas",
   4:      from m in peliculas
   5:      select new XElement("Pelicula",
   6:          new XElement("Titulo", m.Titulo),
   7:          new XElement("Director", m.Director),
   8:          new XElement("Estrenado", m.Estrenado),
   9:          new XElement("Actores",
  10:              from a in m.Actores
  11:              select new XElement("Actor",
  12:                  new XElement("Nombre", a.Nombre),
  13:                  new XElement("Nacimiento", a.Nacimiento),
  14:                  new XElement("Roles",
  15:                      from r in a.Roles
  16:                      select new XElement("Rol",
  17:                          new XElement("NombrePelicula", r.Pelicula),
  18:                          new XElement("NombreRol", r.NombreRol)))))));
  19:  File.WriteAllText("peliculas.xml", xmlArch.ToString());

Leer (XML a Linq):


   1:  XElement xmlArch = XElement.Load("peliculas.xml");
   2:  var peliculas =
   3:      from m in xmlArch.Descendants("Pelicula")
   4:      select new Pelicula {
   5:          Titulo = (string)m.Element("Titulo"),
   6:          Director = (string)m.Element("Director"),
   7:          Estrenado = (DateTime)m.Element("Estrenado"),
   8:          Actores = (from c in m.Elements("Actores").Descendants("Actor")
   9:                     select new Actor {
  10:                         Nombre = (string)c.Element("Nombre"),
  11:                         Nacimiento = (DateTime)c.Element("Nacimiento"),
  12:                         Roles = (from r in c.Elements("Roles").Descendants("Rol")
  13:                                  select new Rol {
  14:                                      Pelicula = (string)r.Element("NombrePelicula"),
  15:                                      NombreRol = (string)r.Element("NombreRol")
  16:                                  }).ToList()
  17:                     }).ToList()
  18:      };

El resultado de el último ejemplo es un Enumerable<pelicula> el cual hay que recorrer por ejemplo con foreach para obtener resultados.

Para aprender mas acerca de Linq visita:
Lista de artículos acerca de Linq

Para aprender más sobre el uso de XML en .Net Framework visita:
Lista de artículos acerca del uso de XML en .Net Framework

sábado, 20 de febrero de 2010

Arreglos de tipos anónimos en Visual Basic .Net

En una edición anterior vimos el uso de arreglos de tipos anónimos en C# en esta edición anexamos el ejemplo con Visual Basic, la síntaxis es muy parecida:


        Dim arreglo() = {New With {.Miembro1 = "hola", .Miembro2 = 10}, _
          New With {.Miembro1 = "mundo", .Miembro2 = 5}}
        For Each i As Object In arreglo
            Console.Out.WriteLine("Miembro1: {0}, Miembro2: {1}", i.Miembro1, i.Miembro2)
        Next

viernes, 19 de febrero de 2010

Tipos anónimos en Visual Basic .Net

En una edición anterior hablamos sobre los tipos anónimos y su uso en c sharp en esta edición solo completamos el ejemplo en Visual Basic, la sítaxis es muy parecida aunque es un poco más sencilla en c sharp.
En fin aquí esta el ejemplo:

        Dim tipo = New With {.Miembro1 = "hola mundo", .Miembro2 = 10}
        Console.Out.WriteLine("Miembro1: {0}, Miembro2: {1}", tipo.Miembro1, tipo.Miembro2)

jueves, 18 de febrero de 2010

Arreglos de tipos anónimos

En la última edición vimos como usar los tipos anónimos de .Net pero que pasa si queremos usarlos en un arreglo?. Basta declarar la variable del arreglo como y sin tipo de dato para los elementos del arreglo, tambien debemos declarar los elementos del arreglo en el inicializador del arreglo cuidando que todos usen la misma forma. Despues podemos pasar a usar el arreglo siempre con el tipo de datos var.
Aqui esta el ejemplo:

            var arreglo = new[] { new { Miembro1 = "hola", Miembro2 = 10 },
                new { Miembro1 = "mundo", Miembro2 = 5 } };
            foreach(var i in arreglo) {
                Console.WriteLine("Miembro1: {0}, Miembro2: {1}", i.Miembro1, i.Miembro2);
            }

miércoles, 17 de febrero de 2010

Tipos Anónimos

Una de las nuevas caracteristicas de .Net Framework es que podemos declarar tipos en el mismo lugar en que se van a utilizar y de una forma simplificada de tal modo que si necesitamos un tipo que se va a utilizar solo temporalmente en una zona de codigo muy corta podemos usar un tipo anónimo y listo:
Aqui esta el ejemplo:


var tipo = new { Miembro1 = "hola", Miembro2 = 10 };
Console.WriteLine("Miembro1: {0}, Miembro2: {1}", tipo.Miembro1, tipo.Miembro2);

martes, 16 de febrero de 2010

SEO con el control DataPager

Usando Asp.Net es fácilisimo hacer sitios Web en muy poco tiempo, sin embargo estos sitios frecuentemente no son amistosos con los buscadores de Internet, es decir no nos ayudan con el SEO, ya que generan links que navegan con javascript o botones con postback los cuales no pueden ser seguidos por los robots de los buscadores.

Este es el caso de los controles GridView y ListView que cuando estan configurados para paginar generan ligas de página que funcionan ya  sea con javascript o postback.

Por fortuna en el caso del control DataPager (que se utiliza con el control ListView) podemos indicarle que genere ligas normales es decir que genera peticiones GET y pueden ser seguidas fácilmente por los robots siendo así una gran ayuda para el SEO.

Para indicar este comportamiento en el control DataPager basta incluir el atributo QueryStringField en el tag del DataPager:

<asp:DataPager ID="DataPager1" runat="server" PageSize="4" QueryStringField="pageNumber">

con esto el control generara ligas que incluyan el valor pageNumber en el querystring indicando la pagina del ListView que se desea ver.

El control DataPager solo funciona de momento con el control ListView pero en otra entrada veremos como hacer que el control GridView modificando el comportamiento del mismo.

Como nota final hay que decir que hay que tener cuidado cuando se usa la propiedad QueryStringField ya que cuando el querystring de la pagina incluye una variable sin valor algo como /pagina.aspx?foo el mismo generara una excepción sin importar que la variable foo no tenga nada que ver con el DataPager, solo hay que cuidar el no tener querystrings con variables sin valor.

Para aprender más sobre el control DataPager busca en la lista de artículos sobre el control DataPager en este blog.

Bienvenidos a Solo Net

En primer les quiero dar la bienvenida a este nuevo blog.
Este espacio se crea para publicar tips de Net Framework

Mi intención es convertir este blog en un punto de encuentro donde todos aprendamos de todos, y así consigamos enriquecernos mutuamente.