Echemos un vistazo al Bing Map Control

Septiembre 18, 2009

Estoy hablando del control que Microsoft tiene para representar el mapa del mundo, sus provincias,  países y calles, dicho de otra manera es el Google Earth de Microsoft. El ejemplo que voy a mostrar es muy sencillo pero sirve (al menos función conmigo) para familiarizarse con el control de Microsoft. El punto de partida comienza aca, donde explican que es un control de Javascript que contiene todos los métodos, propiedades y eventos. De este lado nos descargamos el CHM(la ayuda) del SDK para tener la documentación de las clases con ejemplos y todo.

Pero vamos directo al código y a medida que se van viendo las clases se van comprendiendo mejor el funcionamiento.

El puntapié inicial lo damos agregando el script que tiene todo el control (por supuesto que esta hosteado por Microsoft) en nuestra pagina, lo hacemos de esta manera en el Header del HTML:

<head>
   <title>Mapa del mundo</title>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
   <script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2"></script>
</head>

La primer clase con que nos encontramos es la mas importante y es VEmap.

Un ejemplo básico de instancia de un mapa es(obviamente todo el código es de Javascript):

function GetMap()
        {
           map = new VEMap('myMap');
           map.LoadMap(CapFed, 11, VEMapStyle.Road, false, VEMapMode.Mode2D, true, 1);
        }

Donde myMap vamos a ver mas adelante que es el DIV en el HTML donde vamos a mostrar el mapa. Para las propiedades del método LoadMap:

