Welcome to Comunidad .NET de Cd. Juárez Sign in | Join | Help

Preguntas de los lectores: DataSets y Web Services

Esta pregunta me llegó por e-mail y la respuesta acabó tan larga que mejor la pongo como una entrada:

De antemano te digo que tu blog es muy interesante y se entienden todas las cosas que has puesto... ahora bien tengo una duda que puede sonar un poco tonta pero aqui va...
En cuanto a los xml de los web services en visual studio un dataset que se envia por un web services es convertido a xml para viajar por el HTTP asi que lo puedo dejar de esa manera para que otra aplicacion lo recoja como un xml????
en el caso de que no... al serializar el objeto DataSet obtengo, eso si en la vista del browser un tag String y dentro de ella todo el codigo del xml, evidentemente eso no es lo que se ocupa o si??
Bueno disculpa por las preguntas pero me interesan demasiado las respuestas.... de antemano muchas gracias!!!

—Luis Mario Carvajal

Primero que nada, gracias Luis.  Se siente muy padre que las personas encuentren algo que escribes útil.

Segundo, las preguntas que haces son bien interesantes.  La respuesta a la primera es, sí, un DataSet se serializaría a XML—al tratarse de servicios Web todos los tipos son serializados a XML, porque en escencia estamos hablando de XML sobre HTTP, como tú lo mencionaste.

Sin embargo, no se recomienda utilizar un DataSet para pasar datos, ya que es un objeto bastante complejo: tiene muchas colecciones (DataTables, DataRelations, etc.), y cada una de ellas, a su vez tiene colecciones (un DataTable tiene una colección de DataRows, etc.).  Así que al serializar el grafo de todos eso objetos, acabas con mucho overhead, mucho XML complejo para transmitir solo unos cuantos datos. Y, aunque en teoría sí podrías consumir eso de otra aplicación—dependiendo si estas usando ASP.NET Web Services o WCF, ya que utilizan serializadores distintos—no es muy interoperable con otras plataformas. 

A pesar de estas recomendaciones, debo mencionar que si el consumidor de tu servicio usa .NET, no debe tener problemas para consumir ese DataSet como un objeto de .NET, ya que el generador de la clase proxy que viene con Visual Studio utiliza unos artilugios para des-serializar el DataSet apropiadamente.

Ahora, que si lo que te interesa solo es extraer los datos del DataSet en formato XML, una manera muy sencilla de hacerlo—y mucho mejor que hacer ToString(), creo—es a través del método WriteXml() que es parte de la clase DataSet y DataTable.  Aunque no te da mucho control sobre el XML Schema que utiliza para exportar esos datos, utiliza una estructura bastante sencilla y amigable como para leerlo y manipularlo con otras herramientas.

Finalmente, creo que también es importante mencionar que si simplemente estás exponiendo datos, existen otros formatos más breves (que no usan XML), pero que siguen siendo amigables a los servicios, como JSON.  WCF maneja JSON de una manera relativamente fácil, y puedes consumirlo utilizando ASP.NET AJAX, por ejemplo.  Una última alternativa también es exponer tus datos como un ADO.NET Data Service (que es una característica nueva del .NET Framework 3.5 SP1).

Espero te ayude.

Enjoy smile_shades

Microsoft anuncia Visual Studio 2010 y .NET Framework 4.0

Ayer Microsoft se adelantó al PDC y anunció que Visual Studio 2010 (también conocido por Visual Studio 10 o “Rosario”) y el .NET Framework 4.0 estarían disponibles a finales del 2009 o principios del 2010—seguramente para coincidir con el lanzamiento de Windows 7, tal como lo hicieron con .NET 3.0 y Windows Vista.

Lo curioso, sin embargo es que no dió muchos detalles al respecto.  Según esta página en MSDN, los “pilares” de esa versión son [interpretación mía]:

  • Democratizar el ciclo de desarrollo.  Que en términos prácticos parece que se trata de incorporar aún más modelación en Visual Studio, incluyendo—finalmente—diagramación en UML.  Checa este video en Channel 9 al respecto. Parece que también van a mejorar algunas de las herramientas de pruebas y documentación, sobre todo para poder reproducir pulgas elusivas.
  • Facilitar las tecnologías emergentes.  No sé exactamente a qué se refieran, ¿quizá soporte nativo a Silverlight 2 y cosas así? ¿Facilitar cosas de cloud computing? ¿Desarrollo para mulitprocesadores/multicore?
  • Inspirar deleite en los desarrolladores.  Esto me suena a puro marketingspeak :)
  • Seguir la ola de plataformas de próxima generación.  Esto pudiera referirse a tecnologías asociadas con Windows 7 o Server 2008 R2, o a cosas relacionadas con Live Mesh—parte de la iniciativa de cloud computing de Microsoft—que estoy seguro también tendrán algo de integración.
  • Aplicaciones departamentales avanzadas.  Supongo que se enfocarán a facilitar el desarrollo no solo de “aplicacionzotas” sino también “aplicacioncitas”—que luego crecen como monstruos y luego las quieren usar en todos lados.  ¿Significa que integrarán algunos pricipios de Access? [eek]

Hay una serie de videos ya en Channel 9 acerca de VS 2010.  El blog de Arturo también tiene algo más de información en español al respecto.

Enjoy cool
Posted from Diario de un Dotnetero | 0 Comments
Filed under:

Videos en español de Visual Studio 2008 y más por Channel 9

Para los que no lo conocen, Channel 9 es un sitio de Microsoft para desarrolladores donde puedes encontrar un montonal de videos—y más importante creo—opinar sobre muchas de las tecnologías que maneja la compañía. 

