<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Quemando cromo &#187; Visual Basic 2005</title>
	<atom:link href="http://cromo.cda-ie.es/category/programacion/visual-basic-2005/feed/" rel="self" type="application/rss+xml" />
	<link>http://cromo.cda-ie.es</link>
	<description>Hacía calor, la noche que quemamos a Cromo</description>
	<lastBuildDate>Tue, 27 Dec 2011 08:07:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>El problema de la barra de progreso</title>
		<link>http://cromo.cda-ie.es/2011/12/27/el-problema-de-la-barra-de-progreso/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=el-problema-de-la-barra-de-progreso</link>
		<comments>http://cromo.cda-ie.es/2011/12/27/el-problema-de-la-barra-de-progreso/#comments</comments>
		<pubDate>Tue, 27 Dec 2011 08:07:53 +0000</pubDate>
		<dc:creator>Cubano</dc:creator>
				<category><![CDATA[Visual Basic 2005]]></category>
		<category><![CDATA[Visual Basic 2008]]></category>
		<category><![CDATA[Visual Basic 2010]]></category>

		<guid isPermaLink="false">http://cromo.cda-ie.es/?p=382</guid>
		<description><![CDATA[El año pasado, intentando desembarazarme de una tarea tediosa que dejaba frito mi equipo, usé mi primera función recursiva con utilidad práctica. Como la tarea consumía su tiempo, tiré de un BackGroundWorker. Componente sencillo de usar y con ejemplos bastante claros en la ayuda de Visual Studio. No problem: tenía un valor de entrada pedido [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify"><span style="font-size:10pt"><span style="font-family:Verdana">El año pasado, intentando desembarazarme de una tarea tediosa que dejaba frito mi equipo, usé mi primera función recursiva con utilidad práctica. Como la tarea consumía su tiempo, tiré de un </span><span style="font-family:Courier New"><strong>BackGroundWorker</strong></span><span style="font-family:Verdana">. Componente sencillo de usar y con ejemplos bastante claros en la ayuda de Visual Studio. No problem: tenía un valor de entrada pedido por el usuario, se realizaban n operaciones de forma recursiva, se obtenía un valor de salida.<br />
</span></span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">Como el proceso era algo largo (mínimo unos diez segundos, pero podía llegar superar el minuto en la versión 2, que admitía de entrada una serie de valores), se me ocurrió usar una barra de progreso para mantener informado al usuario.<br />
</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">Entonces empezaron los problemas.<br />
</span></p>
<p style="text-align: justify"><span style="font-size:10pt"><span style="font-family:Verdana">Todos los ejemplos que he visto que usan el evento </span><span style="font-family:Courier New"><strong>ProgressChanged</strong></span><span style="font-family:Verdana"> del </span><span style="font-family:Courier New"><strong>BackGroundWorker</strong></span><span style="font-family:Verdana"> para alimentar una barra de progreso presentan una serie de operaciones en secuencia con llamadas a </span><span style="font-family:Courier New"><strong>ProgressChanged</strong></span><span style="font-family:Verdana"> entre ellas, es decir: hago paso 1; progreso cambiado; hago paso 2; progreso cambiado… Sin embargo, mi problema era otro: tengo una instancia de mi clase de trabajo, cojo los valores del usuario (a través de </span><span style="font-family:Courier New"><strong>DoWorkEventArgs.Argument</strong></span><span style="font-family:Verdana">), se los paso, y le digo &#8220;ea, majo. Tú puedes&#8221; llamando al método </span><span style="font-family:Courier New"><strong>MiClase.HacerCurro</strong></span><span style="font-family:Verdana">. Ahí dentro se harán las n operaciones (recursivas), número desconocido hasta que se hagan.<br />
</span></span></p>
<p style="text-align: justify"><span style="font-size:10pt"><span style="font-family:Verdana">Vale, pensé. Puedo provocar un evento </span><span style="font-family:Courier New"><strong>OperaciónCompletada</strong></span><span style="font-family:Verdana"> cada vez que complete una operación. Pero la instancia de </span><span style="font-family:Courier New"><strong>MiClase</strong></span><span style="font-family:Verdana"> está declarada dentro del </span><span style="font-family:Courier New"><strong>DoWork</strong></span><span style="font-family:Verdana"> del </span><span style="font-family:Courier New"><strong>BackGroundWorker</strong></span><span style="font-family:Verdana">. No tengo acceso desde fuera. ¿Cómo lo hago?<br />
</span></span></p>
<p style="text-align: justify"><span style="font-size:10pt"><span style="font-family:Verdana">¿Y si meto alguien que escuche en el </span><span style="font-family:Courier New"><strong>DoWork</strong></span><span style="font-family:Verdana">? De esta forma tendría mi &#8220;escuchador&#8221; de eventos en el mismo hilo. Es decir, una clase, digamos </span><span style="font-family:Courier New"><strong>Escuchante</strong></span><span style="font-family:Verdana">, a la que le paso mi instancia de </span><span style="font-family:Courier New"><strong>MiClase</strong></span><span style="font-family:Verdana"> y la del </span><span style="font-family:Courier New"><strong>BackGroundWorker</strong></span><span style="font-family:Verdana">. Escuchante gestiona el evento </span><span style="font-family:Courier New"><strong>OperacionCompletada</strong></span><span style="font-family:Verdana"> provocando a su vez el </span><span style="font-family:Courier New"><strong>ProgressChanged</strong></span><span style="font-family:Verdana">, que actualiza la barra de progreso.<br />
</span></span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">No sé si será una solución muy limpia, pero funcionó.<br />
</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">En resumen, algo así:<br />
</span></p>
<p ><span style="font-family:Courier New; font-size:10pt">Public Class Escuchante<br />
</span></p>
<p ><span style="font-family:Courier New; font-size:10pt">Private WithEvents _MiClase as MiClase<br />
</span></p>
<p ><span style="font-family:Courier New; font-size:10pt">Private _MiBGW as BackGroundWorker<br />
</span></p>
<p ><span style="font-family:Courier New; font-size:10pt">Public Sub New(mc as MiClase, bw as BackGroundWorker)<br />
</span></p>
<p style="margin-left: 36pt"><span style="font-family:Courier New; font-size:10pt">_MiClase=mc<br />
</span></p>
<p style="margin-left: 36pt"><span style="font-family:Courier New; font-size:10pt">_MiBGW=bw<br />
</span></p>
<p ><span style="font-family:Courier New; font-size:10pt">End Sub<br />
</span></p>
<p ><span style="font-family:Courier New; font-size:10pt">Private Sub OpCompletada(sender as Object, e as OperacionCompletadaEventArgs) _<br />
</span></p>
<p ><span style="font-family:Courier New; font-size:10pt">                                    Handles _MiClase.OperacionCompletada<br />
</span></p>
<p style="margin-left: 36pt"><span style="font-family:Courier New; font-size:10pt">_MiBGW.ReportProgress=e.NumOp<br />
</span></p>
<p ><span style="font-family:Courier New; font-size:10pt">End Sub<br />
</span></p>
<p ><span style="font-family:Courier New; font-size:10pt">End Class</span></p>
]]></content:encoded>
			<wfw:commentRss>http://cromo.cda-ie.es/2011/12/27/el-problema-de-la-barra-de-progreso/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pegar datos de una hoja de Excel a un DataGridView</title>
		<link>http://cromo.cda-ie.es/2011/01/18/pegar-datos-de-una-hoja-de-excel-a-un-datagridview/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=pegar-datos-de-una-hoja-de-excel-a-un-datagridview</link>
		<comments>http://cromo.cda-ie.es/2011/01/18/pegar-datos-de-una-hoja-de-excel-a-un-datagridview/#comments</comments>
		<pubDate>Tue, 18 Jan 2011 21:05:29 +0000</pubDate>
		<dc:creator>Cubano</dc:creator>
				<category><![CDATA[Visual Basic 2005]]></category>
		<category><![CDATA[Visual Basic 2008]]></category>
		<category><![CDATA[Visual Basic 2010]]></category>

		<guid isPermaLink="false">http://cromo.cda-ie.es/?p=338</guid>
		<description><![CDATA[Un intento de simplificar el uso de una aplicación por lo demás bastante simple (de cara al usuario) me ha llevado a jugar con el portapapeles para permitir que el usuario copie una serie de valores de una hoja de cálculo (Excel, para más señas) y las pegue en un DataGridView, algo que me ha [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">Un intento de simplificar el uso de una aplicación por lo demás bastante simple (de cara al usuario) me ha llevado a jugar con el portapapeles para permitir que el usuario copie una serie de valores de una hoja de cálculo (Excel, para más señas) y las pegue en un DataGridView, algo que me ha costado un buen rato, no porque sea complicado, sino porque no he encontrado información al respecto por Internet (seguramente por la torpeza &#8220;buscativa&#8221; de uno).</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">El problema, como digo, no es complicado. Por una parte, acceder al portapapeles es muy sencillo, mediante My.Computer.Clipboard y hay varios métodos para extraer su contenido según lo que contenga. En este caso (la copia de texto) usaremos el método GetText, que nos devuelve un String. El dónde gestionar esto ya queda a gusto del consumidor pero, para mí, lo más fácil es añadir un menú contextual con el habitual atajo de teclado (Ctrl + V).</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">El siguiente paso es tratar ese texto. Cualquier colección de celdas de Excel es copiada al portapapeles como un conjunto de valores separados por tabulación. El otro día mostraba el uso de la clase <b><a href="http://cromo.cda-ie.es/2010/11/23/leer-ficheros-csv-y-de-campos-de-ancho-fijo-en-visual-basic/">TextFieldParser</a></b> para procesar ficheros de texto que nos viene como anillo al dedo. Bueno, casi, porque al TextFieldParser no le podemos pasar un String, está pensado para procesar ficheros. Si vemos sus constructores, a uno se le pasa la ruta de un fichero, a otro un Stream, precisamente para tratar con un fichero, y a la tercera sobrecarga, un TextReader.</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">¿Qué es un TextReader (era la primera vez que lo veía)? Según la biblioteca de MSDN, TextReader es la clase abstracta de StreamReader (éste si lo conocía) y StringReader. Éste último tiene en su nombre la palabra mágica, String, así que merece la pena echar un ojo. Me da igual los tutoriales que nos puedan aparecer ni los mil usos que tenga StringReader. Para el caso que nos ocupa, todo se reduce a crear un StringReader a partir del texto contenido en el portapapeles:</span></p>
<p><span style="font-family:Courier New; font-size:10pt"><span style="color:blue">Dim</span> miTexto <span style="color:blue">As</span> <span style="color:#2b91af">StringReader</span></span></p>
<p><span style="font-family:Courier New; font-size:10pt">miTexto = <span style="color:blue">New</span> <span style="color:#2b91af">StringReader</span>(<span style="color:blue">My</span>.Computer.Clipboard.GetText)</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">Y pasarle ese StringReader a un TextFieldParser, con lo que estamos casi, casi, en el mismo caso del ejemplo de TextFieldParser. Ya podemos trabajar de forma simple con el texto del portapapeles. Sólo hay que añadir los controles de errores necesarios y decidir qué vamos a hacer con cada fila válida devuelta por el TextFieldParser. Siguiendo la lógica del título de esta entrada, pasárselas al DataGridView, pero tengo que confesar que no lo hice así. La razón es muy simple: me interesaba más pasárselo directamente al origen de datos del DataGridView.</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">Para mi caso concreto (Origen de datos + BindingSource + DataGridView), antes de iniciar el proceso de lectura de TextFieldParser, llamé al CancelEdit del BindingSource para evitar la posibilidad de que se generase una fila en blanco o no válida (si se da el caso, se saltaría la validación de datos) y le quité también la referencia al DataSource:</span></p>
<p style="text-align: justify"><span style="font-family:Courier New; font-size:10pt"><span style="color:blue">Me</span>.bsArticulos.CancelEdit()<br />
</span></p>
<p><span style="font-family:Courier New; font-size:10pt"><span style="color:blue">Me</span>.bsArticulos.DataSource = <span style="color:#a31515">&#8220;&#8221;<br />
</span></span></p>
<p><span style="font-family:Verdana; font-size:10pt">Después de añadir los valores del portapapeles al origen de datos, se vuelve a enlazar el BindingSource con éste y listo. Bueno, vale, no he pegado realmente en el DataGridView. Espero que nadie se sienta estafado.<br />
</span></p>
<p><span style="font-family:Verdana; font-size:10pt">Nos vemos en el <em>Forlon.</em></span></p>
]]></content:encoded>
			<wfw:commentRss>http://cromo.cda-ie.es/2011/01/18/pegar-datos-de-una-hoja-de-excel-a-un-datagridview/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Leer ficheros csv y de campos de ancho fijo en Visual Basic</title>
		<link>http://cromo.cda-ie.es/2010/11/23/leer-ficheros-csv-y-de-campos-de-ancho-fijo-en-visual-basic/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=leer-ficheros-csv-y-de-campos-de-ancho-fijo-en-visual-basic</link>
		<comments>http://cromo.cda-ie.es/2010/11/23/leer-ficheros-csv-y-de-campos-de-ancho-fijo-en-visual-basic/#comments</comments>
		<pubDate>Tue, 23 Nov 2010 14:21:10 +0000</pubDate>
		<dc:creator>Cubano</dc:creator>
				<category><![CDATA[Visual Basic 2005]]></category>
		<category><![CDATA[Visual Basic 2008]]></category>

		<guid isPermaLink="false">http://cromo.cda-ie.es/?p=323</guid>
		<description><![CDATA[En mi vuelta al servicio activo he tenido que procesar dos ficheros en texto plano: uno con campos separados por un carácter y otro con campos de ancho fijo. En su día ya lo hice (concretamente para un csv, valores separados por comas), pero no me acordaba de cómo lo hice (fue al poco de [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">En mi vuelta al servicio activo he tenido que procesar dos ficheros en texto plano: uno con campos separados por un carácter y otro con campos de ancho fijo. En su día ya lo hice (concretamente para un csv, valores separados por comas), pero no me acordaba de cómo lo hice (fue al poco de empezar con VB2005) y no tenía a mano ni el código que hice ni el libro que usé de referencia, así que busqué en Internet.<br />
</span></p>
<p style="text-align: justify"><span style="font-size:10pt"><span style="font-family:Verdana">Y fíjese usted por donde, encontré una forma más simple de hacer las cosas que no conocía: usando la clase </span><a href="http://msdn.microsoft.com/es-es/library/ms128079.aspx"/><span style="font-family:Courier New">TextFieldParser</span></a><span style="font-family:Verdana">.</span></p>
<p style="text-align: justify"><span style="font-size:10pt"><span style="font-family:Verdana">En la forma más fácil, le pasamos en el constructor la ruta del archivo a tratar. Le indicamos luego qué es, si de ancho fijo (</span><span style="font-family:Courier New"><strong>FixedWith</strong></span><span style="font-family:Verdana">) o separado por carácter (</span><span style="font-family:Courier New"><strong>Delimited</strong></span><span style="font-family:Verdana">) con la propiedad </span><span style="font-family:Courier New"><strong>TextFieldType</strong></span><span style="font-family:Verdana">. Si es el segundo caso, con el método </span><span style="font-family:Courier New"><strong>SetDelimiters</strong></span><span style="font-family:Verdana"> indicamos el delimitador (por ejemplo, </span><span style="font-family:Courier New">MiTfp.SetDelimiters(vbTab)</span><span style="font-family:Verdana"> para indicar campos separados por una tabulación).</span></p>
<p style="text-align: justify"><span style="font-size:10pt"><span style="font-family:Verdana">En el primero, indicaríamos el ancho de los campos mediante una lista de enteros que le pasamos al método </span><span style="font-family:Courier New"><strong>SetFieldWiths</strong></span><span style="font-family:Verdana">: </span><span style="font-family:Courier New">MiTfp.SetFieldWiths(2, 3, 12, 85, 5)</span><span style="font-family:Verdana">.</span></p>
<p style="text-align: justify"><span style="font-size:10pt"><span style="font-family:Verdana">Para leer cada línea tenemos el método </span><span style="font-family:Courier New"><strong>ReadFields</strong></span><span style="font-family:Verdana">, que nos devuelve un array de cadenas con cada campo de la línea del fichero en la posición correspondiente del array. Se tarda más en explicar que en hacer.</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">Hay un pequeño problema adicional: la codificación de caracteres. Por defecto, se usa UTF8. Ahora mismo no recuerdo si Vista y 7 usan UTF8 por defecto, pero XP y versiones anteriores de Windows, no, y podemos encontrarnos con problemas con algunos caracteres, como ñ, tildes, etc. En ese caso, seguramente estemos usando Windows occidental (Windows 1252) o, más raramente, ISO-8859-1. Podemos indicarle esto al TextFieldParser en el constructor, pasándole el código de <a href="http://msdn.microsoft.com/es-es/library/system.text.encoding%28v=VS.100%29.aspx">la página de códigos</a> a emplear:</span></p>
<p style="text-align: justify"><span style="font-family:Courier New; font-size:10pt">Dim MiTfp as New TextFieldParser(MiRuta, System.Text.Encoding.GetEncoding(1252))<br />
</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">Lo más largo, como siempre, es el control de errores, o el propio tratamiento de los valores que hayamos leído, pero el hecho de leer en sí más simple no puede ser.<br />
</span></p>
]]></content:encoded>
			<wfw:commentRss>http://cromo.cda-ie.es/2010/11/23/leer-ficheros-csv-y-de-campos-de-ancho-fijo-en-visual-basic/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DataRepeater y el evento Enter de sus controles</title>
		<link>http://cromo.cda-ie.es/2010/11/16/datarepeater-y-el-evento-enter-de-sus-controles/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=datarepeater-y-el-evento-enter-de-sus-controles</link>
		<comments>http://cromo.cda-ie.es/2010/11/16/datarepeater-y-el-evento-enter-de-sus-controles/#comments</comments>
		<pubDate>Tue, 16 Nov 2010 10:24:18 +0000</pubDate>
		<dc:creator>Cubano</dc:creator>
				<category><![CDATA[Visual Basic 2005]]></category>
		<category><![CDATA[Visual Basic 2008]]></category>

		<guid isPermaLink="false">http://cromo.cda-ie.es/2010/11/12/datarepeater-y-el-evento-enter-de-sus-controles/</guid>
		<description><![CDATA[A la hora de evitar que el usuario manazas edite el valor de algún control, una opción habitual es controlar el evento Enter de ese control o de su contenedor (un GroupBox, un Panel&#8230;), mandando el foco a otro control mediante el método OtroControl.Select(). Esto funciona para buena parte de los controles disponibles en Windows [...]]]></description>
			<content:encoded><![CDATA[<p><span style="font-family:Verdana; font-size:10pt">A la hora de evitar que el usuario manazas edite el valor de algún control, una opción habitual es controlar el evento Enter de ese control o de su contenedor (un GroupBox, un Panel&#8230;), mandando el foco a otro control mediante el método OtroControl.Select(). Esto funciona para buena parte de los controles disponibles en Windows Forms, pero no para todos (dtpicker, optionbutton&#8230; hay varios que pasarán de nosotros).<br />
</span></p>
<p><span style="font-family:Verdana; font-size:10pt">Si nosotros queremos usar este sistema con controles que estén dentro de un DataRepeater&#8230; En fin, probadlo si queréis, pero ya os digo que la aplicación se quedará muerta si mandáis el foco a un control que esté fuera del DataRepeater. ¿Entonces?<br />
</span></p>
<p><span style="font-family:Verdana; font-size:10pt">Pues no salgamos. Pasemos el foco al ítem del DataRepeater al que pertenezca el control y listo:<br />
</span></p>
<p><span style="font-family:Courier New; font-size:10pt"><strong>MiDataRepeater.CurrentItem.Select()<br />
</strong></span></p>
<p><span style="font-family:Verdana; font-size:10pt">El control DataRepeater es más versátil que el habitual DataGridView, pero es caprichoso como él solo.<br />
</span></p>
]]></content:encoded>
			<wfw:commentRss>http://cromo.cda-ie.es/2010/11/16/datarepeater-y-el-evento-enter-de-sus-controles/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ordenando por resoluciones</title>
		<link>http://cromo.cda-ie.es/2009/07/13/ordenando-por-resoluciones/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=ordenando-por-resoluciones</link>
		<comments>http://cromo.cda-ie.es/2009/07/13/ordenando-por-resoluciones/#comments</comments>
		<pubDate>Mon, 13 Jul 2009 17:15:47 +0000</pubDate>
		<dc:creator>Cubano</dc:creator>
				<category><![CDATA[Visual Basic 2005]]></category>
		<category><![CDATA[Visual Basic 2008]]></category>

		<guid isPermaLink="false">http://cromo.cda-ie.es/?p=139</guid>
		<description><![CDATA[Esto es una tontería del tipo tonterida, pero me ha llevado un ratito escribir el código, así que lo anoto aquí para cuando me vuelva a pasar, que entonces, seguramente, ya se me habrá olvidado y me tocará echar otro ratito y no me apetece. El problema es sencillo: hay que ordenar una lista de [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify"><span style="font-size:10pt"><span style="font-family:Verdana">Esto es una tontería del tipo <em>tonterida</em>, pero me ha llevado un ratito escribir el código, así que lo anoto aquí para cuando me vuelva a pasar, que entonces, seguramente, ya se me habrá olvidado y me tocará echar otro ratito y no me apetece. El problema es sencillo: hay que ordenar una lista de elementos de forma no trivial. En este caso concreto, hay que ordenar por una propiedad de tipo </span><span style="font-family:Courier New">String</span><span style="font-family:Verdana">, cadena de caracteres, que va a contener resoluciones de imagen, esto es, dos valores numéricos separados por una &#8220;x&#8221;: 640&#215;480, 1024&#215;768 y así. También serviría para cualquier lista de pares de valores y se podría extender a situaciones más complejas, como coordenadas espaciales y cosas así. </span></span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">Lo primero ha sido elegir el algoritmo de ordenación. Como van a ser pocos elementos, me he tirado a los sencillitos y, de estos, al de inserción, que es el único que soy capaz de desarrollar sin mirar la chuleta (el de la burbuja lo tengo atravesado). El proceso es muy simple: vamos ordenando por el primer valor. Si este es igual, pasamos a ordenar por el segundo valor. En este caso concreto, ordenamos por largo (primer valor) y si son iguales, por ancho. Para ello, lo primero que he hecho ha sido crearme dos funciones que me devuelvan el largo o el ancho a partir de la cadena:</span></p>
<p><span id="more-139"></span></p>
<table border="0" width="90%" align="center" bgcolor="#e6e6fa">
<tbody>
<tr>
<td>
<pre style="font-family: 'Courier New', Courier, monospace; font-size:9pt"><span style="color:#0000FF">Private</span> <span style="color:#0000FF">Function</span> ValorNumL(<span style="color:#0000FF">ByVal</span> Resolucion <span style="color:#0000FF">As</span> <span style="color:#0000FF">String</span>) <span style="color:#0000FF">As</span> <span style="color:#0000FF">Integer</span>
    <span style="color:#0000FF">Dim</span> pos <span style="color:#0000FF">As</span> <span style="color:#0000FF">Integer</span>
    pos = Resolucion.ToLower.IndexOf(<span style="color:#B22222">"x"</span>c)
    <span style="color:#0000FF">If</span> pos = -1 <span style="color:#0000FF">Then</span>
        ValorNumL = 0
    <span style="color:#0000FF">Else</span>
        <span style="color:#0000FF">Try</span>
            ValorNumL = <span style="color:#0000FF">CInt</span>(Strings.Left(Resolucion, pos))
        <span style="color:#0000FF">Catch</span> ex <span style="color:#0000FF">As</span> Exception
            ValorNumL = 0
        <span style="color:#0000FF">End</span> <span style="color:#0000FF">Try</span>
    <span style="color:#0000FF">End</span> <span style="color:#0000FF">If</span>
    <span style="color:#0000FF">Return</span> ValorNumL
<span style="color:#0000FF">End</span> <span style="color:#0000FF">Function</span>
<span style="color:#0000FF">Private</span> <span style="color:#0000FF">Function</span> ValorNumA(<span style="color:#0000FF">ByVal</span> Resolucion <span style="color:#0000FF">As</span> <span style="color:#0000FF">String</span>) <span style="color:#0000FF">As</span> <span style="color:#0000FF">Integer</span>
    <span style="color:#0000FF">Dim</span> pos <span style="color:#0000FF">As</span> <span style="color:#0000FF">Integer</span>
    pos = Resolucion.ToLower.IndexOf(<span style="color:#B22222">"x"</span>c)
    <span style="color:#0000FF">If</span> pos = -1 <span style="color:#0000FF">Then</span>
        ValorNumA = 0
    <span style="color:#0000FF">Else</span>
        <span style="color:#0000FF">Try</span>
            ValorNumA = <span style="color:#0000FF">CInt</span>(Strings.Right(Resolucion, _
                            Resolucion.Length - (pos + 1)))
        <span style="color:#0000FF">Catch</span> ex <span style="color:#0000FF">As</span> Exception
            ValorNumA = 0
        <span style="color:#0000FF">End</span> <span style="color:#0000FF">Try</span>
    <span style="color:#0000FF">End</span> <span style="color:#0000FF">If</span>
    <span style="color:#0000FF">Return</span> ValorNumA
<span style="color:#0000FF">End</span> <span style="color:#0000FF">Function</span></pre>
</td>
</tr>
</tbody>
</table>
<p style="text-align: justify"><span style="font-size:10pt"><span style="font-family:Verdana">Lo siguiente, implementar la búsqueda. Parto de una </span><span style="font-family:Courier New">List(of IdMasDescripcion)</span><span style="font-family:Verdana"> de nombre Resoluciones, donde </span><span style="font-family:Courier New">IdMasDescripcion</span><span style="font-family:Verdana"> es una clase que tiene una propiedad, </span><span style="font-family:Courier New">Descripcion</span><span style="font-family:Verdana">, de tipo </span><span style="font-family:Courier New">String</span><span style="font-family:Verdana">, que es por la que vamos a ordenar. </span></span></p>
<table border="0" width="90%" align="center" bgcolor="#e6e6fa">
<tbody>
<tr>
<td>
<pre style="font-family: 'Courier New', Courier, monospace; font-size:9pt"><span style="color:#0000FF">Dim</span> i, j, ElementoLargo, ElementoAncho, jLargo, jAncho <span style="color:#0000FF">As</span> <span style="color:#0000FF">Integer</span>
<span style="color:#0000FF">Dim</span> Elemento <span style="color:#0000FF">As</span> IdMasDescripcion
<span style="color:#0000FF">Dim</span> Menor <span style="color:#0000FF">As</span> <span style="color:#0000FF">Boolean</span> = <span style="color:#0000FF">False</span>
<span style="color:#0000FF">For</span> i = 1 <span style="color:#0000FF">To</span> Resoluciones.Count - 1
    Elemento = Resoluciones(i)
    ElementoLargo = ValorNumL(Elemento.Descripcion)
    ElementoAncho = ValorNumA(Elemento.Descripcion)
    j = i - 1
    <span style="color:#0000FF">Do</span>
        <span style="color:#008000">'1) Comparamos primero el largo(lado izdo):</span>
        jLargo = ValorNumL(Resoluciones(j).Descripcion)
        <span style="color:#0000FF">If</span> jLargo &gt; ElementoLargo <span style="color:#0000FF">Then</span>
            Resoluciones(j + 1) = Resoluciones(j)
            j = j - 1
            Menor = <span style="color:#0000FF">False</span>
        <span style="color:#0000FF">ElseIf</span> jLargo = ElementoLargo <span style="color:#0000FF">Then</span>
            <span style="color:#008000">'Si son iguales, ordenamos por el ancho</span>
            jAncho = ValorNumA(Resoluciones(j).Descripcion)
            <span style="color:#0000FF">If</span> jancho &gt; ElementoAncho <span style="color:#0000FF">Then</span>
                Resoluciones(j + 1) = Resoluciones(j)
                j = j - 1
                Menor = <span style="color:#0000FF">False</span>
            <span style="color:#0000FF">Else</span>
                Menor = <span style="color:#0000FF">True</span>
            <span style="color:#0000FF">End</span> <span style="color:#0000FF">If</span>
        <span style="color:#0000FF">Else</span>
            Menor = <span style="color:#0000FF">True</span>
        <span style="color:#0000FF">End</span> <span style="color:#0000FF">If</span>
    <span style="color:#0000FF">Loop</span> <span style="color:#0000FF">Until</span> j &lt; 0 <span style="color:#0000FF">OrElse</span> Menor
    Resoluciones(j + 1) = Elemento
<span style="color:#0000FF">Next</span></pre>
</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://cromo.cda-ie.es/2009/07/13/ordenando-por-resoluciones/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mantener actualizados unos ComboBox</title>
		<link>http://cromo.cda-ie.es/2009/07/02/mantener-actualizados-unos-combobox/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mantener-actualizados-unos-combobox</link>
		<comments>http://cromo.cda-ie.es/2009/07/02/mantener-actualizados-unos-combobox/#comments</comments>
		<pubDate>Thu, 02 Jul 2009 09:54:48 +0000</pubDate>
		<dc:creator>Cubano</dc:creator>
				<category><![CDATA[Visual Basic 2005]]></category>
		<category><![CDATA[Visual Basic 2008]]></category>

		<guid isPermaLink="false">http://cromo.cda-ie.es/?p=131</guid>
		<description><![CDATA[Vamos con una de programación, que hace mucho que no cuento nada (básicamente, porque llevo unos meses sin programar; a ver si arranco motores). Me he puesto con mi aplicación de anime (un front-end para una base de datos de series, nada más, que me sirve de aprendizaje y experimentación). Ya me toca meter datos, [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">Vamos con una de programación, que hace mucho que no cuento nada (básicamente, porque llevo unos meses sin programar; a ver si arranco motores). Me he puesto con mi aplicación de anime (un <em>front-end</em> para una base de datos de series, nada más, que me sirve de aprendizaje y experimentación). Ya me toca meter datos, sacar fallos, pulir el funcionamiento y terminar algunas funciones pendientes. Y recordar lo que estaba haciendo, que hace seis meses o así que no la tocaba.<br />
</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">Una de estas funciones, o funcionalidades, si lo preferís para no confundirlo con <em>functions</em>, es la de mantener actualizados una serie de comboboxes que hay en el formulario principal de las series. Estos comboboxes contienen los datos de una serie de tablas de la base de datos que se caracterizan por tener pocos datos: el formato de archivo, la resolución, el códec de vídeo… En otras circunstancias, los rellenaría usando mi clase <a href="http://cda-ie.es/2008/01/09/llenar-un-combobox/" target="_blank">RellenarCombo</a>, pero aquí se me presenta un problema curioso: como podéis ver en la imagen, hay una buena cantidad de comboboxes (una docena o así) que se corresponden a una serie de campos de las Releases (versiones) de una serie. El formulario muestra conjuntamente las series y sus releases, estando en la parte superior los datos de la serie y en la inferior, <em>en cero o más pestañas</em> los datos de las releases. O sea, tengo una docena de combos por cada pestaña.<br />
</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">Aquí empezaron mis problemas: ¿cómo rellenar esos combos y mantenerlos actualizados?</span></p>
<p><span id="more-131"></span></p>
<p style="text-align: center;"><img style="border: 0pt none; margin: 5px;" src="http://i114.photobucket.com/albums/n280/ercubano/Foro/pestagnarelease.jpg" alt="" width="400" height="200" /></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">Lo primero que pensé fue no utilizar combos. En lugar de traerme los datos de las Releases (tabla) y ligarlos al ValueMember de cada combo, podía crearme una consulta que englobara la tabla de Releases y las tablas relacionadas. A la hora de modificar datos sí tendría que mostrar los combos y trabajar con la tabla de Releases, lo que me añadiría bastante complicación al código. Este sistema, más o menos, es el que estoy siguiendo en una aplicación para fábrica donde la modificación de los datos será mínima.<br />
</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">Otra opción era rellenar cada combo por su cuenta. En principio, lo normal sería tener sólo una release por serie, esto es, una pestaña, siendo tres o cuatro el número máximo. Así pues, podría hacer la carga del combo, digamos, de Tipo de archivo, una vez para cada pestaña. Esto no me gustaba por varias razones: la primera es la redundancia de datos en memoria. Si tengo tres veces el mismo ComboBox en el formulario (en tres pestañas) he cargado tres datatables para ligarlas a estos combos. La segunda es que a la hora de mantener esos datos actualizados (por ejemplo, si añado un nuevo tipo de archivo) tendría que comprobar cuántas pestañas hay y volver a cargar cada tabla ligada a cada combobox. Si tengo tres pestañas, el trabajo por tres. Y la tercera y más importante: no me parecía elegante.<br />
</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">Así que opté por cargar todos esos datos en memoria y que los combos de las distintas pestañas, independientemente de cuántas pestañas hubiera, se sirvieran de ellos. Como mucho, unos doscientos registros formados por dos campos: un valor numérico (clave primaria, a ligar al ValueMember) y una cadena de caracteres (el campo descriptor que se mostrará en el combo). Para trabajar con ello creé una clase muy sencilla que contuviera esos valores. En su forma más simple:<br />
</span></p>
<table border="0" width="90%" align="center" bgcolor="#e6e6fa">
<tbody>
<tr>
<td>
<pre style="font-family: 'Courier New', Courier, monospace; font-size:9pt"><span style="color:#0000FF">Public</span> <span style="color:#0000FF">Class</span> IdMasDescripcion
    <span style="color:#0000FF">Private</span> _Id <span style="color:#0000FF">As</span> <span style="color:#0000FF">Integer</span>
    <span style="color:#0000FF">Private</span> _Descripcion <span style="color:#0000FF">As</span> <span style="color:#0000FF">String</span>
    <span style="color:#0000FF">Public</span> <span style="color:#0000FF">Sub</span> <span style="color:#0000FF">New</span>(<span style="color:#0000FF">ByVal</span> Id <span style="color:#0000FF">As</span> <span style="color:#0000FF">Integer</span>, _
                   <span style="color:#0000FF">ByVal</span> Descripcion <span style="color:#0000FF">As</span> <span style="color:#0000FF">String</span>)
        _Id = Id
        _Descripcion = Descripcion
    <span style="color:#0000FF">End</span> <span style="color:#0000FF">Sub</span>
    <span style="color:#0000FF">Public</span> <span style="color:#0000FF">Sub</span> <span style="color:#0000FF">New</span>()

    <span style="color:#0000FF">End</span> <span style="color:#0000FF">Sub</span>
    <span style="color:#0000FF">Public</span> <span style="color:#0000FF">Property</span> Id() <span style="color:#0000FF">As</span> <span style="color:#0000FF">Integer</span>
        <span style="color:#0000FF">Get</span>
            <span style="color:#0000FF">Return</span> _Id
        <span style="color:#0000FF">End</span> <span style="color:#0000FF">Get</span>
        <span style="color:#0000FF">Set</span>(<span style="color:#0000FF">ByVal</span> <span style="color:#0000FF">value</span> <span style="color:#0000FF">As</span> <span style="color:#0000FF">Integer</span>)
            _Id = <span style="color:#0000FF">value</span>
        <span style="color:#0000FF">End</span> <span style="color:#0000FF">Set</span>
    <span style="color:#0000FF">End</span> <span style="color:#0000FF">Property</span>
    <span style="color:#0000FF">Public</span> <span style="color:#0000FF">Property</span> Descripcion() <span style="color:#0000FF">As</span> <span style="color:#0000FF">String</span>
        <span style="color:#0000FF">Get</span>
            <span style="color:#0000FF">Return</span> _Descripcion
        <span style="color:#0000FF">End</span> <span style="color:#0000FF">Get</span>
        <span style="color:#0000FF">Set</span>(<span style="color:#0000FF">ByVal</span> <span style="color:#0000FF">value</span> <span style="color:#0000FF">As</span> <span style="color:#0000FF">String</span>)
            _Descripcion = <span style="color:#0000FF">value</span>
        <span style="color:#0000FF">End</span> <span style="color:#0000FF">Set</span>
    <span style="color:#0000FF">End</span> <span style="color:#0000FF">Property</span>
<span style="color:#0000FF">End</span> <span style="color:#0000FF">Class</span></pre>
</td>
</tr>
</tbody>
</table>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">Luego me declaré una serie de colecciones de IdMasDescripcion, digamos que unas List (of IdMasDescripcion). Al arrancar la aplicación y realizar la carga de datos, rellenos estas colecciones con los datos de las tablas respectivas. Luego, en el procedimiento que controla las pestañas, cuando se crea una, ligo cada colección a su ComboBox correspondiente (mediante su DataSource, etc.) y listo.<br />
</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">Bueno, listo, no. Ahora viene controlar que se muestren los datos actualizados en esos combos. Si, digamos, yo añado un nuevo tipo de archivo, la aplicación lo detecta y vuelve a rellenar la List(of T) correspondiente a esta tabla, los combos ya existentes no muestran los cambios. Oh, vaya.<br />
</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">La solución es muy simple: la colección elegida no es la adecuada para esto. Si cambiamos la List(of T) por una BindingList(of T), problema solucionado.<br />
</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">En resumen: vuelco los datos que necesito de una tabla de la base de datos a una BindingList. Enlazo todos los comboboxes que vayan a mostrar esos datos (uno por pestaña, vaya) a la BindingList y puedo mantenerlos todos actualizados para cuando vaya a modificar una release. Ahora que lo veo así, resulta evidente, pero en su momento me llevó bastante caer en ello.<br />
</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">No me da tiempo a más. Si alguien quiere que ponga el código completo (aunque no es nada del otro mundo, la verdad), pues me lo pide y lo subo en cuanto pueda.<br />
</span></p>
<p style="text-align: justify"><span style="font-family:Verdana; font-size:10pt">Nos vemos en el <em>Forlon.</em></span></p>
]]></content:encoded>
			<wfw:commentRss>http://cromo.cda-ie.es/2009/07/02/mantener-actualizados-unos-combobox/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dando clases</title>
		<link>http://cromo.cda-ie.es/2009/03/12/dando-clases/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=dando-clases</link>
		<comments>http://cromo.cda-ie.es/2009/03/12/dando-clases/#comments</comments>
		<pubDate>Thu, 12 Mar 2009 17:49:30 +0000</pubDate>
		<dc:creator>Cubano</dc:creator>
				<category><![CDATA[Cuentos desde la Cripta]]></category>
		<category><![CDATA[Visual Basic 2005]]></category>

		<guid isPermaLink="false">http://cromo.cda-ie.es/2009/03/12/dando-clases/</guid>
		<description><![CDATA[Tengo este blog un poco en stand by. La razón es que he estado dando [impartiendo] clases particulares de VB2005 que se me han llevado el tiempo que dedicaba antes a programar para mí y cacharrear en Windows. Así, los planes de meterme con WPF y también con servicios Windows, así como alguna cosilla de [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify"><span style="font-family: Verdana; font-size: 10pt">Tengo este blog un poco en <em>stand by.</em> La razón es que he estado dando [impartiendo] clases particulares de VB2005 que se me han llevado el tiempo que dedicaba antes a programar para mí y cacharrear en Windows. Así, los planes de meterme con WPF y también con servicios Windows, así como alguna cosilla de Windows Vista han tenido que esperar. Tampoco he podido investigar con calma algunos problemas <em>bonitos</em> que se han planteado en el foro: los días sólo tienen veinticuatro horas.<br />
</span></p>
<p style="text-align: justify"><span style="font-size: 10pt"><span style="font-family: Verdana">Respecto a las clases, no estoy contento. Sólo he tenido un mes, el peor del curso (2º de un FP superior son dos trimestres, así que los finales han sido ahora), así que ha tocado jugar a la defensiva, a verlas venir. Me hubiera gustado tener más tiempo para darle un buen tute a lo básico, pero hubo que entrar directamente con arrays de estructuras. La verdad es que los puñeteros arrays son un fastidio; ya me había acostumbrado a otras colecciones y volver a lo básico duele. Y más si no se puede tirar de </span><span style="font-family: Courier New">ICompare</span><span style="font-family: Verdana"> para ordenar, o propiedades para enlazar a los controles me ha exigido pensar mucho. No poder usar el </span><span style="font-family: Courier New">ValueMember</span><span style="font-family: Verdana"> y el </span><span style="font-family: Courier New">DisplayMember</span><span style="font-family: Verdana"> de un </span><span style="font-family: Courier New">ComboBox</span><span style="font-family: Verdana"> o </span><span style="font-family: Courier New">ListBox</span><span style="font-family: Verdana"> por no poder definir unas </span><span style="font-family: Courier New">Property</span><span style="font-family: Verdana"> en la estructura, para mí, que abuso de eso precisamente, ha sido definitivamente exasperante.<br />
</span></span></p>
<p style="text-align: justify"><span style="font-family: Verdana; font-size: 10pt">Al final, un mes a carajo sacado, mucho array y mucha base de datos y sin tiempo para explicar las cosas como me gustaría. Sólo espero que las horas les hayan sido de provecho y tengan suerte.<br />
</span></p>
<p style="text-align: justify"><span style="font-family: Verdana; font-size: 10pt">Por otra parte, he empezado con WPF y no me entero de <em>ná.</em> Mi reino por un buen libro al respecto, pero no encuentro ninguno. En fin, con paciencia.</span></p>
]]></content:encoded>
			<wfw:commentRss>http://cromo.cda-ie.es/2009/03/12/dando-clases/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>MenuStrip heredado y vista diseño</title>
		<link>http://cromo.cda-ie.es/2009/01/15/menustrip-heredado-y-vista-diseno/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=menustrip-heredado-y-vista-diseno</link>
		<comments>http://cromo.cda-ie.es/2009/01/15/menustrip-heredado-y-vista-diseno/#comments</comments>
		<pubDate>Thu, 15 Jan 2009 16:27:48 +0000</pubDate>
		<dc:creator>Cubano</dc:creator>
				<category><![CDATA[Visual Basic 2005]]></category>
		<category><![CDATA[Visual Basic 2008]]></category>

		<guid isPermaLink="false">http://cromo.cda-ie.es/2009/01/15/menustrip-heredado-y-vista-diseno/</guid>
		<description><![CDATA[Esto es un problema viejo y es fácil encontrar soluciones en Google, pero, bueno, supongo que repetirlo una vez más no viene mal. La situación es la siguiente: tengo un formulario base, a modo de plantilla, que lo uso cuando tengo acceso a datos. Tiene una serie de controles y métodos entre los que se [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify"><span style="font-family: Verdana; font-size: 10pt">Esto es un problema viejo y es fácil encontrar soluciones en Google, pero, bueno, supongo que repetirlo una vez más no viene mal.<br />
</span></p>
<p style="text-align: justify"><span style="font-family: Verdana; font-size: 10pt">La situación es la siguiente: tengo un formulario base, a modo de plantilla, que lo uso cuando tengo acceso a datos. Tiene una serie de controles y métodos entre los que se encuentra un MenuStrip con varios ToolStripMenuItem. Es un control (él y sus ítems) que da problemas con el diseñador de formularios de Visual Studio cuando es un control heredado. Aparece como de sólo lectura y no nos deja trabajar con él y lo digo en serio: no podemos añadir elementos al menú en vista diseño, ni cambiar ninguna propiedad (ni siquiera el texto mostrado) de los ítems que ya tenga. Tenemos que hacerlo directamente en código. Lo que es más incómodo: no podemos controlar un evento de un elemento ya existente.<br />
</span><br />
<span id="more-79"></span></p>
<p style="text-align: justify"><span style="font-family: Verdana; font-size: 10pt">Me explico: tenemos un ToolStripMenuItem llamado mnuNuevo y declarado como Protected en el formulario plantilla y tengo mi formulario heredado (HijoMioForm). Si en HijoMioForm se me ocurre hacer algo como:<br />
</span></p>
<p><span style="font-size: 9pt; font-family: Courier New"><span style="color: blue">Private Sub</span> mnuNuevo_Click() <span style="color: blue">Handles</span> mnuNuevo.Click</span></p>
<p style="text-align: justify"><span style="font-family: Verdana; font-size: 10pt">El programa compilará y funcionará, pero nos podemos olvidar del diseñador de formularios: cascará irremediablemente. Después de buscar soluciones a este problema por ahí (he leído bastantes quejas sobre este caso y otros similares), lo que hice fue declarar el dichoso método en la plantilla como Overridable y luego redefinirlo en HijoMioForm:<br />
</span></p>
<p style="text-align: left"><span style="font-size: 9pt; font-family: Courier New"><span style="color: blue">Protected Overridable Sub</span> mnuNuevo_Click() <span style="color: blue">Handles</span> mnuNuevo.Click</span></p>
<p><span style="font-family: Verdana; font-size: 10pt">Y<br />
</span></p>
<p><span style="font-size: 9pt; font-family: Courier New"><span style="color: blue">Protected Overrides Sub</span> mnuNuevo_Click()</span></p>
]]></content:encoded>
			<wfw:commentRss>http://cromo.cda-ie.es/2009/01/15/menustrip-heredado-y-vista-diseno/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Corrigiendo un… problema de diseño con un evento</title>
		<link>http://cromo.cda-ie.es/2008/12/12/corrigiendo-un%e2%80%a6-problema-de-diseno-con-un-evento/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=corrigiendo-un%25e2%2580%25a6-problema-de-diseno-con-un-evento</link>
		<comments>http://cromo.cda-ie.es/2008/12/12/corrigiendo-un%e2%80%a6-problema-de-diseno-con-un-evento/#comments</comments>
		<pubDate>Fri, 12 Dec 2008 16:34:52 +0000</pubDate>
		<dc:creator>Cubano</dc:creator>
				<category><![CDATA[Programacion]]></category>
		<category><![CDATA[Visual Basic 2005]]></category>
		<category><![CDATA[Visual Basic 2008]]></category>

		<guid isPermaLink="false">http://cromo.cda-ie.es/2008/12/12/corrigiendo-un%e2%80%a6-problema-de-diseno-con-un-evento/</guid>
		<description><![CDATA[Si ya me lo decían: &#8220;no vayas a Z&#8217;ha&#8217;dum&#8220;. Pero yo, ni caso. Me puse a hacer una interfaz MDI tan ricamente para la aplicación de fábrica sin pensarlo con detenimiento (eso también me lo decían, en este caso Coco y Barrio Sésamo, lo de &#8220;tienes que planificar&#8221;, pero, igualmente, ni caso) y ahora me [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify"><span style="font-family: Verdana; font-size: 10pt">Si ya me lo decían: &#8220;no vayas a <a href="http://en.wikipedia.org/wiki/Z%27ha%27dum_(planet)" target="_blank">Z&#8217;ha&#8217;dum</a>&#8220;. Pero yo, ni caso. Me puse a hacer una interfaz MDI tan ricamente para la aplicación de fábrica sin pensarlo con detenimiento (eso también me lo decían, en este caso Coco y Barrio Sésamo, lo de &#8220;tienes que planificar&#8221;, pero, igualmente, ni caso) y ahora me encuentro con lo normal: mucho impedirle cambiar de registro cuando está modificando una pieza, por ejemplo, pero nada le impide irse a otro formulario a trastear allí. Y, como es un luser, lo hará. O sea, que me pueden coger en un renuncio (error de concurrencia en el mejor de los casos) sin necesidad de tener dos lusers, con uno me basta y sobra.<br />
</span></p>
<p style="text-align: justify"><span style="font-family: Verdana; font-size: 10pt">Vale, que no cunda el pánico. Pensemos. O cubro bien todas las posibilidades o me curo en salud y no le dejo tocar al usuario donde no deba. Como soy alumno de mi profe, he optado por lo segundo. Así que quiero que cuando el luser quiera modificar o dar de alta &#8220;algo&#8221; en uno de los formularios, todos los demás se hagan los suecos (disabled). Pregunta: ¿cómo lo hago?<br />
</span><br />
<span id="more-71"></span></p>
<p style="text-align: justify"><span style="font-family: Verdana; font-size: 10pt">Bien, resulta que, ¡oh, casualidad!, casi todos los formularios derivan de un formulario plantilla (cuestión de vagancia), así que se me ocurrió usar un evento compartido en la clase base. El evento se provocará cada vez que cambie el &#8220;estado&#8221; del formulario, por ejemplo, al pulsar el botón de Nuevo o el de Aceptar. Necesito también saber, cuando salte el evento, si ha sido porque he entrado en un modo &#8220;modificar datos&#8221; o en un modo &#8220;ver datos&#8221;, así que necesito un argumento booleano que me lo controle. Vale, al trabajo.<br />
</span></p>
<p style="text-align: justify"><span style="font-size: 10pt"><span style="font-family: Verdana">Empezamos definiendo el tipo de argumentos para el evento. He dicho que necesito un booleano, pero para hacerlo &#8220;según las normas&#8221; he definido una clase </span><span style="font-family: Courier New">ModificandoEventArgs</span><span style="font-family: Verdana"> que hereda de </span><span style="font-family: Courier New">EventArgs</span><span style="font-family: Verdana"> y que, de momento, lo único que tiene importante es una propiedad booleana.<br />
</span></span></p>
<table align="center" bgcolor="#e6e6fa" width="100%">
<tr>
<td>
<pre style="font-family: 'Courier New',Courier,monospace; font-size: 9pt"><span style="color: #0000ff">Public</span> <span style="color: #0000ff">Class</span> ModificandoEventArgs
    <span style="color: #0000ff">Inherits</span> EventArgs
    <span style="color: #0000ff">Private</span> _EstoyModificando <span style="color: #0000ff">As</span> <span style="color: #0000ff">Boolean</span>

    <span style="color: #0000ff">Public</span> <span style="color: #0000ff">Sub</span> <span style="color: #0000ff">New</span>(<span style="color: #0000ff">ByVal</span> estamosModificando <span style="color: #0000ff">As</span> <span style="color: #0000ff">Boolean</span>)
        <span style="color: #0000ff">Me</span>._EstoyModificando = estamosModificando
    <span style="color: #0000ff">End</span> <span style="color: #0000ff">Sub</span>

    <span style="color: #0000ff">Public</span> <span style="color: #0000ff">ReadOnly</span> <span style="color: #0000ff">Property</span> EstamosModificando() <span style="color: #0000ff">As</span> <span style="color: #0000ff">Boolean</span>
        <span style="color: #0000ff">Get</span>
            <span style="color: #0000ff">Return</span> <span style="color: #0000ff">Me</span>._EstoyModificando
        <span style="color: #0000ff">End</span> <span style="color: #0000ff">Get</span>
    <span style="color: #0000ff">End</span> <span style="color: #0000ff">Property</span>
<span style="color: #0000ff">End</span> <span style="color: #0000ff">Class</span></pre>
</td>
</tr>
</table>
<p style="text-align: justify"><span style="font-family: Verdana; font-size: 10pt">Luego declaramos el delegado:<br />
</span></p>
<table align="center" bgcolor="#e6e6fa" width="100%">
<tr>
<td>
<pre style="font-family: 'Courier New',Courier,monospace; font-size: 9pt"><span style="color: #0000ff">Public</span> <span style="color: #0000ff">Delegate</span> <span style="color: #0000ff">Sub</span> ModificandoEventHandler(<span style="color: #0000ff">ByVal</span> sender <span style="color: #0000ff">As</span> <span style="color: #0000ff">Object</span>, _
    <span style="color: #0000ff">ByVal</span> e <span style="color: #0000ff">As</span> ModificandoEventArgs)</pre>
</td>
</tr>
</table>
<p style="text-align: justify"><span style="font-family: Verdana; font-size: 10pt">Y, ya por fin, el evento y el método que lo lanza:<br />
</span></p>
<table align="center" bgcolor="#e6e6fa" width="100%">
<tr>
<td>
<pre style="font-family: 'Courier New',Courier,monospace; font-size: 9pt"><span style="color: #0000ff">Public</span> <span style="color: #0000ff">Shared</span> <span style="color: #0000ff">Event</span> Modificando <span style="color: #0000ff">As</span> ModificandoEventHandler

<span style="color: #0000ff">Protected</span> <span style="color: #0000ff">Overridable</span> <span style="color: #0000ff">Sub</span> OnModificando(<span style="color: #0000ff">ByVal</span> e <span style="color: #0000ff">As</span> ModificandoEventArgs)
    <span style="color: #0000ff">RaiseEvent</span> Modificando(<span style="color: #0000ff">Me</span>, e)
<span style="color: #0000ff">End</span> <span style="color: #0000ff">Sub</span></pre>
</td>
</tr>
</table>
<p style="text-align: justify"><span style="font-family: Verdana; font-size: 10pt">Ya de paso me creo un método para gestionar este evento dentro de la clase base, a ver qué pasa.<br />
</span></p>
<table align="center" bgcolor="#e6e6fa" width="100%">
<tr>
<td>
<pre style="font-family: 'Courier New',Courier,monospace; font-size: 9pt"><span style="color: #0000ff">Protected</span> <span style="color: #0000ff">Overridable</span> <span style="color: #0000ff">Sub</span> EstamosModificando(<span style="color: #0000ff">ByVal</span> sender <span style="color: #0000ff">As</span> <span style="color: #0000ff">Object</span>, _
    <span style="color: #0000ff">ByVal</span> e <span style="color: #0000ff">As</span> ModificandoEventArgs) <span style="color: #0000ff">Handles</span> <span style="color: #0000ff">Me</span>.Modificando
    <span style="color: #0000ff">If</span> sender <span style="color: #0000ff">IsNot</span> <span style="color: #0000ff">Me</span> <span style="color: #0000ff">Then</span>
        <span style="color: #0000ff">Me</span>.Enabled = <span style="color: #0000ff">Not</span> e.EstamosModificando
    <span style="color: #0000ff">End</span> <span style="color: #0000ff">If</span>
<span style="color: #0000ff">End</span> <span style="color: #0000ff">Sub</span></pre>
</td>
</tr>
</table>
<p style="text-align: justify"><span style="font-size: 10pt"><span style="font-family: Verdana">Ya está. ¡Ah, no! Falta lanzar el evento. Pues nada, llamadita a </span><span style="font-family: Courier New">OnModificando</span><span style="font-family: Verdana"> desde el lugar apropiado, concretamente desde el método </span><span style="font-family: Courier New">PrepararForm</span><span style="font-family: Verdana"> que se ejecuta en cada cambio de estado del formulario. Y funciona. A la primera. Ya no me acuerdo cuándo fue la última vez que me funcionó algo a la primera.</span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://cromo.cda-ie.es/2008/12/12/corrigiendo-un%e2%80%a6-problema-de-diseno-con-un-evento/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mover los elementos de un ListBox</title>
		<link>http://cromo.cda-ie.es/2008/11/24/mover-los-elementos-de-un-listbox/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mover-los-elementos-de-un-listbox</link>
		<comments>http://cromo.cda-ie.es/2008/11/24/mover-los-elementos-de-un-listbox/#comments</comments>
		<pubDate>Mon, 24 Nov 2008 17:57:14 +0000</pubDate>
		<dc:creator>Cubano</dc:creator>
				<category><![CDATA[Programacion]]></category>
		<category><![CDATA[Visual Basic 2005]]></category>
		<category><![CDATA[Visual Basic 2008]]></category>

		<guid isPermaLink="false">http://cromo.cda-ie.es/2008/11/24/mover-los-elementos-de-un-listbox/</guid>
		<description><![CDATA[Hay veces que lo que parece más simple da unos dolores de cabeza terribles. Estaba yo, feliz y despistado, queriendo montar un listbox y dos botoncitos, uno con una flecha para arriba y otro con una flecha para abajo, de forma que, al pulsar el botoncito con la flecha hacia arriba, el elemento seleccionado en [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify"><span style="font-family: Verdana; font-size: 10pt">Hay veces que lo que parece más simple da unos dolores de cabeza terribles. Estaba yo, feliz y despistado, queriendo montar un listbox y dos botoncitos, uno con una flecha para arriba y otro con una flecha para abajo, de forma que, al pulsar el botoncito con la flecha hacia arriba, el elemento seleccionado en el listbox intercambie su posición con el que tiene encima (<em>vulgo,</em> suba) y cuando pulse sobre el botoncito con la flecha para abajo… en fin, creo que os lo imagináis.<br />
</span></p>
<p style="text-align: justify"><span style="font-family: Verdana; font-size: 10pt">Pues tiene su aquél. Bueno, vale, no tiene mucho &#8220;aquél&#8221; pero me ha costado un buen rato dar con la tecla. O sea, sacar el elemento, borrarlo, insertarlo en su nueva posición. Ahora mismo no estoy seguro, pero creo haber hecho algo parecido en VB6 sin necesidad de dar tantos pasos. Por ejemplo, el código del <em>click</em> del botón de subir quedaría más o menos así:<br />
</span></p>
<p style="text-align: justify">
<table align="center" bgcolor="#e6e6fa" width="90%">
<tr>
<td>
<pre style="font-family: 'Courier New',Courier,monospace; font-size: 9pt"><span style="color: #0000ff">Dim</span> MiMecanizado <span style="color: #0000ff">As</span> MecanizadoPieza
<span style="color: #0000ff">Dim</span> i <span style="color: #0000ff">As</span> <span style="color: #0000ff">Integer</span> = <span style="color: #0000ff">Me</span>.lstOrdenMecanizado.SelectedIndex
<span style="color: #0000ff">If</span> i &gt; 0 <span style="color: #0000ff">Then</span>
    MiMecanizado = <span style="color: #0000ff">TryCast</span>(<span style="color: #0000ff">Me</span>.lstOrdenMecanizado.SelectedItem, _
                          MecanizadoPieza)
    <span style="color: #0000ff">If</span> MiMecanizado <span style="color: #0000ff">Is</span> <span style="color: #0000ff">Nothing</span> <span style="color: #0000ff">Then</span> <span style="color: #0000ff">Exit</span> <span style="color: #0000ff">Sub</span>
    <span style="color: #0000ff">Me</span>.lstOrdenMecanizado.Items.RemoveAt(i)
    <span style="color: #0000ff">Me</span>.lstOrdenMecanizado.Items.Insert(i - 1, MiMecanizado)
    <span style="color: #0000ff">Me</span>.lstOrdenMecanizado.SelectedIndex = i - 1
<span style="color: #0000ff">End</span> <span style="color: #0000ff">If</span></pre>
</td>
</tr>
</table>
<p style="text-align: justify"><span style="font-family: Verdana; font-size: 10pt">Donde MecanizadoPieza es una clase que incluye un campo Descripción (DisplayMember) y un campo Id (ValueMember) y lstOrdenMecanizado es el listbox de marras.<br />
</span></p>
<p style="text-align: justify"><span style="font-family: Verdana; font-size: 10pt">Si alguien lo encuentra útil, pues mejor.</span></p>
]]></content:encoded>
			<wfw:commentRss>http://cromo.cda-ie.es/2008/11/24/mover-los-elementos-de-un-listbox/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