la 1era es la zona donde queremos que aparezca exactamente (esto representa también una clase llama VELatLong que la explicamos mas adelante e indica Latitud y Longitud de cualquier lugar del mundo donde queremos que se inicie nuestro mapa.

La 2da es el zoom que va tener al momento de renderear.

La 3ra es el estilo de mapa podemos elegir entre:  Road (calles), Shaded (es como el Road pero permite niveles de sombreado), Aerial (es la clásica vista satelital con los terrenos del suelo: montañas, ríos, etc.), Hybrid  (es el aerial con los nombres de las ciudades, provincias y paises), Oblique y Birdseye son ambos estilos de imágenes de mapas y el BirdseyeHybrid que es como el Birdseyes pero con los nombres de las ciudades, provincias y países. A nosotros nos interesa el estilo Road.

4to Parámetro de Fixed, false para que puedas moverte por el mapa y true para que el mapa este fijo y no lo puedas mover.

5to el modo 2D o 3D (para 3D tenés que instalar un cliente).

6to showSwitch es la barrita que permite cambiar de 2D a 3D moverte en el mapa con el Zoom y cambiar el estilo de mapa, el default es True.

7to tileBuffer es el buffer que usa al cargar el mapa.

8to es mapOptions que permite la carga de otro mapa.

Ahora bien nos falta decirle donde queremos que inicie la vista del mapa y eso como comentaba anteriormente lo hacemos con el objeto VELatLong CapFed. Se forma de esta manera:

var CapFed = new VELatLong(-34.62473282635766, -58.520393371582045);

Así como esta inicia el mapa en Capital Federal y como esta en zoom 11 se logra ver hasta el 1er Cordón del Conurbano Bonaerense de la Provincia de Buenos Aires (Argentina por supuesto).

Lo primero que vamos a hacer es agregar un Pin a algún punto dentro del mapa. Para lograrlo basta con instancia un objeto VELatLong con el lugar exacto (alguno se puede preguntar como lo consigo? yo uso este programita proporcionado por microsoft que me muestra las coordenadas MapCruncher aunque su funcionalidad sea otra mucho mas amplia, sirve xD). El código es el siguiente:

<head>
   <title></title>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
   <script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2"></script>
  <script type="text/javascript">
      var map = null;

     //Esta Latitud y Longitud mas o menos es Capital Federal
      var CapFed = new VELatLong(-34.62473282635766, -58.520393371582045);
      //Esta Latitud y Longitud mas o menos es Capital Federal
      var CapFedDestino = new VELatLong(-34.69646117, -58.38546753);

 function GetMap() {
           map = new VEMap('myMap');
           route = new VERoute;
           map.LoadMap(CapFed, 11, VEMapStyle.Road, false, VEMapMode.Mode2D, true, 1);
           var myPolygon = new VEShape(VEShapeType.Pushpin, CapFed);
           map.AddShape(myPolygon);
           myPolygon.SetTitle("Origen");
           myPolygon.SetDescription("Este es el punto 1");

           var myPolygon2 = new VEShape(VEShapeType.Pushpin, CapFedDestino);
           map.AddShape(myPolygon2);
           myPolygon2.SetTitle("Destino");
           myPolygon2.SetDescription("Este es el punto 2");
       }

   </script>
   </head>
<body onload="GetMap();">

Creando Rutas entre dos Puntos

Ahora vamos a realizar una de las cosas mas interesantes que tiene que son crear una ruta entre dos puntos geográficos.

<head>
      <title></title>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2"></script>
      <script type="text/javascript">
         var map = null;
        var CapFed = new VELatLong(-34.62473282635766, -58.520393371582045);

         function GetMap()
         {
            map = new VEMap('myMap');
            map.LoadMap(CapFed, 11, VEMapStyle.Road, false, VEMapMode.Mode2D, false, 1);
         }

         function GetRouteMap()
         {
            var locations;

            if (legForm.legType[0].checked)
            {
            //Los parametros son Desde, por donde y Hasta
                locations = new Array("Villa Devoto Argentina", "Moron Buenos Aires Argentina", "San Justo Buenos Aires Argentina", "Lanus Buenos Aires Argentina");
            }
            else if (legForm.legType[1].checked)
            {
                locations = new Array("Villa Devoto Argentina", "Lanus Buenos Aires Argentina");
            }

            var options = new VERouteOptions;
            options.DrawRoute      = true;
            options.SetBestMapView = false;
            map.GetDirections(locations, options);
         }

     </script>
   </head>
   <body onload="GetMap();" style="font-family:Arial">
      <h3>Rutas</h3>

      <div id='myMap' style="position:relative; width:100%; height:400px;"></div>

      <form name="legForm">
         Route:          <br/>
         <input id="thruAdelina" type="radio" name="legType" checked="checked"/>
        De Villa Devoto a Lanus (pasando por Moron y San Justo)
         <br/>
         <input id="thruMunro" type="radio" name="legType"/>
        De Villa Devoto a Lanus (sin escalas)
      </form>

      <form name="dirsForm">
      </form>
     <input id="getroutemap" type="button" value="Realizar Ruta" onclick="GetRouteMap();"/>
  </body>
</html>

Decía interesante porque el Array Locations en un caso tiene como inicio: el Origen(Villa Devoto), y luego tiene dos puntos por donde quiero que pase hasta llegar a mi destino(Lanus), esto tiene 2 cosas que son muy buenas la primera es que puedo indicarle las escalas que yo quiera y la segunda y mas fantástica es que solo necesito indicarle el nombre del barrio la provincia y el país (yo le di esos datos para que sea bien preciso) y el control decide la mejor ruta y realmente es una ruta que pasa por calles correctas sino basta con realizar un zoom y ver el recorrido por uno mismo.

Este esta es la ruta desde Villa Devoto hasta Lanus pasando por las 2 escalas:

1

Esta es la ruta realizada desde Villa Devoto hasta Lanus sin escalas:

2

Bueno esto es simplemente una introducción a las cosas que se pueden realizar que son realmente muchas y muy interesantes. A continuación voy a dejar tanto el ejemplo que realice como algunos links de interés para meterse mas en profundidad con el tema.

Código de Ejemplo (Hecho en VS2008): Link

Paginas de Interés:

Bing Maps Interactive SDK

Usar rutas y direcciones

Blog del Bing Maps

Saludos



Un solo RowDataBound para varias GridView

Julio 28, 2008

Suele pasar que tengamos mas de una grilla (gridView en .NET 2.0) en una misma pagina Web y es incomodo, cuando se necesita que cada fila tenga un comportamiento, copiar y pegar código para cada grilla en el evento RowDataBound. Por ejemplo, si quiero a cada fila agregarle algo de Javascript para su validación o simplemente cambiar de color esa fila.

Este ejemplo muetra como enlazar un solo evento RowDataBound para las grillas que sean necesarias en un misma pagina. Esta hecho en  ASP.NET (VB.NET) 2.0

Una vez creado el proyecto y agregada las 2 GridView, simplemente en el Code Behind y nos paramos sobre una GridView.

foto0

Y luego en sus eventos vamos al RowDataBound:

foto01

Una vez que nos genero el código simplemente vamos hacia el handles (que esta al final) con comas vamos agregando todos los objetos que queremos que ese evento maneje:

foto1

Ahora bien, la pregunta es simple: ¿Como distingo una Grilla de Otra?, simple:

Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) _
                   Handles GridView1.RowDataBound, GridView2.RowDataBound

       If e.Row.RowType = DataControlRowType.DataRow Then 'DataRow Vale las row que tienen datos, de esta manera se saltea el header,el footer y el pager
           Dim idCelda As Integer
           Dim gvrow As GridViewRow = CType(e.Row.Cells(idCelda).NamingContainer, GridViewRow)
           Select Case CType(sender, GridView).ID
               Case GridView1.ID
                   gvrow.BackColor = Drawing.Color.Red
               Case GridView2.ID
                   gvrow.BackColor = Drawing.Color.LightGoldenrodYellow
           End Select
       End If

   End Sub

