Ene 23
A día de hoy yo no tendría duda sobre cual opción elegir, opción que no tiene que ser mejor que la otra. Realmente, yo enfocaría el dilema mas bien desde el punto de vista de aplicación web AJAX (orientada al servicio), o aplicación web convencional (.net por supuesto), con sus postbacks (o callbacks) y sus Update Panels. (Debería de estar penalizado el uso del control Update Panel
)
Ajax Control Toolkit
Esta opción nos deja en el ámbito de una aplicación web .Net tradicional con controles de servidor, por lo que seguramente tendremos el grueso de la aplicación en el servidor. Con esto no quiero decir que no sea posible tener lógica en cliente, pero si que resulta bastante engorroso trabajar con los controles del ajax control tolkit con javascript. Por otro lado no debemos olvidar que son controles de servidor, y que son muy fáciles de usar, pero que cuando se complica el desarrollo y la web, no se por qué, pero el trabajo se complica. Otro punto es el peso de las librerías, puf, te echan para atrás. Y un punto no menos importante, si por ejemplo tenemos que hacer una modificación de un Extender, digamos por ejemplo el AutoCcomplete, tendremos que generar un nuevo build y añadir la nueva referencia, y rezar por tener problemas de versiones a la hora de realizar el deploy en el servidor. A modo de anectdota, mencionar que un proyecto en el que estuve trabajando, en cual teniamos un Auto Complete Extender customizado, tuvimos problemas de referencias cruzadas entre versiones de librerias, y con el timestamp del build generado del Extender con la fecha del servidor. Hora del Build X , hora del Servidor de despliegue X-6. Solución, cambiar la hora a la maquina de build y realizar un nuevo build con un timestamp de fecha menor que la hora del servidor web.
Leer el artículo completo »
Ene 17
La mayoría de las veces cuando se define la arquitectura de una aplicación web solo se tiene en cuenta la parte servidor, como si el lado cliente no fuera importante o no existiera. Es verdad que en cliente disponemos de un lenguaje interpretado (no compilado), lo cual hace si cabe un poquito mas complicado el desarrollo, al no disponer de las ventajas del pre compilado que nos ofrece Visual Studio. Además, el ordenado del código debería ser un factor importante, ya que la tendencia es tener un único fichero o script de código Javascritp, y esto siempre comienza siendo unas pocas líneas para unas cuantas validaciones y va creciendo paulatinamente debido a la no planificación de la arquitectura en cliente o a nuevos requerimientos.
Atajar esto no es fácil, y el artículo no define ningún modelo de arquitectura, pero si unas cuantas pautas de buena conducta que nos ayuden a tener un condigo algo mas limpio y ordenado.
Leer el artículo completo »
Dic 13
Que divertido es Javascript, y como echaba de menos un proyecto como el de ahora, casi todo en cliente, pero a pelo sin esas maravillosas facilidades que aporta Silverlight...., bueno algunas si, haciendo uso de Framework de AJAX de Microsot. El contenido de este Post es el típico conocimiento que en mi caso nunca me acuerdo y tengo que echar manos de algun proyecto para recuperarlo. Nunca Mais
JAVASCRIPT:
-
var xPos, yPos;
-
var prm = Sys.WebForms.PageRequestManager.getInstance();
-
prm.add_beginRequest(BeginRequestHandler_scroll);
-
prm.add_endRequest(EndRequestHandler_scroll);
-
-
function BeginRequestHandler_scroll(sender, args) {
-
if (document.getElementById('gridClientScroll')) {
-
var item = document.getElementById('gridClientScroll');
-
-
xPos = item.scrollLeft;
-
yPos = item.scrollTop;
-
}
-
}
-
function EndRequestHandler_scroll(sender, args) {
-
-
if (document.getElementById('gridClientScroll')) {
-
var item = document.getElementById('gridClientScroll');
-
-
item.scrollLeft = xPos;
-
item.scrollTop = yPos;
-
}
-
}
El código creo que no necesita explicación. Simplemente obtenemos los valores X e Y de elemento con Scroll que queremos persistir después del postback y lo guardamos, para posteriormente, volverlos a establecer. Para ello, añadimos un manejador de eventos para antes y después del postback asíncrono, de manera que cada uno de ellos ejecute la función que le especificamos.
Oct 17
Simulando al amigo Alejandro (maaestro web de Chuletilla`s Web), aqui va una mini entrada.
Es posible encontrarse en la tesitura de tener un formulario en el que por motivos de dimensiones tengamos un control TextBox con un width predeterminado en el que el número de caracteres permitidos tengan una longitud mayor que el width del control, por lo que siempre veremos el final del texto introducido en vez del comienzo de este.
Extensión del control TextBox.
La solución no es compleja, y consiste en crear un nuevo control TextBox que añada el comportamiento requerido, extendiendo la clase TextBox. Solo tenemos que controlar el evento LostFocus del control.
C#:
-
public class TextBoxExtension : TextBox
-
{
-
public TextBoxExtension()
-
{
-
this.
LostFocus +=
new RoutedEventHandler
(TextBoxExtension_LostFocus
);
-
}
-
-
void TextBoxExtension_LostFocus(object sender, RoutedEventArgs e)
-
{
-
//Marcamos el inicio del cursor
-
this.SelectionStart = 0;
-
this.SelectionLength = 0;
-
}
-
}
Oct 10
El hecho de establecer los datos en los formularios de forma declarativa, es una forma de obtener un codigo limpio. Si bien es verdad que intentar definir toda la interfaz declarativamente puede conllevar complicaciones en el desarrollo, una vez que se consigue uno se queda satisfecho. Una pena que no dispongamos en Silverlight 3 de los comandos que si podemos encontrar en WPF, los cuales nos permitirían establecer el control de eventos sin hacer uso del codebehind.
Un punto interesante del Data Binding, es la posibilidad de establecer el valor de las propiedades de los controles en función de los valores de otras propiedades de otros controles.
Como ejemplo veamos como las cajas de texto buscan su valor en función del objeto seleccionado en un combobox, y como podemos establecer el tamaño de fuente de los TextBoxes mediante un control Slider.
XML:
-
<StackPanel x:Name="LayoutRoot" Orientation="Horizontal" VerticalAlignment="Top">
-
<Border Background="#D3DAED" CornerRadius="3" Margin="2" Padding="2" BorderThickness="1" BorderBrush="#A9AFCC" Width="200" Height="40" VerticalAlignment="Top">
-
<StackPanel Orientation="Horizontal">
-
<TextBlock Text="Modelo" Height="30" Width="80" VerticalAlignment="Center"/>
-
<ComboBox x:Name="cbModelo" Height="30" Width="100" VerticalAlignment="Center"
-
ItemsSource="{Binding Path=Coches}"
-
DisplayMemberPath="Modelo"
-
/>
-
</StackPanel>
-
</Border>
-
<Border Background="#D3DAED" CornerRadius="3" Margin="2" BorderThickness="1"
-
BorderBrush="#A9AFCC" Width="200" VerticalAlignment="Top">
-
<StackPanel Orientation="Vertical" Margin="10,2" HorizontalAlignment="Left">
-
<!-- La propiedad Text de los TextBoxes es obtenida
-
del objeto seleccionado en el combobox -->
-
<TextBlock Text="{Binding SelectedItem.Marca, ElementName=cbModelo}"
-
Height="40" Width="180" FontSize="{Binding Value, ElementName=sliderSize}"/>
-
<TextBlock Text="{Binding SelectedItem.Cilindrada, ElementName=cbModelo}"
-
Height="40" Width="180" FontSize="{Binding Value, ElementName=sliderSize}"/>
-
<TextBlock Text="{Binding SelectedItem.Combustible, ElementName=cbModelo}"
-
Height="40" Width="180" FontSize="{Binding Value, ElementName=sliderSize}"/>
-
</StackPanel>
-
</Border>
-
</StackPanel>
-
<Border Background="#D3DAED" CornerRadius="3" Margin="2" Padding="2" BorderThickness="1"
-
BorderBrush="#A9AFCC" Width="400" Height="40" VerticalAlignment="Top" HorizontalAlignment="Left">
-
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" Margin="2">
-
<TextBlock Text="Tamaño de Fuente" Height="30" Width="120" VerticalAlignment="Center" />
-
<!-- La Propiedad Value del control Slider se puede establcer mediante una caja de texto-->
-
<Slider x:Name="sliderSize" Minimum="10" Maximum="34" Value="{Binding Text,
-
ElementName=txtFont, Mode=TwoWay}" SmallChange="1" LargeChange="1"
-
Width="100" VerticalAlignment="Center"></Slider>
-
<!-- El valor de la caja de texto es obtenida de la propiedad Value del control Slider-->
-
<TextBox x:Name="txtFont" Text="{Binding Value, ElementName=sliderSize}"
-
Height="30" Width="40" VerticalAlignment="Center" />
-
</StackPanel>
-
</Border>
-
</StackPanel>
-
Si nos fijamos en el XAML, observaremos que en el Binding de las propiedades añadimos una nueva etiqueta ElementName, etiqueta que especifica el objeto origen del cual vamos a obtener el valor. El valor será el que proporcione la propiedad de ese objeto y que establecemos en el Binding. Por ejemplo, para las cajas de texto que muestran la información del objeto Coche, indicamos que el objeto origen es el combo box, y que el valor a mostrar es una propiedad del objeto seleccionado.
Text="{Binding SelectedItem.Cilindrada, ElementName=cbModelo}"
Veamos el ejemplo en funcionamiento:
Sep 27
Es verdad que tenía un poco abandonado el blog, y puede parecer que Silverlight también. Lo primero es cierto, pero lo segundo todo lo contrario, ya que en este tiempo he estado asignado a varios proyectos Silverlight. Con un poco de suerte cuaja este nuevo cacharro de Microsoft y las empresas se toman en serio esta nueva tecnología.
Y ahora, cuando más de uno está destripando PRISM, como por ejemplo el compañero Braulio Diez, que por cierto ha sido nombrado recientemente MVP en Silverlight, llega el menda con un post de MVVM. Desde aquí, y antes de continuar, dar mi más sincera enhorabuena a Braulio por este reconocimiento – no sé realmente cuanta gente opta a estos premios, pero si estoy seguro que nadie se lo merecía más que él. Todo un lujo trabajar a su lado. Congratulations (es que se empeña en que escriba en ingles
).
MCV, MVP, y ahora MVVM, Model View ViewModel. Aunque ya se ha dicho y escrito mucho sobre este modelo, voy a intentar dar una visión más práctica, después de haber aplicado el modelo en diversas aplicaciones.
Leer el artículo completo »
Ago 16

Para que no digan que solo de Silverlight vive el hombre, aquí va una de Android.
Por diferentes razones seguro que a más de uno le gustaría cambiar la cuenta de gmail inicial con la que registó su Magic.
Pues bien, es posible cambiar la cuenta con la que hemos registrado nuestra Magic sin tener que volver al estado inicial y tener que reinstalar todas las aplicaciones que ya tuvieramos instaladas. Para ello lo que tenemos que hacer es ir a Ajustes / Aplicaciones / Administrar Aplicaciones y borrar los datos de Google Apps.
Despues de esto android nos volverá a pedir una nueva cuenta de gmail. Es posible que tengamos que ejecutar alguna aplicacion Google, como por ejemplo Google Talk, para que comience el proceso de registro.
May 01
Seguramente que a más de uno le resultarán obvios los puntos mencionados en este post para mejorar el performance de una aplicación web .Net, y reducir el peso de una página, pero nunca esta de mas recordarlos.El que escribe sin ir más lejos los tuvo que aplicar no hace mucho tiempo cuando un cliente solicitó el análisis de una aplicación para intentar disminuir los tiempos de carga.
Imaginemos el siguiente escenario:
Un formulario con un elevado número de componentes, entre ellos muchos dropdownlist anidados en un DataList. Los dropdownlist son cargados en el servidor, y tenemos varios tipos de combos en cada fila diferenciados por los valores que contienen, y estos se repiten en cada una de las filas del DataList.
Pues si por ejemplo, tenemos 4 combos distintos por fila y el Datalist contiene 20 filas, quiere decir que enviamos 20 veces el contenido de cada tipo de combos desde el servidor al cliente (20x4=80 contenidos repetidos). Además tenemos elementos en el formulario, simplemente para mostrar información, sin nunguna funcionalidad asociada.
Bueno con un escenario asi de simple podemos aplicar los siguientes trucos:
- Sustituir aquellos elementos que no tienen funcionalidad asociada por etiquetas que son los elementos más ligeros capaces de mostrar información. De esta manera eliminamos una sobrecarga del ViewState.
- No cargar los DropDownList en el lado del servidor. En vez de establecer los valores desde .Net, inyectar codigo javascript que defina variables que contengan arrays bidimensionales con la tupla valor y texto que definan cada una de las opciones del combo. Luego, desde cliente, en el onLoad del formulario, cargamos cada unos de los combos con los valores de las variables.
- Eliminar los espacios en blanco que se crean al generar el HTML de la página. Para ello, desde la misma página, podemos sobrescribir el método Render que es justo el último punto desde donde podemos modificar el HTML antes de enviarlo al cliente.
Ahora veamos un ejemplo de código que sobrescribe el método Render de una página.
C#:
-
protected override void Render(HtmlTextWriter writer)
-
{
-
HtmlTextWriter swHtmlText =
new HtmlTextWriter
(new System.
IO.
StringWriter());
-
-
base.Render(swHtmlText);
-
-
//Obtenemos el HTML de la pagina
-
string strHtml = swHtmlText.InnerWriter.ToString();
-
-
//Eliminamos todos los espacios en blanco que hay
-
//entre los controles
-
strHtml = Regex.Replace(strHtml, "^\\s+<", " <", RegexOptions.Multiline);
-
strHtml = Regex.Replace(strHtml, ">\\s+<", "> <", RegexOptions.Multiline);
-
-
//Escribimos el nuevo HTML limpio
-
writer.Write(strHtml.Trim());
-
-
}
Mar 21
Como complemento al articulo en el que explicabamos como generar / grabar un fichero en Silverlight, el uso del clipboard puede sernos también de utilidad. La solución, aunque no optima porque solo funciona en Internet Explorer, es simpe.
C#:
-
private void btnSetTo_Click(object sender, RoutedEventArgs e)
-
{
-
ScriptObject clipboard = (ScriptObject)HtmlPage.Window.GetProperty("clipboardData");
-
-
if (clipboard != null)
-
clipboard.Invoke("setData", "text", txtCaja.Text);
-
}
-
-
private void btnGetFrom_Click(object sender, RoutedEventArgs e)
-
{
-
ScriptObject clipboard = (ScriptObject)HtmlPage.Window.GetProperty("clipboardData");
-
-
if (clipboard != null)
-
txtCaja.Text = clipboard.Invoke("getData", "text").ToString();
-
}
-
Feb 28
Creo que este problema es algo frecuente. Intentamos cerrar una pestaña desde una aplicación .Net. Esto simplemente es un "window.close();" y todo funciona correctamente desde Internet explorer 6, pero si intentamos lo mismo en IE7 salta un popup para preguntarnos si realmente queremos cerrar la pestaña.
La solucion es sencilla. Desde la pagina que queremos cerrar redirigimos nuestra aplicación hacia una página nueva que simplente tendrá el siguiente script:
HTML:
-
<!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>
-
-
-
<script language=javascript type="text/javascript">
-
window.open('', '_self');
-
window.close();
-
</script>
-
</body>
-
</html>
La explicación parece ser que es por motivos de seguridad. No se permite cerrar una pestaña desde Javascript que no ha sido abierta desde Javascript. Con este código simplemente engañamos al navegador haciendole creer que la pagina ha sido abierta desde cliente y luego la cerramos.
Un Bug?
Recent Comments