La mayoría de los videos están en inglés, pero hoy descubrí que si juegas con los tags puedes obtener un listado de los videos que está en español.  Este enlace te da dicho listado:

http://channel9.msdn.com/tags/Spanish/

Ahí encontrarás videos sobre Visual Studio 2008, Expression Web, incluso uno que otro sobre Silverlight y Expression Blend.

Por ejemplo, parece que acaban de sacar una serie de cinco partes sobre Expression Web—uno de los productos de la familia Expression diseñados para hacer desde sitios HTML hasta sitios con páginas ASP.NET.

Enjoy smile_shades

Cómo transformar XML sin usar XSLT

El otro día, una compañía externa hizo un una auditoría de seguridad a un sistema grande que manejamos.  Parte de la auditoría consistió en correr la herramienta FxCop contra las DLLs para buscar—entre otras cosas—posibles vulnerabilidades de inyección de SQL.  FxCop produce dichos reportes en XML y eso fue lo que nos entregaron. 

Estos reportes eran enormes y en un formato no muy amigable, así que necesitábamos de alguna forma extraer los datos de ahí para enfocar los esfuerzos de los desarrolladores (qué corregir y en dónde), y también para tabular los datos (número de issues por namespace, DLL, etc.) de manera que se les pudieran presentar a los gerentoides. 

Este es un ejemplo de uno de esos archivos—no te preocupes, todas estas vulnerabilidades ya fueron parchadas, este es un extracto de esos reportes smile_wink.

(Da clic a la imagen para ver un tamaño más grande)

ejemplo de reporte FxCop

Ahora, se me ocurrió que estos archivos se podían transformar a algo menos plano—como otro archivo de XML o un CSV—de manera que pudiera ser importado a Excel fácilmente.  Algo así como lo siguiente:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Vulnerabilities>
  <Vulnerability>
    <Module></Module>
    <Namespace></Namespace>
    <Type></Type>
    <Method></Method>
    <Issue></Issue>
  </Vulnerability>
  <Vulnerability>
    <Module></Module>
    <Namespace></Namespace>
    <Type></Type>
    <Method></Method>
    <Issue></Issue>
  </Vulnerability>
</Vulnerabilities>

La sola idea de hacer una hoja de estilos XSL para transformar eso me daba escalofríos, así que fue una buena oportunidad para practicar mi LINQ-Fu.  Para ello me ayudé de LINQPad—una excelente herramienta para probar snippets de LINQ.

Armando el query

Mi primer query fue este:

XElement xml = XElement.Load(@"C:\Users\Carlos\Desktop\sampleFxCopReport.xml");
 
var query =
    from e in xml.Descendants("Issue")
    where e.Ancestors("Message").Attributes("TypeName").First().Value == "ReviewSqlQueriesForSecurityVulnerabilities"
    select new
    {
        Module = e.Ancestors("Module").Attributes("Name").First().Value,
        Namespace = e.Ancestors("Namespace").Attributes("Name").First().Value,
        Type = e.Ancestors("Type").Attributes("Name").First().Value,
        Method = e.Ancestors("Member").Attributes("Name").First().Value,
        Issue = e.Value
    };

Como puedes ver, cargar el archivo es trivial.  Puedes hacerlo a través del método Load() de la clase XElement o XDocument.

Luego, declaré una variable de tipo var porque no estaba seguro exactamente del tipo de los objetos que regresaría mi query—utilicé un tipo anónimo, el cual explicaré en un minuto.

Si no estás muy familiarizado con queries de LINQ, solo recuerda que en su nivel más básico, tienes un from/where/select

  • Primero le dices a qué objetos quieres hacerle query (from),
  • luego especificas un filtro que deje solo los que te interesen (where) y
  • finalmente le indicas una expresión de cómo quieres proyectar tus datos en la salida (select).

En este caso, se me hizo más fácil elegir primero todos los elementos <Issue> dentro del documento XML, ya que a partir de ellos puedo obtener el resto de la información viendo los nodos ancestros.  Logré hacer esto con una sola línea en el from gracias al método Descendants() de la clase XElement.  En otras palabras estoy diciendo “selecciona los elementos <Issue> en el documento, y por cada uno de ellos dame una variable e de donde extraer más información”.  Puedes pensarlo como algo parecido a un foreach.

Luego, indiqué en el filtro where que únicamente deseo los <Issue> donde el mensaje (<Message>) sea de tipo vulnerabilidad de SQL (TypeName=”ReviewSqlQueriesForSecurityVulnerabilities”).  Como los elementos <Message> son ancestros de <Issue>, utilicé Ancestors() para acceder a ese elemento y luego Attributes() para obtener el valor de atributo TypeName y poder hacer la comparación.

Finalmente, en la proyección el select new crea un tipo (una clase pues) sin nombre con 5 propiedades, que son inicializadas con los valores de las expresiones.  Esto crea una collección de tipo IEnumerable<T> donde T es el tipo anónimo—¿ves por qué fue necesaria la variable var?

El resultado del query es este (da clic para ver la imagen más grande):

resultados del primer query

Pero, ¿qué tal si quisiera ordenar mis resultados primero por Module, luego por Namespace, Type y Method sucesivamente?  Sencillo.  Puedo agregar una cadena de OrderBy’s a mi query original o puedo agarrar el resultado del query y ordenarlo así:

var ordered =
    query.OrderBy(x => x.Method).OrderBy(x => x.Type)
    .OrderBy(x => x.Namespace).OrderBy(x => x.Module);

Esta manera de hacerlo involucra las famosas expresiones lamda, pero no me quiero desviar en explicarlas.  Por ahora sólo tómalas como ejemplo y nota que puedes encadenar las cláusulas.