Bastante sencillo. Y así es como nos queda:

fotofinal

Adjunto el proyecto aqui

Saludos.


PopUp o Ventanas Modales en ASP.NET

Abril 16, 2008

Muchas veces porque queda muy agradable a la vista, es conveniente abrir una ventana (popup) con información adicional sobre un ítem deseado. Otro caso (particularmente el que me tocó desarrollar) puede ser hacer una especie de Wizard donde las ventanas cumplan una suerte de varios pasos donde se pueda ir para atrás,adelante y/o finalizar, al mejor estilo instalación de cualquier soft (siguiente,siguiente,siguiente,instalar…finalizar).

Lo que voy a mostrar parte de una pagina Principal (Pagina Madre) que es la que va a abrir el popup y acá se pueden usar 2 maneras, una ventana modal o una ventana modeless.

ventana modal: Este tipo de ventanas no permite la interacción con la ventana anterior mientras este abierta, de hecho interrumpe cualquier ejecución que se este haciendo por atrás. Por ejemplo si nosotros hacemos un postback y en el servidor abrimos una ventana con el método de JS window.showModalDialog puede ocurrir que la pagina madre quede en blanco o a medio cargar.

ventana modeless: Estas ventanas si permiten la interacción con su ventana madre, de hecho es posible hacer click en la ventana de atrás y lo va a permitir. Por lo comentado arriba este tipo modal puede ser útil. Pero si por ejemplo vamos a abrir una modal de una fila en un gridview que tiene un enlace a eliminarlo, si lo hace mientras esta la modeles abierta se lo va a permitir.

Este ejemplo esta diseñado para IE 6.0 en adelante y voy a usar VS2005. Básicamente voy a hacer esto:

Voy a usar una sola pagina como Wizard pero pueden ser las que se necesiten, al fin y al cabo todas terminan en un pagina de Fin.

La pagina principal va a contar con script porque va a mantener una variable para poder tomarla al final:

<script>
var Guardar;
function DeseaGuardar()
{
window.document.Form1.txtOculto.value=Guardar;
__doPostBack('lnkGuardar','');
}
function Ejecutar()
{
//Agregamos el JS para pasar el parametro
var param='';
param='valor=' + window.document.Form1.TextBox1.value;
WizardGeneral(200,550,'Default2.aspx',param);
}
</script>

La función WizardGeneral esta en un JS que adjunto con todo el proyecto al final y es la que arma la URL para abrir el Wizard de una manera u otra (Modal/Modeless) . Yo lo hago con una función en el evento onclick llamando a Ejecutar pero por ejemplo si queremos hacer popups de una grilla agregándole a todas las rows solo vamos a necesitar el ID de cada row para levantar los datos en el popup con lo cual se puede hacer todo en la 1era carga de la pagina agregando el id en el evento RowDatabound. Yo a modo de ejemplo solo modifico un textbox.

El HTML de la pagina sería algo así:

<HTML>
<HEAD>
<title>Prueba</title>
<meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
<meta content="Visual Basic .NET 7.1" name="CODE_LANGUAGE">
<meta content="JavaScript" name="vs_defaultClientScript">
<script language="javascript" src="JS/ScriptJS.js"></script>
</HEAD>
<body style="text-align: left">
<form id="Form1" method="post" runat="server">
&nbsp;<table>
<tr>

</tr>
</table>
<br />
<table width="100%">
<tr>
<td style="text-align: center;" colspan="3">
<asp:Label ID="lblerror" runat="server" Width="100%"></asp:Label></td>
</tr>
<tr>
<td style="width: 24px">
<asp:Label ID="Label1" runat="server" Text="Valor"></asp:Label></td>
<td style="width: 60px">
<asp:TextBox ID="TextBox1" runat="server" Width="279px"></asp:TextBox>
</td>
<td style="width: 100px">
</td>
</tr>
<tr>
<td style="width: 24px">
</td>
<td style="width: 60px; text-align: center;">
<input id="btnBoton" type="button" value="Popup" runat =server  /></td>
<td style="width: 100px">
</td>
</tr>
</table>
<br />
<asp:LinkButton ID="lnkGuardar" runat="server"></asp:LinkButton>&nbsp;
<input id="txtOculto" style="width: 54px" runat =server  type="hidden" />
</form>
</body>
</HTML>

