Después de una semana de vacaciones disfrutando en las islas afortunadas, probando la playa mientras la península se helaba, vuelvo a la dura realidad y aquí os dejo los enlaces del día
Mes: enero 2010
Enlaces Interesantes WPF/Silverlight 24-01-2010
Os dejo una pequeña colección
Este ultimo es una joya un Hands-On-Lab de aplicaciones LOB con WCF Ria Services (Swiss MSDN)
Silverlight 4 Nuevas Caracteristicas – Paso de credenciales ClientHttp
En el post anterior vimos como acceder a un servicio web que estuviese en otro dominio sin los ficheros Crossdomain.xml o ClientAccessPolicy.xml, en el ejemplo el acceso era a Twitter pero a los tweets públicos, que pasa si quiero acceder a mis tweets?. Esto es posible en Silverrlight 4 ya que se ha habilita el paso de credenciales vía hhtp.
El código de la anterior aplicación nos quedaría en este caso de la siguiente manera
1: WebRequest.RegisterPrefix("http://", System.Net.Browser.WebRequestCreator.ClientHttp);
2: string userTimeLine = "http://twitter.com/statuses/user_timeline/" + UserNameTextBox.Text + ".xml";
3: WebClient client = new WebClient();
4: client.Credentials = new NetworkCredential(UserNameTextBox.Text, PasswordTextBox.Password);
5: client.UseDefaultCredentials = false;
6: client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(user_DownloadStringCompleted);
7: client.DownloadStringAsync(new Uri(userTimeLine, UriKind.Absolute));
Importante es la linea client.UseDefaultCredentials = false; ya que si no ponemos a false la propiedad UseDefaultCredentials Silverlight pasara las credenciales del usuario logeado en la maquina (NTLM).
A probarlo!!!!
Silverlight 4 Nuevas Caracteristicas – Acceso a servicios cross-domain
En las anteriores versiones cuando queríamos consumir un servicio web que no estuviese en nuestro dominio debían estar los ficheros Crossdomain.xml o ClientAccessPolicy.xml en el raíz del Sitio Web donde estuviese el Servicio a consumir por Silverlight.
La estructura de este fichero se puede consultar aquí: Cross-domain policy file specification
Silverlight hace uso de este tipo de ficheros de la misma forma que Flash, además que incluye también un nuevo tipo de fichero clientaccesspolicy.xml. Silverlight primero tratará de descargar este fichero y si no existe, tratará de descargar crossdomain.xml.
Generalmente los servicios web típicos como flickr, twitter.. tienen esos ficheros, por ejemplo
Pero que pasaba si no existían esos ficheros, no podía acceder desde Silverlight?
Para este caso existen alternativas.
Una de ellas sería hacer uso de la API de integración con el navegador para acceder al objeto JavaScript XMLHttpRequest y consultar a través de él el servicio en cuestión. XMLHttpRequest no hace esta comprobación de ninguno de estos ficheros Xml, aunque podríamos tener problemas con otras características de seguridad que implementen los navegadores para evitar XSS.
Otra alternativa es hacer que nuestro servidor nos haga de Proxy con el servicio o recurso del otro dominio. El problema de esta solución es la posible sobrecarga de nuestro servidor.
Silverlight 4 nos va a permitir acceder a servicios que estén fuera de nuestro dominio aunque no tengan estos ficheros siempre y cuando se ejecuten out-of-browser y con confianza total (full-trusted)
En el ejemplo que vamos a hacer utilizaremos el servicio web de twitter en este caso el código de acceso a los datos sería
1: public void GetTwitterPublic()
2: {
3: string publicTimeLine = "http://twitter.com/statuses/public_timeline.xml";
4: WebClient client = new WebClient();
5: client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
6: client.DownloadStringAsync(new Uri(publicTimeLine, UriKind.Absolute));
7: }
8:
9: void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
10: {
11: XDocument document = XDocument.Parse(e.Result);
12: twitterData = (from status in document.Descendants("status")
13: select new Tweet
14: {
15: Message = status.Element("text").Value.Trim(),
16: User = status.Element("user").Element("name").Value.Trim()
17: }).ToList();
18:
19: PublicTimeLineListBox.ItemsSource = twitterData;
20: }
Accedemos al xml de twiiter y con linq lo convertimos a nuestra clase, el ejemplo quedaría que como podéis ver no he hecho ningún esfuerzo en el diseño
Enlaces Interesantes WPF/Silverlight 22-01-2010
Hola vengo con los enlaces interesantes de hoy pero quisiera resaltar uno y establecer un pequeño debate sobre la nueva utilidad de Silverlight 4 que nos permite interactuar con COM+. En esta sección de enlaces se encuentra el articulo de Mike Taulty con el que estoy totalmente de acuerdo, no me parece un acierto romper la interoperabilidad de plataformas, con esta funcionalidad parece que Microsoft enfoca Silverlight a Windows (lo cual es lógico), pero una gran atracción por parte de los clientes es cross-browser cross-plataforms y con la salida de Silverlight 4 esto se rompe.
Además es muy interesante el articulo de Justin donde te da una idea de lo que puedes hacer con COM en la maquina local (una pasada), hasta que no lei el articulo para mi la integración de Silverlight se reducía a Office pero me ha abierto nuevas posibilidades.
Espero vuestras opiniones
Silverlight 4 Nuevas Características- Botón Derecho del Ratón
Una de las funcionalidades mas demandas por los desarrolladores de Silverlight era soporte al botón derecho del ratón para mostrar menús contextuales. Silverlight 4 si soporta ahora el botón derecho del ratón, este esta implementado en la clase UIElement en los eventos MouseRightButtonDown y MouseRightButtonUp a estos eventos les llega el parámetro MouseButtonEventArgs el cual es usado con el click del botón izquierdo.
Cuando pulsamos con el botón izquierdo por defecto nos muestra el menú de Silverlight para bloquear este menú debemos de recoger el evento MouseRightButtonDown y poner e.Handled=true, de esta manera el menú por defecto no se muestra y ya podemos mostrar nuestro menú contextual en el evento MouseLeftButtonUp.
Por ejemplo
private void imgTree_MouseRightButtonDown(object sender, MouseButtonEventArgs e) { e.Handled = true; }
private void imgTree_MouseRightButtonUp(object sender, MouseButtonEventArgs e) { Image image = sender as Image; if (image != null) { ContextMenu contextMenu = new ContextMenu(PrintCanvas, image); contextMenu.Show(e.GetPosition(LayoutRoot)); } }
En nuestro caso la clase ContextMenu hereda de Dialog, porque mostraremos un dialogo y su código
public class ContextMenu:Dialog { private Image imageToDelete; private Canvas canvas; public ContextMenu(Canvas canvas, Image image) { this.canvas = canvas; imageToDelete = image; } protected override FrameworkElement GetContent() { Grid grid = new Grid() { Width = 100, Height = 30 }; Border border = new Border() { BorderBrush = new SolidColorBrush(Colors.Black), BorderThickness = new Thickness(1), Background = new SolidColorBrush(Colors.LightGray) }; grid.Children.Add(border); TextBlock imageDeleteTextBlock = new TextBlock() { Text = "Borrar imagen", VerticalAlignment=VerticalAlignment.Center}; imageDeleteTextBlock.MouseLeftButtonUp += (s, args) => { if (canvas != null && imageToDelete != null) { canvas.Children.Remove(imageToDelete); } }; grid.Children.Add(imageDeleteTextBlock); return grid; } protected override void OnClickOutside() { Close(); } }
También podría haber sido un PopUp en vez de un dialogo
Scrolling en WPF como el IPhone para ItemsControl
Uno de los gadgets que mas me gusta es el iPhone sobre todo por su interfaz y me suelo fijar mucho en el para implementarlas en WPF, en esta ocasión he reproducido (todavía esta en versión alfa) el scrolling del IPhone, había visto el implementado por Kevin Marshall para los ListBox donde podéis ver un video de su manejo aquí, pero para mi le falta algo que le da naturalidad al iphone que es el rebote y que vuelva a la posición de inicio o de final automáticamente, así que decidí implementar lo pero en vez de para listbox en este caso para ItemsControl , por lo que el control contiene interiormente un ItemsControl .
Por ahora solo tiene dos propiedades, una es la fuente de datos que en este caso he puesto IEnumerable (seguramente en futuras versiones ponga ObservableCollection) y la segunda propiedad es el DataTemplate que va a utilizar el ItemsControl, mas adelante pondré el rozamiento, aceleración…..
Os dejo un video de un ejemplo de como funciona, si os fijáis primero muestro una animación intentando indicar al usuario como funciona, luego desaparece para que el usuario peuda ver completamente el control
El código fuente lo podéis descargar de
En la siguiente versión (cuando saque tiempo) mi idea es que se muestre una barra de scroll parecida a la del iphone
Silverlight 4 Nuevas Características – NotificationWindow
Una nueva característica que se va incluir en Silverlight 4 es NotificationWindow que nos va a permitir mostrar una venta al estilo a las notificaciones de Outlook en la parte inferior a la izquierda (En Mac saldría en la parte superior). Estas notificaciones solo aparecerán en las aplicaciones out-of-browser, asi que debemos de configurar nuestra aplicación Silverlight para esta característica
Una vez hecho esto vamos a empezar a realizar nuestra aplicación, lo primero es comprobar que que nuestra aplicación esta instalada o no en el equipo, si no esta instalada le mostraremos un botón para instalarla y en el caso de estar instalada le diremos que debe ejecutarla desde el escritorio.
El código pararealizar estas comprobaciones es
1: public MainPage()
2: {
3: InitializeComponent();
4: Loaded += new RoutedEventHandler(MainPage_Loaded);
5: }
6:
7: void MainPage_Loaded(object sender, RoutedEventArgs e)
8: {
9: #region Running State/Installer Checks
10:
11:
12: if (App.Current.InstallState == InstallState.Installed)
13: {
14: InstallButton.Visibility = Visibility.Collapsed;
15: }
16: else
17: {
18: CustomNotificationButton.Visibility = Visibility.Collapsed;
19: return;
20: }
21:
22:
23: if (!App.Current.IsRunningOutOfBrowser)
24: {
25: WarningText.Visibility = Visibility.Visible;
26: CustomNotificationButton.Visibility = Visibility.Collapsed;
27: }
28: #endregion
29: }
De manera que si no esta instalada le mostramos al usuario
Una vez que este instalada al usuario se le muestra la aplicación, en nuestro caso
Para mostrar la notificación utilizaremos la clase NotificationWindow, esta clase tiene la propiedad Content de tipo FrameWorkElement donde le pasaremos nuestro control de notificaciones, realmente lo que tiene este control es un contenedor donde mostrara el control que le pasemos a la propiedad Content.
Para mostrar la notificación llamaremos al método Show, este tiene un para el tiempo que se tiene que metro que es la duración en milisegundos que se mostrara la notificación
En nuestro caso
1: private void CustomNotificationButton_Click(object sender, RoutedEventArgs e)
2: {
3: NotificationWindow notificationWindow = new NotificationWindow();
4: notificationWindow.Width = 300; notificationWindow.Height = 80;
5: notificationWindow.Content = new TextBlock() { Text = "Probando, probando.." };
6: notificationWindow.Show(10000);
7: }
El resultado:
Un poco fea, pero bueno como lo que pasamos es un control podemos generarla nosotros y aunque esta no es ninguna maravilla es un ejemplo hecho en 5 minutos, lo primero es crear un control como por ejmplo
1: <Grid x:Name="LayoutRoot">
2:
3: <Border x:Name="Frame" Width="300" Height="100" Background="LightYellow">
4:
5: <StackPanel Orientation="Vertical">
6:
7: <Border Width="290" Height="24" CornerRadius="4" Margin="2,4,2,4">
8:
9: <Border.Background>
10:
11: <LinearGradientBrush StartPoint="0.5,0.0"
12:
13: EndPoint="0.5,1.0">
14:
15: <GradientStop Offset="0.2" Color="#FF1C68A0" />
16:
17: <GradientStop Offset="1.0" Color="#FF54A7E2" />
18:
19: </LinearGradientBrush>
20:
21: </Border.Background>
22:
23: <Border.Effect>
24:
25: <DropShadowEffect BlurRadius="4" ShadowDepth="4"
26:
27: Opacity="0.4" />
28:
29: </Border.Effect>
30:
31: <TextBlock Text="{Binding Title, Mode=OneWay}" FontSize="12"
32:
33: FontWeight="Bold" Foreground="White" Margin="4" />
34:
35: </Border>
36:
37: <StackPanel Orientation="Horizontal">
38:
39:
40:
41: <TextBlock Width="240" Text="{Binding Content, Mode=OneWay}"
42:
43: FontSize="11" Foreground="#FF202020" TextWrapping="Wrap"
44:
45: Margin="4" />
46:
47: </StackPanel>
48:
49: </StackPanel>
50:
51: </Border>
52:
53: </Grid>
Para llamarlo ahora
1: private void CustomNotificationButton_Click(object sender, RoutedEventArgs e)
2: {
3: NotificationWindow notificationWindow = new NotificationWindow();
4: Notificacion n = new Notificacion();
5: n.Title = "Titulo de la notificación";
6: n.Content = "Aqui va el mensaje de la notificación";
7: MiNotificacion mi = new MiNotificacion();
8: mi.DataContext=n;
9: notificationWindow.Width = 300; notificationWindow.Height = 80;
10: notificationWindow.Content =mi;
11: notificationWindow.Show(10000);
12: }
El resultado no es ninguna maravilla pero es el camino para que realicéis el vuestro
El código fuente esta en
Enlaces Interesantes WPF/Silverlight 16-01-2010
Los de día
- AutoMagically Implementing INotifyPropertyChanged (Justin Angel)
- Converting Hexadecimals to Colors in code for Silverlight and Flash to Silverlight Guide – Graphics, Images and Display List (Adam Kinney)
- WPF WebBrowser and JavaScript interaction (Oren Eini)
- Silverlight: SketchFlow (Deborah Kurata)
- Quick tip: Finding Silverlight 4 documentation fast (Laurent Bugnion)
- A Field Guide to WPF Presentation Patterns and Introducing MicroModels (Paul Stovell)
- Silverlight: Centering a RadioButton (Deborah Kurata)
- Silverlight Isolated Storage Paths on Windows and MacOS (Frank La Vigne)
- Aspen – A sample app using Silverlight 4 and .Net 4.0 – part 1 of X and Aspen – A sample app using Silverlight 4 and .Net 4.0 – part 2 of X – MEF and EF 4 code-only (Fredrik Normén)
- Prism 4.0 (Blaine Wastell)
- Silverlight, MVVM and Validation Part III (Josh Twist)
- IIS Smooth Streaming Player Development Kit Beta 2 released (Silverlight Team)
- Silverlight 3 API listing in one big text file and Silverlight 4 beta API listing in one big text file (Nick Kramer)
Silverlight 4 Nuevas Características – StringFormat DataBinding
El Databinding de esta nueva versión se parece cada vez mas al databinding de WPF siendo cada vez mas potente. En las versiones anteriores vimos que si queríamos formatear una fecha o un decimal debíamos utilizar converters de los que ya hable en este post. En esta versión se ha implementado la propiedad StringFormat en los Binding.
Imaginemos que tenemos la clase Persona
1: public class Persona
2: {
3: public string Nombre { get; set; }
4: public string Apellidos { get; set; }
5: public DateTime FechaNacimiento { get; set; }
6: public string CorreoElectronico { get; set; }
7: public string Direccion { get; set; }
8: }
Ahora el Xaml en el que mostramos los datos sería
1: <Grid x:Name="LayoutRoot" Background="White" Height="160" VerticalAlignment="Top" Width="320">
2: <Grid.ColumnDefinitions>
3: <ColumnDefinition></ColumnDefinition>
4: <ColumnDefinition></ColumnDefinition>
5: </Grid.ColumnDefinitions>
6: <Grid.RowDefinitions>
7: <RowDefinition></RowDefinition>
8: <RowDefinition></RowDefinition>
9: <RowDefinition></RowDefinition>
10: <RowDefinition></RowDefinition>
11: <RowDefinition></RowDefinition>
12: <RowDefinition></RowDefinition>
13: </Grid.RowDefinitions>
14:
15: <TextBlock x:Name="FirstNameTextBlock" Grid.Row="0" Grid.Column="0" Text="Nombre:" FontWeight="Bold">
16: </TextBlock>
17: <TextBlock x:Name="FirstNameValueTextBlock" Grid.Row="0" Grid.Column="1" Text="{Binding Nombre}" ></TextBlock>
18: <TextBlock x:Name="LastNameTextBlock" Grid.Row="1" Grid.Column="0" Text="Apellidos:" FontWeight="Bold"></TextBlock>
19: <TextBlock x:Name="LastNameValueTextBlock" Grid.Row="1" Grid.Column="1" Text="{Binding Apellidos}"></TextBlock>
20: <TextBlock x:Name="AddressTextBlock" Grid.Row="3" Grid.Column="0" Text="Direccion:" FontWeight="Bold"></TextBlock>
21: <TextBlock x:Name="AddressValueTextBlock" Grid.Row="3" Grid.Column="1" Text="{Binding Direccion, TargetNullValue=Desconocida}" ></TextBlock>
22: <TextBlock x:Name="BirthDateTextBlock" Grid.Row="2" Grid.Column="0" Text="Fecha Nacimiento:" FontWeight="Bold"></TextBlock>
23: <TextBlock x:Name="BirthDateValueTextBlock" Grid.Row="2" Grid.Column="1" Text="{Binding FechaNacimiento, StringFormat=dd/MM/yyyy}"></TextBlock>
24: <TextBlock x:Name="EmailTextBlock" Grid.Row="4" Grid.Column="0" Text="Email:" FontWeight="Bold"></TextBlock>
25: <TextBlock x:Name="EmailValueTextBlock" Grid.Row="4" Grid.Column="1" Text="{Binding CorreoElectronico}"></TextBlock>
26: </Grid>
Si os fijáis en el Binding de Fecha Nacimiento podéis ver que la fecha tiene el formato de dd/MM/yyyy evitándonos el converter, además también podeos ver en el binding de dirección que cuando sea nulo se muestre la palabra Desconocida
Solo nos queda el código c# para el binding
1: public MainPage()
2: {
3: InitializeComponent();
4: Persona p = new Persona
5: {
6: Nombre = "Oscar",
7: Apellidos = "Alvarez Guerras",
8: FechaNacimiento = new DateTime(1971, 6, 29),
9: CorreoElectronico = "bialguos@gmail.com"
10: };
11: DataContext = p;
12: }
El resultado