Esto es un buen comienzo, pero ahora quiero esos datos en algo que se le parezca a un documento XML.

Entonces agregué esto después de mi query:

XDocument xdoc = new XDocument();
xdoc.AddFirst(new XElement("Vulnerabilities"));
 
foreach (var element in query)
{
    xdoc.Root.Add(
        new XElement("Vulnerability", new XElement("Module", element.Module)
                                    , new XElement("Namespace", element.Namespace)
                                    , new XElement("Type", element.Type)
                                    , new XElement("Method", element.Method)
                                    , new XElement("Issue", element.Issue)
                                    ));
}

Primero creo un nuevo documento XML utilizando la clase XDocument, y le agrego un elemento raíz <Vulnerabilities>.  Luego por cada elemento de mi lista ordenada, agrego un elemento <Vulnerability> que contendrá cinco elementos, uno por cada propiedad que me interesó, y que tendrán el valo.  Nota que los constructores “raros” de XElement facilitan enormemente la tarea, y que los métodos AddFirst() y AddNew() se encargará de cerrar los elementos adecuadamente—a diferencia de la forma en que se utiliza un XmlWriter, por ejemplo.

El resultado:

resultados del query

Esto ya es prácticamente lo que quiero.  Sin embargo, mi código hasta ahorita son como 30 líneas—principalmente por el formato, en realidad solo he utilizado como 7 instrucciones—y me gustaría condensar el código más.  Además descubrí que el ordenamiento en realidad no lo necesito—puedo hacerlo en Excel—y que al documento XML le falta la declaración <?xml> al pricipio.

Sintetizando el código

Así que decidí cambiar la proyección (el select pues) de mi query original.  El total del código quedó así:

XElement xml = XElement.Load(@"C:\Users\Carlos\Desktop\sampleFxCopReport.xml");
 
IEnumerable<XElement> query =
    from e in xml.Descendants("Issue")
    where e.Ancestors("Message").Attributes("TypeName").First().Value == "ReviewSqlQueriesForSecurityVulnerabilities"
    select new XElement("Vulnerability",
        new XElement("Module", e.Ancestors("Module").Attributes("Name").First().Value),
        new XElement("Namespace", e.Ancestors("Namespace").Attributes("Name").First().Value),
        new XElement("Type", e.Ancestors("Type").Attributes("Name").First().Value),
        new XElement("Method", e.Ancestors("Member").Attributes("Name").First().Value),
        new XElement("Issue", e.Value)
        );
 
XDocument xDoc = new XDocument(
    new XDeclaration("1.0", "UTF-8", "yes"),
    new XElement("Vulnerabilities", query)
    );

Nota que con solo 2 instrucciones—la instrucción de carga no cuenta—logré hacer la transformación (¡!) smile_omg.   Veamos los cambios significativos al query.

Primero, el resultado es almacenado en una variable que ya no es tipo var, sino IEnumerable<T> donde T es XElement.  Esto es porque en la proyección (el select) ya no estoy utilizando un tipo anónimo para construir un objeto, sino los constructores de la clase XElement para obtener objetos de este tipo.

Finalmente, a la hora de crear el nuevo documento XML, utilizo también un constructor alterno de XDocument, para primero pasarle la declaración XML, y agregarle un elemento <Vulnerabilities> que tendrá como contenido el resultado de mi query—la lista de nodos <Vulnerability> con sus respectivos elementos hijo.  ¿Así o más mágico? smile_teeth

[Pronunciarse en tono de vendedor de chuchulucos por T.V.:] ¡Pero aún hay más!

¿Quieres saber lo que se necesita para guardar el nuevo documento de XML a un archivo?

xDoc.Save(@"C:\Users\Carlos\Desktop\transformedReport.xml");

Así que con un total de 4 instrucciones logré cargar un archivo complejo de XML, transformarlo y escribir los resultados a otro más amigable.

[Pronunciarse en tono de vendedor de chuchulucos por T.V.:] ¡Pero aún hay más!

Sintetizándo el código aún más

¿En verdad quieres ponerte quisiquilloso con el query?  Puedes lograr la totalidad de la lógica con solo 3 instrucciones—una para cargar el archivo original, otra para transformarlo y una más para guardar el archivo resultante—si utilizas expresiones lambda.  Este ejemplo no lo explico porque igual y te acabo confundiendo más, pero creo que ilustra el poderío de LINQ y las nuevas clases para manipular XML.

XElement xml = XElement.Load(@"C:\Users\Carlos\Desktop\sampleFxCopReport.xml");
 
XDocument xDoc = new XDocument(
  new XDeclaration("1.0", "UTF-8", "yes"),
    new XElement("Vulnerabilities",
      xml.Descendants("Issue")
      .Where(i => i.Ancestors("Message").Attributes("TypeName").First().Value == "ReviewSqlQueriesForSecurityVulnerabilities")
      .Select(e => new XElement("Vulnerability",
              new XElement("Module", e.Ancestors("Module").Attributes("Name").First().Value),
              new XElement("Namespace", e.Ancestors("Namespace").Attributes("Name").First().Value),
              new XElement("Type", e.Ancestors("Type").Attributes("Name").First().Value),
              new XElement("Method", e.Ancestors("Member").Attributes("Name").First().Value),
              new XElement("Issue", e.Value)
              )
          )
      )
  );
 
xDoc.Save(@"c:\users\Carlos\Desktop\transformedReport.xml");

¿Qué tal, eh? smile_nerd

Conclusión

Este artículo mostró un ejemplo de cómo transformar un documento XML utilizando LINQ to XML.  También mostró de manera práctica qué son los tipos anónimos (“clases sin nombres”), cómo cargar y escribir archivos XML con las clases XElement y XDocument incluidas en el .NET Framework 3.5, e ilustró brevemente el uso de expresiones lambda.  La mayoría de los conceptos—excepto quizá las expresiones lambda—aplican también si estás utilizando Visual Basic como tu lenguaje de desarrollo para .NET.