Al final de la pagina hay 2 elementos importantes un Link, que es el que va a causar el postback de la pagina madre cuando termine el wizard y un hidden que es el que va a tener el valor de retorno del wizard.

El código de servidor es mas o menos este:

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Introducir aquí el código de usuario para inicializar la página
If Not Page.IsPostBack Then
Try
txtOculto.Value = ""
btnBoton.Attributes.Add("onclick", "javascript:Ejecutar()")
Catch ex As Exception
lblerror.Text = ex.Message
End Try
End If
End Sub

Protected Sub lnkGuardar_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles lnkGuardar.Click
'txtOculto tiene el valor modificado que me devuelve el Wizard
If Not String.IsNullOrEmpty(txtOculto.Value) Then TextBox1.Text = txtOculto.Value
End Sub

Cuando la pagina de fin se cierre “cargar” de nuevo esta pagina ósea va a pasar por el page_load por eso hay que manejar bien el page.ispostback para no pisar valores y luego va a entrar por el click del Link que nosotros le formamos a hacer con la instrucción de Javascript __doPostBack.

La Pagina del Wizard tiene este HTML:

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Pagina del Wizard</title>
<base target="_self">
</head>
<body >
<script language="javascript">
   1:
   2:         var sData = dialogArguments;
   3:         sData.Guardar= '';
   4:         sData.DeseaGuardar();
   5:         /*function cargarVentana ()
   6:                 {
   7:                  document.form1.TextBox1.value=window.dialogArguments;
   8:                 }*/
   9:
  10:       function sourceCode()  //Para ver el codigo fuente
  11:         {
  12:          d=window.open();
  13:          d.document.open('text/plain').write(document.documentElement.outerHTML);
  14:          }

</script>
<form id="form1" runat="server" method="post">
<table>
<tr>
<td style="width: 100px">
<asp:Label ID="Label1" runat="server" Text="Valor del Wizard" Width="118px"></asp:Label></td>
<td style="width: 100px">
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td style="width: 100px">
</td>
<td style="width: 100px">
<asp:Button ID="Button1" runat="server" Text="Ejecutar" /></td>
</tr>
<tr>
<td colspan="2">
<asp:Label ID="Label2" runat="server" ForeColor="#0000C0" Text="Al cambiar esta valor se modifica el textbox de la pagina principal"></asp:Label></td>
</tr>
</table>
</form>
</body>
</html>

Tiene algunas particularidades la primera es que tiene le atributo target= self esto es para cuando hacemos el response.redirect a la pagina de fin no nos abra una pagina sino que siga en la misma. Después la función Javascript toma el dialogArguments que son las variables o funciones de la pagina madre. Y por ultimo algo que nos puede ser muy útil para depurar es una función para ver el HTML de la pagina cuando se esta ejecutando, porque las modales no dejan hacer click derecho para ver el código. Simplemente se agrega el nombre (sourceCode) en el evento onload del Form y listo apenas carga la pagina tenemos una nueva ventanita con el HTML :D .

Este es el código de servidor:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Try
If Not Page.IsPostBack Then
TextBox1.Text = Request.Params("valor")
Else
Dim strpage As String = "General_Fin_W.aspx"
Dim paramFinal As String = "modo=modificacion&datos=".ToString + TextBox1.Text
strpage += "?".ToString + paramFinal.ToString 'General_Fin_W.aspx?modo=modificacion&datos=
Response.Redirect(strpage)
End If
Catch ex As Exception
Response.Write(ex.Message)
End Try
End Sub

y por ultimo la pagina de Fin HTML y código de Servidor:

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title></title>
<script language="JavaScript" type="text/javascript">
   1:
   2:      function CerrarWizard()
   3:      {
   4:       var sData = dialogArguments;
   5:
   6:         //var datos= document.Form1.HiddenField1.value; // Esto vale lo que 
   7:         //termina concatenando en el wizard
   8:         var datos= document.Form1.HiddenField1.value;
   9:         sData.Guardar=datos;
  10:         sData.DeseaGuardar();
  11:         window.close();
  12:         }
  13:
  14:        function sourceCode()  //Para ver el codigo fuente
  15:          {
  16:          d=window.open();
  17:          d.document.open('text/plain').write(document.documentElement.outerHTML);
  18:          }
  19:
  20:

</script>
</head>
<body class="BodyNormal" onactivate ="CerrarWizard();">
<form id="Form1" runat="server" >
<div style="text-align: center" >
<asp:Label ID="lblMensajes" runat="server" CssClass="labelmensaje" Width="98%">Cargando ...</asp:Label><br />
<asp:HiddenField ID="HiddenField1" runat="server" />

