Enlaces Interesantes WPF/Silverlight 31-01-2010

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

  • Microsoft Releases a Cross-Platform Silverlight Client for Facebook (Me)
  • Binding UI Events from View to commands in ViewModel in Silverlight 4 (Slobodan Pavkov)
  • Fluent Silverlight – Binding control events to actions (Gabriel N. Schenker)
  • XAML: writing down all values of an object? (Rob Relyea)
  • Announcing the First User Interface (UI) Components for Silverlight 4 (Silverlight Team)
  • Chapter Excerpt in CODE magazine (Pavan Podila)
  • A Silverlight, Deep Zoom and Smooth Streaming extravaganza (Mike Ormond)
  • Open Source Silverlight Video Players (Corey Schuman)
  • MVVM – It’s Not Kool-Aid* (Jesse Liberty)
  • Rounder, Faster, Better – WriteableBitmapEx 0.9.0.0 (Rene Schulte)
  • Using the WPF Tree Visualizer — vstipDebug0004 (Zain Naboulsi)
  • DataBinding tooling: keeps getting better (Rob Relyea)
  • Handing Events with Care? (Shawn Wildermuth)
  • The Code Not Taken [Comparing two ways of creating a full-size Popup in Silverlight – then picking the best] (David Anson)
  • Enlaces Interesantes WPF/Silverlight 24-01-2010

    Os dejo una pequeña colección

  • How can I sort data virtualized items in WPF? (Bea Stollnitz)
  • Aspen – part 6 of X – Reusing ObjectContex among Repositories during a DomainSerivce operation. (Fredrik Normen)
  • Known Issue – Controls Deriving From A Generic Base Class Must Be In Separate Assembly (Karl Shifflett)
  • Scrubbing with Thumbnails with the SMF Player (Michael S. Scherotter)
  • Microsoft Silverlight Media Framework v1.1 Released (Van Wortell)
  • XamlPadSample Step 1c-Project (Rob Relyea)
  • 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

     

  • http://api.google.com/crossdomain.xml
  • http://api.flickr.com/crossdomain.xml
  • http://www.twitter.com/crossdomain.xml
  • http://www.amazon.com/crossdomain.xml
  • http://www.youtube.com/crossdomain.xml

     

    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

     

    image

     

  • 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 and Drupal and Open Source Silverlight video players (Corey Schuman)
  • PDF for Silverlight Preview (Koen Zwikstra)
  • Aspen – A sample app using Silverlight 4 and .Net 4.0 – part 5 of X – New Repository implementation (Fredrik Normen)
  • Silverlight 4 – Writing a Windows-Only Application via COM Interop? (Mike Taulty)
  • COM interop examples from Silverlight 4.(Justin)
  • XamlPadSample Step 1b-fullscreen and XamlNodeLoop Sample – changing Name to x:Name during Save (Rob Relyea)
  • 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

     

    image 

    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

    image 

    Una vez que este instalada al usuario se le muestra la aplicación, en nuestro caso

     

    image

     

    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:

    image

    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

    image

    El código fuente esta en

    Enlaces Interesantes WPF/Silverlight 16-01-2010

    Los de día

    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

     

    image