Enjoy. smile_shades

Google Chrome beta tampoco me impresiona

Todo mundo y su abuelita para ahora se ha de haber enterado que Google lanzó su propio browserWired tiene un artículo interesante de por qué se tardaron tanto para lanzarlo, cuando para muchas personas era una evolución lógica.

Bajo riesgo repetir artículos anteriores, tengo que admitir que cuando comencé a ver la lista de características “inovadoras” me sorprendió lo no inovadoras que en realidad son:

  • Omnibox. Básicamente una versión del Awesomebar (Firefox 3) o del Smart Address Bar de IE8 beta2, pero con búsqueda integrada. Moderadamente interesante. Se parece también al search box que trae Flock—y el cual espero fusionen con el Awesomebar para Flock 2 final.
  • Pestañas independientes. Rara vez se me ha ofrecido que una pestaña haga que truene el navegador. De las pocas veces que me ha sucedido es cuando corro IETab dentro de Firefox, e incluso en esas instancias FF hace buen trabajo en recuperar mi sesión. Pero, la idea es interesante. Tanto que al parecer se le ocurrió lo mismo al equipo de Internet Explorer 8.
  • Acceso directo a aplicaciones. Un concepto que se me hizo bastante útil, desde que el equipo de Mozilla comenzó con el proyecto Prism hace casi un año (¿?)—y del cual, naturalmente hay una extensión para Firefox.
  • Pestañas dinámicas. Yo suelo mantener una sola ventana de navegador abierta—si no ¿pa’ qué quiero las pestañas, verdad?—pero si les gusta esta característica, también pueden encontrarla en Safari.
  • Modo incógnito. O como dijo un amigo mío, modo “p0rn” jejeje—y no que yo lo use, ¿verdad? Hmm… ¿dónde he visto eso? ¡Ah! Qué tal en Safari (conocido como Private Browsing) y en IE 8 beta 2 (conocido como InPrivate).
  • Marcadores instantáneos. Ver Flock, y FF 3. No digo más.

De lo único que en verdad puedo ver inovador es el motor de JavaScript que le pusieron, V8, que al parecer patea traseros en desempeño. Y aunque algunos autores han argumentado que JavaScript es “solo una parte mínima del Web”, yo les digo: ¿Alguna vez has intentado correr Gmail, Slashdot o Facebook en IE7 o previos contra cualquier otro navegador moderno? JavaScript sí importa, y mucho.

Tratando de no tirar mucho rollo—demasiado tarde, lo sé—sí hubo cosas que me gustaron:

  • Desempeño. Jala hecho la mater cuando no está detrás de un proxy—lean un poco más abajo.
  • Google Gears integrado. No tienes que instalar esto por separado para utilizar, por ejemplo, Google Reader en modo offline. No sorprendente, dado que otro producto de Google, pero es útil que lo traiga integrado.
  • Interfaz minimalista. De las primeras cosas que le hago a Firefox es quitarle todos los botones y cosas extra y si vieran mi pantalla verían que mi arreglo quedó prácticamente idéntico al que usaron en Chrome. Safari también viene de cajón así.
  • Herramientas de desarrollo Web incluidas. Al igual que Safari, puedes seleccionar un elemento y dar “Inspect Element” para obtener información de CSS, etc.
  • Búsqueda en la página amigable. Casi igual que la de Safari—¿comienzan a ver un patrón?

image

Si quisiera resumir “lo bueno” diría que en muchos sentidos, Chrome es como Safari, pero sin el rendereo borroso de fonts en Windows y con Gears integrado.

Lo que de plano no me gusto, y de hecho impide que lo use de tiempo completo:

  • No le gustan los proxies, sobretodo los que te piden username y password. Ni siquiera puedes instalarlo si estás detrás de un proxy de este tipo. Y el desempeño se va por el caño, con muchas páginas que no se llegan a cargarse completas—no pude correr Gmail, lo cual es el colmo. Esto quizá es de esperarse de un beta—Safari tuvo problemas similares que resolvieron en la versión final—pero por ahora es un dealbreaker para mi.
  • Fallas de compatibilidad con sitios sociales. Algunas cosas en Facebook y MySpace no funcionan aún con Chrome. Unas simplemente hacen una experiencia menos agradable y otras de plano hacen que no puedas utilizar funcionalidad de estos sitios. MySpace puede irse a chiflar alpistle—es el sitio del demonio en lo que a mi concierne—pero Facebook está bastante bien armado hasta donde sé. Pero si el navegador no jala bien en estos sitios, ¿cuántos chavalos de 12 a 17 años que se la pasan viviendo ahí lo usarían?
  • No trae soporte para RSS. Solo muestra el XML del feed. ¿Cómo se supone que voy a leer mis noticias?

¿Matará Chrome a IE? Lo dudo. Habrá que ver lo que sucede. En mi opinión esto tomaría tiempo, aunque es interesante que algunos ya le achacan el 3% del mercado después de su lanzamiento. Google es una compañía a la par con los recursos y reputación de Microsoft, lo cual introduce una dinámica interesante, sobretodo para los que desarrollamos aplicaciones Web. Antes probablemente te preocupabas por que tus sitios jalaran en IE o Firefox, si mucho—al pobre de Opera nunca lo han pelado y mucho menos a Konqueror et.al. Ahora que tienes Safari y Chrome en el mercado, creo que finalmente comenzaremos una era donde los estándares en el desarrollo del Web cobren la importancia que debieron tener desde el principio. *Cruzando los dedos para que suceda*