</div>
</form>
</body>
</html>

Tiene una simple pantalla blanca con un mensaje cargando…. (pero la idea es que prácticamente no aparezca) porque como se ve en la funcion hace en onload le asigna el valor a sData.Guardar (osea el valor oculto de la pagina madre) y despues hace un window.close.

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Select Case Request.Params("modo")
Case "modificacion"
If Not String.IsNullOrEmpty(Request.Params("datos")) Then
HiddenField1.Value = Request.Params("datos")
End If
End Select
End Sub

La idea es hacer una sola pagina de fin en caso de que necesitamos varios Wizard por ejemplo para cargar Personas o Productos, etc. Todas devuelven 1 dato por ejemplo si son Wizard de Alta podrían devolver el ID a la pagina Madre para poder levantarlo desde ahí.

El proyecto completo esta aqui

Saludos.


Agregar un ID oculto en un GridView

Marzo 28, 2008

Voy a mostrar una manera muy sencilla de ocultar, y poder mas adelante obtener, un ID en una grilla (GridView) en VS2005, ASP.NET 2.0.

Una vez agregada la GridView y seleccionado los campos (no uso campos automáticos) es elegir, por lo general la primer columna (columna 0), el template. Esto lo hacemos de esta manera:

foto1.jpg

Entonces el código de HTML nos quedaría así:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" CellPadding="4"
           ForeColor="#333333" GridLines="None">
           <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
           <RowStyle BackColor="#EFF3FB" />
           <EditRowStyle BackColor="#2461BF" />
           <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
           <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
           <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
           <AlternatingRowStyle BackColor="White" />
           <Columns>
               <asp:TemplateField HeaderText="Cargo">
                   <ItemTemplate>
                       <asp:Label ID="Label1" runat="server" Text='<%# Bind("cargo") %>'></asp:Label>
                   </ItemTemplate>
               </asp:TemplateField>
               <asp:BoundField DataField="nomCom" HeaderText="Nombre" />
               <asp:ButtonField CommandName="ver" Text="Ver" />
           </Columns>
       </asp:GridView>

Dentro del Tag ItemTemplate, vamos a agregar el Label Oculto y nos va a quedar de esta manera:

<ItemTemplate>
         <asp:Label ID="lblID" runat="server" Text='<%# Bind("id") %>' Visible="false"></asp:Label>
         <asp:Label ID="Label1" runat="server" Text='<%# Bind("cargo") %>'></asp:Label>
</ItemTemplate>

A la hora de llenar la Grilla es simplemente haciendo el dataBind del objeto gridview y obviamente el dataset o datatable tiene que tener la columna ID
A la hora de obtener el ID, yo voy a mostrar el código para hacerlo tanto de Javascript como desde el Servidor.
Para el Lado del Servidor:

Uso el Buttonfield de la grilla para al seleccionarlo poder mostrar el ID.

Protected Sub GridView1_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles GridView1.RowCommand
      Dim idCelda As Integer = 0 'Como el ID oculto esta en la 1er celda le pongo 0 (El indice de Columnas empieza desde 0)
      Select Case e.CommandName
          Case "ver"
              Dim indice As Integer = e.CommandArgument ' Me paro en la row que hizo click
              Dim row As GridViewRow
              row = GridView1.Rows(indice) ' la busco en la Grilla
              lblIDSeleccion.Text = ""
              lblIDSeleccion.Text = Convert.ToInt32(CType(row.FindControl("lblID"), Label).Text) ' encuentro el id oculto en el Label (lblID) y se lo asigno a un objeto Label
      End Select
  End Sub

Para el Lado del Cliente:
Bueno hay varias maneras pero yo voy a inyectar JS al momento de hacer el RowDatabound de la grilla ósea en el momento de llenar fila por fila.
Del lado del Servidor sería esta código:

Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
       If e.Row.RowType = DataControlRowType.DataRow Then 'DataRow Vale las row que tienen datos, de esta manera se saltea el header,el footer y el pager
           Dim idCelda As Integer = 0
           Dim lbl As Label
           Dim objButton As LinkButton
           Dim gvrow As GridViewRow = CType(e.Row.Cells(idCelda).NamingContainer, GridViewRow)
           lbl = CType(gvrow.Cells(idCelda).FindControl("lblID"), Label)
           objButton = CType(gvrow.Cells(2).Controls(0), LinkButton) 'Columna 2 control 0 asi me paro en la ultima columna
           objButton.Attributes.Add("onclick", "javascript:return Ejecutar('" & lbl.Text & "')")
       End If
   End Sub

y como se ve hay una inyección de JS de la función Ejecutar que ahí va el simplisimo codigo:

<script language =javascript >
   1:
   2: function Ejecutar(id)
   3: {
   4: alert ('El ID Seleccionado es: ' +id);
   5: return false;
   6: }

</script>

Descargar el proyecto aqui.

Es una manera muy simple de ocultarlo y es agradable a la vista del usuario que no vea un número que en definitiva a él no le significa nada.

Saludos


Llenar un DropDownList en una GridView

Enero 23, 2008

Hay una manera muy simple de llenar un combo, ya sea con los mismo valores o con distintos, en cada fila de una GridView en ASP.NET 2.0 (VS 2005). Lo primero que hay que hacer es (obviamente) dropear una gridview en la pagina y al insertar las columnas a la que queremos que sea nuestro combo la convertimos en Template de esta manera:

foto1.jpg

Hecho esto vamos a editar nuestro Template asi:
foto2.jpg

SIN USAR EDITITEMTEMPLATE

Dentro de ItemTemplate vamos a eliminar el Label que nos viene por defecto y dropear un DropDownList, no hace falta hacerlo en EditTemplate. Nos queda algo asi:
foto3.jpg

Al termina la edición nos queda algo asi:
foto4.jpg

Ahora nos pasamos a la parte HTML de la pagina para ver como nos queda la grilla:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" CellPadding="4"

           ForeColor="#333333" GridLines="None">

           <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />

           <Columns>

               <asp:BoundField DataField="nomCom" HeaderText="Nombre" />

               <asp:TemplateField HeaderText="Cargo">

                   <EditItemTemplate>

                       <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

                   </EditItemTemplate>

                   <ItemTemplate>

                       <asp:DropDownList ID="DropDownList1" runat="server" Width="179px" DataTextField="CARGO" DataValueField="ID">

                       </asp:DropDownList>

                   </ItemTemplate>

               </asp:TemplateField>

           </Columns>

           <RowStyle BackColor="#EFF3FB" />

           <EditRowStyle BackColor="#2461BF" />

           <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />

           <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />

           <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />

           <AlternatingRowStyle BackColor="White" />

       </asp:GridView>

En mi caso todos los combos se llenan con la misma información por eso agrego el DataTextField ahí, esto se podría hacer del lado servidor.
Ahora lo mas importante del código esta en el evento RowDataBound de la grilla y es algo muy simple:

Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound        Try

            If e.Row.RowType = DataControlRowType.DataRow Then 'DataRow Vale las row que tienen datos, de esta manera se saltea el header,el footer y el pager

                Dim ddl As DropDownList

                Dim dt2 As DataTable = LlenarTabla2()

                'Celda 1 es donde esta el DropdownList

                Dim gvrow As GridViewRow = CType(e.Row.Cells(1).NamingContainer, GridViewRow)

                ddl = CType(gvrow.FindControl("DropDownList1"), DropDownList)

                ddl.ClearSelection()

If ddl IsNot DBNull.Value Then

                    ddl.DataSource = dt2

                    ddl.DataBind() 'Lleno el combo

                End If

                'Después de llenar el combo se puede asignar el valor si es que tenia uno

                'aca haciendo ddl.ddl.SelectedValue =...

            End If

        Catch ex As Exception

            Throw ex

        Finally

End Try

    End Sub

Al ejecutar el proyecto la pagina nos queda de esta manera.

foto5.jpg

Adjunto el proyecto aqui.

USANDO EDITITEMTEMPLATE

También se pueden usar las hermosas características que nos proporciona .NET 2.0 y usar la columna CommandField con los botones de Editar y Actualizar.

En este caso el HTML nos quedaría de esta manera:

<asp:GridView  ID="GridView2"  runat="server"

            OnRowCancelingEdit="GridView2_RowCancelingEdit"  OnRowEditing="GridView2_RowEditing"

            DataKeyNames="ID"  OnRowUpdating="GridView2_RowUpdating"  OnRowUpdated="GridView2_RowUpdated"

            ShowFooter="True"  CellPadding="4" ForeColor="#333333" GridLines="None" AutoGenerateColumns="False" >

        <Columns>

                <asp:BoundField DataField="nomCom" HeaderText="Nombre" />

                <asp:TemplateField HeaderText="Cargo">

                    <EditItemTemplate>

                        <asp:DropDownList ID="DropDownList1" runat="server" Width="179px" DataTextField="CARGO" DataValueField="ID">

                        </asp:DropDownList>

                    </EditItemTemplate>

                    <ItemTemplate>

                    <asp:Label ID="CargoText" runat="server" Text='<%# Eval("Cargo") %>'></asp:Label>

                    </ItemTemplate>

                </asp:TemplateField>

                <asp:CommandField ShowEditButton="True" EditText="Editar" />

            </Columns>

             <FooterStyle BackColor="#1C5E55" Font-Bold="True" ForeColor="White" />

             <RowStyle BackColor="#E3EAEB" />

             <EditRowStyle BackColor="#7C6F57" />

             <SelectedRowStyle BackColor="#C5BBAF" Font-Bold="True" ForeColor="#333333" />

             <PagerStyle BackColor="#666666" ForeColor="White" HorizontalAlign="Center" />

             <HeaderStyle BackColor="#1C5E55" Font-Bold="True" ForeColor="White" />

             <AlternatingRowStyle BackColor="White" />

    </asp:GridView>

La primer diferencia es que el Dropdownlist ahora está dentro de una Tag edititemtemplate, esto es porque el combo no va aparecer desde un principio con el ejemplo anterior sino que solo se va a renderear para la row que quiera editar. Y que se mostrará en su lugar? Buena pregunta, para eso está el ItemTemplate que muestra algo por defecto en todas las rows o como en mi caso el valor de “Cargo” (esto va a salir del datatable que llenará la grilla, le agrego un valor por defecto).

Ahora vamos al código en VB en este caso no solo voy a necesitar RowDataBound sino también el evento RowEditing (el que entrará en acción cuando el usuario de click a la row):

Partial Class _Default

    Inherits System.Web.UI.Page

    Dim dt1 As DataTable = LlenarTabla1()

    Dim ht As Hashtable

    Dim flag As Boolean = FalseProtected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        Try

            If Not Page.IsPostBack Then

                dBindData()

            End If

        Catch ex As Exception

            Throw ex

        End Try

    End Sub

Sub dBindData()

      GridView2.DataSource = dt1

      GridView2.DataBind()

End Sub

Protected Sub GridView2_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView2.RowDataBound

       Try

           If e.Row.RowType = DataControlRowType.DataRow Then 'DataRow Vale las row que tienen datos, de esta manera se saltea el header,el footer y el pager

               Dim ddl As DropDownList

               Dim dt2 As DataTable = LlenarTabla2()

               'Celda 1 es donde esta el DropdownList

               Dim gvrow As GridViewRow = CType(e.Row.Cells(1).NamingContainer, GridViewRow)

               ddl = CType(gvrow.FindControl("DropDownList1"), DropDownList)

If ddl IsNot Nothing Then

                   ddl.ClearSelection()

                   If ddl IsNot DBNull.Value Then

                       ddl.DataSource = dt2

                       ddl.DataBind() 'Lleno el combo

                   End If

                   If flag = True Then

                       'si no esta vacio la hashtable se lo asigno al combo

                       If Not String.IsNullOrEmpty(ht.Item(1)) Then ddl.SelectedValue = ddl.Items.FindByText(ht.Item(1)).Value

                   End If

               End If

End If

       Catch ex As Exception

           Throw ex

       Finally

End Try

   End Sub

Protected Sub GridView2_RowEditing(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewEditEventArgs) Handles GridView2.RowEditing

       Dim idIndex As Integer = e.NewEditIndex

       Try

           GridView2.EditIndex = idIndex

           Dim lblTexto As Label = GridView2.Rows(idIndex).Cells(1).FindControl("CargoText")

           Dim ddl As DropDownList = GridView2.Rows(idIndex).Cells(1).FindControl("DropDownList1")

           If lblTexto IsNot Nothing Then

               'Guardo un Hash con el valor que tiene el Label

               ht = New Hashtable

               'siempre en el value 1 porque lo voy a usar solo para un valor

               ht.Add(1, lblTexto.Text)

           End If

           'uso el flag para saber cuando esta rendereando 

           'el EditTemplate y no el Itemtemplate

           If ddl IsNot Nothing Then flag = True

           GridView2.DataSource = LlenarTabla1()

           GridView2.DataBind()

       Catch ex As Exception

           Throw ex

       Finally

End Try

End Sub

End Class

Uso una HashTable para almacenar el valor que voy a tener que setear en el DropDownList una vez seleccionado, sino siempre mostraría el 1er valor del Combo.

Dejo este 2do ejemplo para descargar aca

Saludos.


Mostrar/Ocultar TRs con Javascript

Noviembre 26, 2007

Hay una manera rápida y sencilla de ocultar o mostrar TR con Javascript, es bastante simple.
En este caso voy a mostrar un simple ejemplo que consta de 2 radiobutton que van a mostrar u ocultar determinados TR y por ende determinados filtros (textbox, combos, listas, etc.).

Primero los Script que se pueden poner en la página:

<script language="javascript">
   1:
   2: function opt1_OnClick()
   3: {
   4: trDatos1.style['display'] = display;
   5: }
   6: function opt2_OnClick()
   7: {
   8: trDatos2.style['display'] = display;
   9: }
  10: function OcultarTodos()
  11: {
  12: trDatos1.style['display'] = 'none';
  13: trDatos2.style['display'] = 'none';
  14: }
  15: function Mostrar()
  16: {
  17: var rdo1=window.document.Form1.opt1.checked;
  18: var rdo2=window.document.Form1.opt2.checked;
  19: OcultarTodos();
  20: if (rdo1==true){opt1_OnClick(); return true;}
  21: if (rdo2==true){opt2_OnClick(); return true;}
  22: }

</script>

La función Mostrar se encarga de mostrar uno u otro TR dependiendo de que RadioButton se ha seleccionado y llamará a la función correspondiente, previamente ocultado Todos los TR.
En el Body de la pagina hay que colocar (en el evento OnLoad) la función Mostrar() de esta manera:

<body onload="Mostrar()">

Luego hay que crear los TR donde van a ir los controles de esta manera:

<TR id="trDatos1" runat="server">
<TD><asp:label id="lblUF">Dato 1</asp:label></TD>
<TD><asp:textbox id="TextBox1" ></asp:textbox></TD>
</TR>
<TR id="trDatos2" runat="server">
<TD><asp:label id="lbldatos2">Datos 2</asp:label></TD>
<TD><asp:textbox id="txt2"></asp:textbox></TD>
<TD><asp:button id="Button1" Text="Boton" runat="server"></asp:button></TD>
<TD><asp:dropdownlist id="cbo2"></asp:dropdownlist></TD>
</TR>

A los 2 TR es importante ponerle un ID para poder llamarlos mas fácilmente, de hecho sino es casi imposible, y que sean runat=Server.
En este ejemplo hice 2 TR con algunas cosas simples pero ahí va lo que se necesite.
Para iniciar la página yo decidí que estén los 2 TR ocultos, de esta manera, poniendo esto en el Page_Load:

trDatos1.Style("display") = "none"
trDatos2.Style("display") = "none"

Ventajas:
Es rápido y con poco código se soluciona, para mostrar u ocultar Textbox es ideal.

Desventaja:
Al esta todo del lado del Cliente, justamente esa es la desventaja viaja todo, si el cliente nunca entra en la opción 2 estaríamos llevándole los datos del a opción 2 de todas maneras.

Este es el primer resultado:

Resultado1

Este el segundo:
Resultado2

 

Saludos.

 

 


Div con Scroll Horizontal/Vertical

Noviembre 12, 2007

Hace poco tuve que agregar unas columnas a una grilla existente en un sistema y me encontré con que se excedía de la pantalla y aparecía una barra de scroll en el explorador para poder ver la grilla, por supuesto que el cliente no quería que aparezca un scroll en el explorador y buscando encontré esta solución para poder ver un scroll tanto vertical como horizontal en un Div, esto esta testeado tanto para IE como para Firefox y es muy sencillo.

<div style=” OVERFLOW: auto; WIDTH: 536px; TOP: 48px; HEIGHT: 232px>
 <!--Inserte Grilla Aqui -->
</div>

Saludos.


Try, Catch y end Try

Octubre 27, 2007

El Bloque Try…Catch…Finally…End Try, es una innovación apartir de .NET (ósea no existia en VB 6.0), a estas alturas ya no es una innovación puesto que el VS 2008 ya esta en las calles, con su framework 3.5 (aqui) pero vamos a comentar algunas cosas básicas y otras no tan básicas(al menos yo no las sabias). Este bloque como todos sabemos sirve para el manejo de las excepciones tanto propias, de nuestra aplicación, como las que podrían ocurrir que vamos a comentar mas adelante. Para comenzar vamos a ver un ejemplo web simple de cómo usar la sentencia try…catch.

Leer el resto de esta entrada »


Llenar y Recorrer un HashTable

Octubre 20, 2007

Una Hastable es una tabla (que utiliza la interface IDictionary) y lo que hace es guardar un par (clave y valor) NO de manera secuencial es decir uno atrás de otro dentro de la tabla sino usando internamente una tabla Hash, esto es importante porque cuando uno está programando no tiene que creer que los datos dentro de la HashTable están “uno al lado del otro” por decirlo en criollo sino que están guardados internamente según el código Hash numérico de la clave. La ventaja es obvia, cuando se tenga que buscar esa clave no se va a recorrer la tabla secuencialmente sino se buscará directamente por su código Hash.

Leer el resto de esta entrada »