Enjoy.

Visual Studio 2008 Service Pack 1 ya está disponible

Al menos para suscriptores de MSDN.

Official MSDN Subscriptions Blog : Visual Studio 2008 Service Pack 1 files are also now available

Oh, y también ya soltaron la versión RTM de SQL Server 2008.

Enjoy

Posted from Diario de un Dotnetero | 0 Comments
Filed under:

Reseña del Lanzamiento de Visual Studio 2008

Alex Briseño puso una muy buena reseña del evento que tuvimos el pasado martes 27 de mayo, repleto de fotografías, pa’ que vayan a leerla. 

La verdad yo me divertí un chorro, a pesar de que quedé exhausto porque me tocó dar 3 pláticas—lo cual implica hablar casi tres horas—me dió mucho gusto ver tanta gente.  También se sintió bien padre que que ahora sí tuvimos bastantes cosas que regalar como todos esos paquetes de desarrollador con Visual Studio 2008, SQL Server 2008 y Windows Server 2008, así como los discos de Windows Vista y las suscripciones de TechNet.

Pero lo más chido creo que fue definitivamente el final, cuando nos pusimos a jugar—o a hacer el intento de jugar—boliche y a echarnos unas chelas con toda la raza hardcore que se quedó hasta esa hora. 

El momento priceless se lo llevó Sergio, después de ganarle a Alex: “No pos si es la primera vez que juego”... ajá... sí cómo no... jejeje

Posted from Diario de un Dotnetero | 0 Comments
Filed under: ,

Cómo acceder a controles dentro de un GridView

Esta entrada salió como resultado de una pregunta que hicieron en el Foro de la Comunidad .NET.  La pregunta, esencialmente, es: ¿Cómo accedo a un control que tengo en una columna templeteada dentro de un GridView de ASP.NET?

Me pareció buena la pregunta, así que hice un pequeño ejemplo para ilustrarlo.   Una columna templeteada (TemplateField) es distinta a una normal (BoundField) en que tienes más control sobre los controles que aparecen en la columna.  En otras palabras, tú especificas qué quieres que se muestre cuando el renglón está en modo "normal" (ItemTemplate) o cuando está en modo "edición" (EditItemTemplate).  Puedes tener múltiples controles dentro de la columna, en lugar de solo uno que represente el dato.

La siguiente página contiene un GridView con tres columnas que vienen de un SqlDataSource.  Los datos provienen de la clásica base de datos Northwind.   En este caso estoy recuperando datos de la tabla de productos:

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb"
  Inherits="_Default" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
  <title>Accediendo a Elementos en un GridView</title>
  <style type="text/css">
    #miGrid
    {
      width: 450px;
      float: left;
    }
  </style>
</head>
<body>
  <form id="form1" runat="server">
  <asp:Button runat="server" ID="leerElementosButton" Text="Leer elementos" />
  <div id="miGrid">
    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
      DataKeyNames="ProductID" DataSourceID="SqlDataSource1" 
      EmptyDataText="No hay registros que mostrar.">
      <Columns>
        <asp:BoundField DataField="ProductID" HeaderText="ID Producto" 
          InsertVisible="False" ReadOnly="True" />
        <asp:BoundField DataField="ProductName" HeaderText="Nombre Producto" />
        <asp:TemplateField HeaderText="Descontinuado">
          <EditItemTemplate>
            <asp:CheckBox ID="CheckBox1" runat="server" 
              Checked='<%# Bind("Discontinued") %>' />
          </EditItemTemplate>
          <ItemTemplate>
            <asp:CheckBox ID="CheckBox1" runat="server" 
              Checked='<%# Bind("Discontinued") %>' Enabled="false" />
          </ItemTemplate>
        </asp:TemplateField>
      </Columns>
    </asp:GridView>
    <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
      ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
      ProviderName="<%$ ConnectionStrings:NorthwindConnectionString.ProviderName %>"
      SelectCommand="SELECT [ProductID], [ProductName], [Discontinued] FROM [Products]">
    </asp:SqlDataSource>
  </div>
  <div id="resultados">
    <asp:Label runat="server" ID="resultadosLabel" />
  </div>
  </form>
</body>
</html>

Para acceder, por ejemplo, al CheckBox que está dentro de la columna templeteada, primero necesitas una referencia al renglón, ya que el ID del control se repetirá n veces (una por cada renglón del Grid). 

Esto se puede hacer de varias formas, por ejemplo, si tienes un manejador para un evento clic en alguno de los controles dentro del renglón pues en ese caso el sender viene siendo el renglón en sí, entonces únicamente te falta encontrar el CheckBox de ese renglón para leer sus propiedades.   Otra forma de hacerlo, como en el siguiente ejemplo, es leer todos los renglones y por cada uno encontrar el CheckBox que le corresponde al renglón:

Partial Class _Default
  Inherits System.Web.UI.Page
 
  Protected Sub leerElementosButton_Click(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles leerElementosButton.Click
 
    Dim grid As GridView = Me.GridView1
    Dim checkBox As CheckBox
    Dim resultado As New StringBuilder
 
    For Each renglon As GridViewRow In grid.Rows
      checkBox = CType(renglon.FindControl("CheckBox1"), CheckBox)
      If checkBox.Checked Then  'Hacer algo con esta información
        resultado.Append(String.Format( _
          "El renglón {0} está descontinuado <br />", renglon.DataItemIndex))
      End If
    Next
 
    resultadosLabel.Text = resultado.ToString()
 
  End Sub
End Class

En resúmen, la idea clave aquí es que el GridView tiene una colección de renglones (de tipo GridViewRow) y cada uno de estos renglones tiene su correspondiente colección de controles que están dentro de ese renglón.  El GridViewRow también te da acceso al DataItem que contiene los datos asociados al renglón, en caso de que lo requirieras.

El resultado de correr el código anterior (dando clic al botón) es el siguiente:

Espero les ayude.

Enjoy smile_shades

Posted from Diario de un Dotnetero | 0 Comments
Filed under: ,

Creo que he estado trabajando mucho...

Me salió esto hoy.  Creo que Visual Studio está tratando de decirme algo...

Atajos de teclado para Visual Studio

Una de las maneras más fáciles de incrementar tu productividad cuando utilizas casi cualquier programa es aprenderte los atajos de teclado—los mentaos keyboard shortcuts, pues.  De hecho tengo amigos que odian levantar las manos del teclado cuando están programando.  Si alguna vez has usado algún editor de texto como vi, quizá hayas apreciado que una vez que dominas la complejidad de los comandos, en realidad se siente como si estuvieras "platicando" con el editor. Y aunque yo no llegaría al extremo de recomendar que manejes Visual Studio con los comandos de vi, sí recomiendo enormemente que te aprendas algunos de los más comúnes que ya vienen de cajón con el IDE.

El problema es que Visual Studio tiene 8 millones 557,934 comandos.  Bueno, quizá algunos menos, pero aún así son un titipuchal.  Y lo que es peor, los atajos de teclado cambian de acuerdo a la configuración general de Visual Studio.  Esta es la configuración que te pregunta la primer vez que arrancas el IDE o si das Tools>Import and Export Settings...>Reset all settings.

Ventana de diálogo de configuración general de Visual Studio

Aquí es donde ayudan algunos documentos de referencia rápida.  Si primordialmente desarrollas en Visual Basic, y utilizas esa configuración (Visual Basic Development Settings), aquí hay un PDF de Microsoft que los resume. 

Si usas la configuración de Visual C# Development Settings, para desarrollar primordialmente en C#, están este para Visual Studio 2005 y este otro para Visual Studio 2008.

Sin embargo, yo utilizo la configuración para desarrollo general (General Development Settings) porque desarrollo tanto aplicaciones Web como Windows, a veces en C# y a veces en Visual Basic, aparte que ya me había aprendido algunos atajos desde versiones anteriores de Visual Studio.  Como no encontré ninguna referencia rápida para esta configuración, creé mi propio documento.  Puedes descargarlo del sitio de la Comunidad.

Mi recomendación personal es, no intentes aprenderlos todos de un zopetón.  Dice un proverbio: "¿Cómo te comes un elefante? Un bocado a la vez".  Así que mejor escoge un grupo de comandos y practica cada uno por separado, repitiéndolo al menos 20 veces.  Lo que yo hice fue agarrar una archivo con código y practicar un comando a la vez en diferentes partes del archivo mientras lo "vocalizaba mentalmente" hasta que quedaba grabado en mi memoria muscular.  Luego practicaba el siguiente comando hasta terminar el grupo.  Al día siguiente me enfocaba en un grupo distinto, y así sucesivamente.

Cómo crear tus propios atajos

Por supuesto, también puedes definir tus propios atajos.  Estos atajos pueden ejecutar un comando del IDE o alguna macro que hayas creado para alguna tarea específica.  Por ejemplo, hay dos atajos que a mi me ha sido útil definir: uno para comparar el archivo actual contra la versión en el controlador de código y otro para obtener el historial del archivo actual en el controlador de código.

Para definirlos, primero ve a Tools>Options... y luego Environment>Keyboard.  Al hacerlo verás la siguiente ventana:

En la parte donde dice Show commands containing, teclea parte del comando, p. ej. "compare".  Esto traerá una lista de posibles comandos.  En este caso, el que busco es File.Compare.  Luego, selecciona el comando adecuado de la lista y pon el cursor en la parte donde dice Press shortcut keys. Presiona la combinación que desees utilizar.  Si la combinación ya está siendo utilizada por algún otro comando, esta información será mostrada en la parte de abajo donde dice Shortcut currently used by.  En mi caso escogí la combinación Ctrl+Alt+F,C para finalmente darle clic en el botón Assign

Repite los mismos pasos para el comando File.ViewHistory y utiliza el atajo Ctrl+Alt+F,H—o cualquier otra combinación que más te guste.

En fin, creo que esto da la idea.  Enjoy smile_shades

La Generación M: Al borde del un nuevo cambio

Hoy me tocó dar una plática bastante diferente a la que estoy acostumbrado.  Resulta que los chavos de la carrera de Tecnologías Computacionales del Tec de Monterrey Campus Juárez (mi "alma mater") hicieron un evento llamado El Congreso con la finalidad de atraer a más chavos (y chavas, claro, si no qué chiste) de las prepas y secundarias locales hacia las carreras de "sistemas".

Aparentemente algunos de ellos habían leído mi blog y me enviaron un correo para invitarme a participar como expositor, lo cual se me hizo un honor.  Se siente medio raro regresar a la escuela de donde te graduaste para "enseñar algo".  Pero cuando me dijeron que la audiencia serían principalmente lepes de preparatoria comencé a ponerme un poco nervioso.  Después de todo, han pasado casi 10 años—a ver díaganlo: "uuuuuuuuuuuuu!"—desde que dejé de dar clases, y no me paraba a hablar enfrente de un grupo de esa edad.  Mi mente inmediatamente comenzó a dar vueltas: "Demonios, ¿de qué les puedo hablar? ¿De qué manera puedo encontrar un tema donde tengamos algo en común, y que hable de tecnología?" 

Pensándola un poco más caí en cuenta que muchos de estos chicos, son modelo 90 o más reciente—osea que nacieron después de 1990—lo cual me hizo sentir más ruco todavía porque yo soy setentayquíhúbole.  Mientras más lo pensaba más me era evidente que hay un a brecha entre esta generación y la mía.  Comencé a recordar cómo era el mundo cuando yo tenía la edad de ellos—hace 15 años más o menos—y cómo había cambiado el mundo desde entonces hasta ahora, hasta que me cayó el veinte: "¿y por qué no hablar precisamente sobre eso?".

Así que eché un poco de alucine este fue el resultado.

Generación i

La i es de internet.  Esta es la generación a la que creo que pertenezco.  En ella incluyo a las personas que eran adolescentes durante los pricipios de la década de 1990 y que nos tocó, por un lado, ver el nacimiento del internet—sí ya sé que el interné existía desde los 70s y 80s pero no fue sino hasta los 90s que el Web lo trajo a las masas ¿verdad?—y por otro lado presenciar cambios históricos a nivel mundial como la caída del comunismo.

 

Aún recuerdo ver en la televisión cómo derribaban el muro de Berlín.  Recuerdo ver también en la T.V. los tanques en Rusia mientras intentaron el golpe de estado contra Gorbachev y sentirme triste porque leí su libro sobre la perestroika y el glasnost.  Recuerdo la caída, país por país, de la cortina de hierro en Europa y también la primera Guerra del Golfo Pérsico donde una coalición de países decidió luchar contra Saddam Hussein.

Para cuando tuve edad de entrar en a la carrera en 1994, el mundo entero parecía enamorado de nuevo con el capitalismo y la apertura de mercados.  México llevaba poco que había firmado el TLC y en el Tec hasta inventaron carreras nuevas como la de Lic. en Comercio Internacional.  También por aquellos tiempos el internet comenzaba a salir de las escuelas y a entrar a los hogares.  El Tec, que hasta entonces había sido el único ISP de Cd. Juárez, le dejó eso a compañías como Infolink (si mal no recuerdo)—¿se acuerdan cuando tenían que pagarle a alguien y marcarles por teléfono con su módem para estar "en línea"? ¿No? Chin.

El caso es que se respiraba un ambiente de apertura.  En el lado tecnológico esa actitud comenzó a reflejarse en movimientos como el de Open Source.  Las personas comenzaron a colaborar a pesar de las grandes distancias gracias a la red que ahora cobraba vida.  Estábamos en plena "globalización 1.0", como lo describe Thomas Friedman y el mundo se estaba aplanando.  El internet había fomentado la globalización y la globalización ayudó al crecimiento de la red.  Por supuesto que ese momento no me dí cuenta de lo que ocurría porque estaba inmerso en él.  Para cuando me gradué de la carrera en 1998, "eso del e-mail" y de trabajar a distancia se había vuelto bastante común. 

Generación M

La M es de móbil, es decir un pochismo deformado mío de mobile phones, también conocidos como teléfonos celulares.  Esta es la generación que en estos momentos está en la adolescencia.

Cuando comencé mi plática, abrí con una pregunta: "¿Cómo sería tu vida... sin tu celular?"  Hubieran visto la reacción.  Fue una exclamación colectiva de auténtico horror: "¡Ay NOOoooo!", jejeje. "¿...sin Google? ¿...sin el Internet? ¿Qué música escucharías? ¿Qué sería diferente?"  Y ya cuando habían parado la oreja puse una diapositiva que decía: "Así era el mundo hace apenas 15 años".

A veces creo que no se le ha dado crédito a la impacto que han tenido los celulares—y sí, yo también considero que son odiosos y ojalá no los hubieran inventado, pero pues ni modo ya ganaron.  "En mis tiempos..."—como dicen los viejitos—los únicos que traían celulares eran los narcos y la gente de muuuucha lana.  Eran esos horrendos ladrillos Motorola que les duraba la pila una hora y podían se utilizados como arma de defensa personal.

 

Hoy en día parece que los chavitos nacen con el celular en la mano.  He visto niños de 7 y 8 años—entre ellos algunos de mis sobrinos—con celular propio, lo cual me parece absurdo, pero es la realidad.  Todo tipo de vagancias y mal comportamiento es videograbado con su teléfono para subirlo a YouTube.  Para ellos se ha convertido en una extensión de su persona.  Algunos de ellos incluso se identifican con su celular, lo cual es en verdad preocupante. 

Esto está ocasionando cambios interesantes.  Por ejemplo, todos esos mensajitos de texto—y la flojera que causa tener que teclearlos, supongo—están ocasionando cambios informales y deformaciones al español escrito.  Una conversación típica podría ser:

—Ke rollo?
—No ps nada
—Vas a ir al cine vdd?

Este tipo de deformaciones también están creciendo por el uso de mensajería instantánea (Messenger, Google Chat, Skype, etc.).  Cuando intento platicar con una de mis sobrinas por Messenger, a veces me dan ganas de darle un sape virtual y decirle: "¡escriba bien, no sea payasa!", pero me las aguanto.  Estos programas, también los están acostumbrando a que ahora se puede tener conversaciones de video o voz internacionales gratis o a muy bajo costo.  En otras palabras, la dimensión de la distancia comienza a cambiar.  El mundo no solo es plano sino que comienza a encogerse.

Una característica más que se me ocurre sobre la generación M es que, los chicos de ahora están (¿mal?)acostumbrados a tener las cosas on-demand, es decir, cuando ellos quieren y como ellos quieren.  Si quieren música, se van a iTunes, o BitTorrent o <inserte aquí la herramienta de piratería de moda>, la bajan y listo; ya no están limitados por la música de la radio o los discos en la tienda del mall.  Si quieren un libro es cuestión de pedirlo por Amazon o similares y obtenerlo.  ¿Aburrido? Solo "prende" YouTube y puedes perder horas enteras viendo todo tipo de tarugadas; ya no están limitados a lo que ofrece la tele.  La palabra clave, supongo, es opción.  Ahora tienen más opciones que nunca.  Lo cual quizá es bueno y malo a la vez.

Por otro lado también se pueden observar una serie de cambios y situaciones sociales interesantes.  Una de ellas me la apuntó Alex Briseño: los hijos de los dueños de muchas empresas están comenzando a tomar las riendas.  Es decir, un empresario que hoy tiene 50-60 años y que puso su negocio propio ahora está dándole el control a su hijos para que se hagan cargo.  Estos "hijos de dueños" son de la generación i, y no se sienten intimidados por la tecnología, lo que es más, lo ven como algo favorable, algo que trae un valor agregado.  Si alguna vez se han dedicado al negocio de vender "sistemas" se habrán quizá dado cuenta que con excepción de empresarios con mucha visión, la mayoría de la generaciones anteriores percibían esto como un costo, no como algo que les pudiera ayudar a ganar dinero.  Los "hijos de dueño", sin embargo, no solo no tienen problema con esto, sino que te buscan para que les hagas un sistema.  Eso a su vez comienza a cambiar la dinámica de la competencia en muchos ámbitos.

Combinado con la maduración de la globalización 2.0, el inicio de la 3.0 esto está permitiendo que los David comiencen a competir con los Goliat.  La Cola Larga está comenzando a esparcirse.  Dos ejemplos locales son que en Cd. Juárez, en los últimos 6 u 8 meses, Cablemás comenzó a competir con Telmex en telefonía; Volaris e InterJet, dos aerolíneas de bajo costo comenzaron a competir con Aeroméxico.

Pero con todas las maravillas de la tecnología hay otra cosa que está ocurriendo: está creciendo la brecha digital, el digital divide.  Es decir después de darte cuenta que el internet es maravilloso y que el acceso a la información es una necesidad porque uno como individuo está compitiendo con personas de todo el mundo, la siguiente pregunta inevitablemente es "¿y qué hay de los millones de mexicanos que aún viven en extrema pobreza? ¿Cómo sobreviviran en este nuevo mundo?"

Desgraciadamente no hay respuestas alentadoras.  La única manera de competir es a través de la educación y de ofrecer algo más.  En otras palabras, no competir en la maquilada de las cosas o de la información—siempre habrá mano de obra más barata en un país más desesperado—sino competir ofreciendo las cosas que requieren de más coco, de más intelecto. Seguro, un ingeniero hindú o chino de sistemas promedio sale más barato que yo, pero ninguno, de todos los que conozco y con los que he trabajado tiene la misma capacidad que yo.  Y no es por ser arrogante, simplemente les ha faltado cayo y colmillo.  No significa que no haya ingenieros competentes en otros países, significa que esos ingenieros no son de bajo costo.  Incluso eso está cambiando claro, al punto que en 10 años quizá estemos hablando de otros países.

Esta es una realidad difícil de aceptar.  Aunque hay que mencionar que sí hay algunas personas haciendo algo concreto al respecto.  Proyectos como el de Una Laptop Por Niño (OLPC) están tratando de atacar este tipo de problemas, pero la tecnología en sí es una solución insuficiente.

Generación W

La W es de wireless.  Esta generación serían los hijos de la generación M, nacidos quizá unos 15 o 20 años más en el futuro.

Si todo progresa como hasta ahora, más temprano que tarde la idea de las redes inalámbricas a nivel ciudad o región se harán realidad a través de cosas como WiMAX o mesh networks.  En otras palabras para entonces ya no estarás atado a tu casa o tu restaurante favorito para estar conectado.  Esto no solo dará a pie a dispositivos más sencillos y a la vez sofisticados—¿imaginas el iPhone del futuro?—sino que haría el sueño de OLPC una realidad.

Una vez liberados de los cables, estos niños podrán asimilar información y tecnología de manera casi instantánea.  De hecho, la idea de adiciones bio-tecnológicas al cuerpo humano no está completamente fuera del rango de posibilidades.  Imagina que en lugar de cargar un dispositivo como un celular o tableta inteligente que te brinda información, ésta esté integrada a ti.  Una red inalámbrica ubicua y un "chip" integrado podría darle la capacidad a los niños de este siglo de comunicarse y compartir información pseudo-psíquicamente en una red verdaderamente P2P.  Piensa en los Borg, de Star Trek, pero no tan feos y con independencia de acción.

¿Todavía suena como ciencia ficción?  Considera que en unos 15 años seguramente habrá avances significativos en la nanotecnología y que según algunos expertos para el 2029 también habrá tanto el hardware como el software necesario para tener inteligencia artificial a nivel humano.  Supon que se retrasen algunos años, el doble aproximadamente, y esto no se de sino hasta mediados de siglo.  Los niños de la generación W estarán apenas entrando a la adolescencia.

Sin embargo hay cosas que podrían descarrilar todo esto.  Conflictos globales persistentes, como la actual guerra en Irak podrían llevar a un des-aplanamiento del mundo y a que se vuelvan a cerrar las fronteras, regresándonos a la era Reagan.  Simplemente consideren algunos de los argumentos de los actuales candidatos demócratas a la presidencia de EE.UU., Barack Obama y Hillary Clinton.  Ambos han expresado que quieren re-negociar el TLC.  Entre eso, y el muro—perdón, "barda"—fronterizo que tan insistentemente y están construyendo, no inspira precisamente un ambiente de apertura para el futuro.  Siguiendo esta línea de pensamiento, no es tampoco d