MadNUG: Materiales del evento de Async y Await

Ayer tuve el honor de participar con unos cracks en el pedazo de evento que organizo MADNUG.

 

Participe con un minitrack de Async y Await con C# 5.0 dentro de VS2012. 

 

A pesar de los nervios, todo lo demás fue muy bien, y me lo pase genial en el evento.

 

Os dejo el enlace a la grabación, y los materiales de mi charla (Demos + PPT)

 

Espero que os sea de utilidad!

PD: De nuevo quiero felicitar a todos mis compañeros y a los amigos de SecondNug por el soporte!

[WIN8] Usando SemanticZoom en XAML

Introducción

En este post vamos a ver qué es y como hacer uso de este nuevo control introducido en la galería de controles de aplicaciones para la Windows Store.

¿Qué es?

Es un Control de usuario compuesto de "2 vistas”, que nos permite cambiar entre ellas haciendo para hacer zoom in, o el gesto contrario para hacer zoom out, lo que permite una interacción táctil adaptada a los nuevos dispositivos que vienen.

¿Cómo utilizarlo?

En primer lugar será necesario definir el control dentro de nuestra Vista, a través de XAML o arrastrándolo desde la barra de controles de Visual Studio.

Después pasaremos a definir las propiedades ZoomedOutView y ZoomedInView:

 

   1: <SemanticZoom>

   2:            <SemanticZoom.ZoomedOutView>

   3:                <GridView></GridView>

   4:            </SemanticZoom.ZoomedOutView>

   5:            <SemanticZoom.ZoomedInView>

   6:                <GridView></GridView>

   7:            </SemanticZoom.ZoomedInView>

   8:        </SemanticZoom>

A continuación vamos a definir la vista sin zoom :

   1: <GridView            

   2:                     AutomationProperties.AutomationId="ItemGridView"

   3:                     AutomationProperties.Name="Grouped Items" 

   4:                     ScrollViewer.IsHorizontalScrollChainingEnabled="False" ScrollViewer.IsVerticalScrollChainingEnabled="False"  SelectionMode="None" ItemsSource="{Binding Source={Binding Floors}}" Margin="0" Padding="0" VerticalAlignment="Center" HorizontalAlignment="Center">

   5:                     <GridView.Resources>

   6:                         <ItemsPanelTemplate x:Key="ItemsPanelZoomOut">

   7:                             <StackPanel Orientation="Horizontal"/>

   8:                         </ItemsPanelTemplate>

   9:                     </GridView.Resources>

  10:                     <GridView.ItemTemplate>

  11:                         <DataTemplate>

  12:                             <Grid>

  13:                                 <TextBlock Text="{Binding Group.Floor}"/>

  14:                             </Grid>

  15:                         </DataTemplate>

  16:                     </GridView.ItemTemplate>

  17:                         <GridView.ItemsPanel>

  18:                         <StaticResource ResourceKey="ItemsPanelZoomOut"/>

  19:                     </GridView.ItemsPanel>

  20:                     <GridView.GroupStyle>

  21:                         <GroupStyle>

  22:                             

  23:                             <GroupStyle.HeaderTemplate>

  24:                                 <DataTemplate>

  25:                                     <Grid Margin="0,0,24,16">

  26:                                         <Grid.RowDefinitions>

  27:                                             <RowDefinition/>

  28:                                             <RowDefinition/>

  29:                                         </Grid.RowDefinitions>

  30:  

  31:                                     </Grid>

  32:                                 </DataTemplate>

  33:                             </GroupStyle.HeaderTemplate>

  34:                             <GroupStyle.Panel>

  35:                                 <ItemsPanelTemplate>

  36:                                     <StackPanel Orientation="Horizontal" Margin="0,0,80,0"/>

  37:                                 </ItemsPanelTemplate>

  38:                             </GroupStyle.Panel>

  39:                         </GroupStyle>

  40:                     </GridView.GroupStyle>

  41:                 </GridView>

En el GridView hemos definido el template que vamos a utilizara para la visualización de cada elemento, y una serie de caracteristicias para la visualización  de la información.

Para la vista con zoom, vamos a utilizar algo parecido al siguiente GridView:

   1: <GridView IsItemClickEnabled="True"  

   2:                            x:Name="gvList" IsEnabled="{Binding IsGridEnabled}"  

   3:                            SelectionMode="Single" 

   4:                            Margin="120,80,0,0" Grid.Row="2"             

   5:                     AutomationProperties.AutomationId="ItemGridView"

   6:                     AutomationProperties.Name="Grouped Items"  

   7:                           SelectedItem="{Binding Selected}" 

   8:                            ScrollViewer.ZoomMode="Disabled"

   9:                     ScrollViewer.IsHorizontalScrollChainingEnabled="False" 

  10:                            ScrollViewer.IsVerticalScrollChainingEnabled="False"

  11:                            ScrollViewer.HorizontalScrollBarVisibility="Hidden" Padding="0" VerticalContentAlignment="Stretch"

  12:                            >

  13:  

  14:                     <GridView.Resources>

  15:                         <ItemsPanelTemplate x:Key="ItemsPanelTemplateZoomIn">

  16:                             <StackPanel Orientation="Horizontal" />

  17:                         </ItemsPanelTemplate>

  18:                     </GridView.Resources>

  19:  

  20:                     <GridView.ItemsSource>

  21:                         <Binding Source="{StaticResource MyViewSource}"/>

  22:                     </GridView.ItemsSource>

  23:  

  24:                     <GridView.ItemsPanel>

  25:                         <StaticResource ResourceKey="ItemsPanelTemplateZoomIn"/>

  26:                     </GridView.ItemsPanel>

  27:                     <GridView.GroupStyle>

  28:                         <GroupStyle>

  29:                             <GroupStyle.ContainerStyle>

  30:                                 <Style TargetType="GroupItem">

  31:                                     <Setter Property="Template">

  32:                                         <Setter.Value>

  33:                                             <ControlTemplate TargetType="GroupItem">

  34:                                                 <Grid Margin="0,0,40,0">

  35:                                                     <Grid.RowDefinitions>

  36:                                                         <RowDefinition Height="Auto"/>

  37:                                                         <RowDefinition Height="*"/>

  38:                                                     </Grid.RowDefinitions>

  39:                                                     <ContentPresenter Content="{TemplateBinding Content}" Grid.Row="0"/>

  40:                                                     <ItemsControl x:Name="ItemsControl2" ItemsSource="{Binding GroupItems}" Grid.Row="1"/>

  41:                                                 </Grid>

  42:                                             </ControlTemplate>

  43:                                         </Setter.Value>

  44:                                     </Setter>

  45:                                 </Style>

  46:                             </GroupStyle.ContainerStyle>

  47:                             <GroupStyle.HeaderTemplate>

  48:                                 <DataTemplate>

  49:                                     <Grid Margin="0,0,24,16">

  50:                                         <TextBlock

  51:                                                 AutomationProperties.Name="Group Title"

  52:                                                 Text="{Binding Floor}"

  53:                                                  Foreground="#FF474747" FontFamily="Segoe UI Semibold" Margin="0"/>

  54:                                     </Grid>

  55:                                 </DataTemplate>

  56:                             </GroupStyle.HeaderTemplate>

  57:  

  58:                         </GroupStyle>

  59:  

  60:                     </GridView.GroupStyle>

  61:  

  62:                 </GridView>

En este GridView,, hemos definido el origen de datos, el Template que se va a aplicar a cada elemento,  y la asociación con los grupos, de la vista “Zoomed Out”.

Ahora vamos a definir el origen de datos:

   1: <Grid.Resources>

   2:     <CollectionViewSource 

   3:         x:Name="MyViewSource" 

   4:         IsSourceGrouped="True" 

   5:         Source="{Binding Floors}"

   6:         ItemsPath="Elements"  

   7:         />

   8: </Grid.Resources>

Como podéis observar, el origen de datos está enlazado a nuestro ViewModel, en  el que tenemos una propiedad llamada Floors del siguiente tipo:

   1: public class ExtractionByFloor

   2:     {

   3:         private string _floor;

   4:  

   5:         public string Floor

   6:         {

   7:             get { return _title; }

   8:             set { _title = value; }

   9:         }

  10:  

  11:        

  12:         public IEnumerable Elements { get; set; }

  13:  

  14:     }

EDIT: Gracias a Antiocol por el reminder

Dentro del ViewModel podemos observar la propiedad Elements. Esta propiedad va a estar enlazada dentro de la vista ZommedInView especificandose en el origen de Datos.

Algo que viene al hilo de esto, es que cuando se haga zoom sobre uno de los elementos de la vista ZoomedOut, el zoom será efectivo sobre el grupo indicado haciendo el scroll (horizontal o verrtical según este configurado) .

Bien, por último desde nuestro CodeBehind vamos as asignar nuestro ViewModel, y asignaremos los grupos al zoom:

 

   1: public MainPage()

   2:        {

   3:            this.InitializeComponent();

   4:            this.DataContext = new MainViewModel();

   5:        }

   6:  

   7:        /// <summary>

   8:        /// Invoked when this page is about to be displayed in a Frame.

   9:        /// </summary>

  10:        /// <param name="e">Event data that describes how this page was reached.  The Parameter

  11:        /// property is typically used to configure the page.</param>

  12:        protected override void OnNavigatedTo(NavigationEventArgs e)

  13:        {

  14:            var collectionGroups = MyViewSource.View.CollectionGroups;

  15:            MyViewSource.View.MoveCurrentToPosition(-1);

  16:            ((ListViewBase)this.zoom.ZoomedOutView).ItemsSource = collectionGroups;

  17:        }

 

A través de la propiedad IsZoomedInViewActive (de tipo Bool) podemos definir como va a aparecer el control, con la vista de Zoom In o de Zoom Out.

Os dejo un enlace bastante interesante sobre el SemanticZoom.

También os dejo el enlace para que podáis descargar el proyecto.

 

Espero que os resulte útil =D

[Personal] MVP 2012

Bueno, pues en esta minientrada quiero decir que Microsoft me ha vuelto a elegir como Microsoft MVP en la categoría C#.

El 1 de octubre de 2011 fue mi primer nombramiento, y desde entonces me han sucedido muchas cosas tanto profesional como laboralmente.

Desde estas líneas quiero dar las gracias a todos aquellos que leeis este blog, o me seguís en Twitter / Facebook y aguantáis charlas, posts o mis tweets!

Un saludo !!

Y por cierto enhorabuena a todos los renovados Lluis, Palel, Ibon and Cia, y al nuevo MVP Josue Yeray, y a todos los que me dejo en el tintero!

[Evento] MadridDotNet: Novedades en VS2012

Aunque a principios de septiembre hable de que iba a participar en un evento de las novedades de VS2012, por diversos motivos hemos tenido que aplazarlo hasta octubre.

Bien os dejo la agenda prevista, y el enlace al evento:

 

  • 1-. Un poco de Visual Studio 2012 + ALM 2012 por Bruno Capuano y Luis Fraile.
  • 2-. CodedUI Tests en Visual Studio 2012 por Juan Carlos Quijano.
  • 3-. Desarrollo con Windows Phone 8 por Josue Yeray.
  • 4-. Windows Store Apps (HTML5/C#) por Javier Holguera y Jorge Serrano.
  • 5-. Async/Await en .NET Framework 4.5 por Javier Torrecilla.
  • 6-. WebAPI por Luis Ruiz Pavón.
  • 7-. Juegos escalables en Azure y Windows 8 por Alex Casquete y Quique Martínez.
  • 8-. ERP en Azure por Víctor González.
  • Mas Info 

    [WINRT] Mostrando Video directamente en un control con XAML + C#

    Introducción

    Una de las características de trabajar con WINRT es la facilidad para hacer uso de las “capacidades” del ordenador en el que está funcionando nuestra aplicación.

    En este pequeño post vamos a ver como llevar a cabo el acceso a la webcam de nuestro equipo, y reproducir dicho contenido en una vista o control de nuestro desarrollo.

    Al lio!

    Para que podamos hacer uso de  la webcam y reproducir el contenido en tiempo de ejecución, vamos a necesitar agregar las siguientes “Capabilties” a nuestro proyecto:

    – Microphone

    – WebCam

    El control que va a actuar como “host” del video va a ser del tipo “CaptureElement

    Para ello dentro de nuestro Usercontrol lo Page, lo definiremos como sigue:

       1: <CaptureElement Name="capture" Stretch="Fill" Opacity="100"/>

    Bien, una vez definido en nuestro XAML, vamos a agregar el código necesario para empezar a mostrar video:

    En primer lugar vamos a configurar el uso de la WEBCAM:

       1: private MediaCapture mediaCaptureMgr;

       2: private async void ConfigureWebCam()

       3: {

       4:     if (mediaCaptureMgr == null)

       5:                 {

       6:  

       7:                     mediaCaptureMgr = new MediaCapture();

       8:                     await mediaCaptureMgr.InitializeAsync();

       9:  

      10:                     capture.Source = mediaCaptureMgr;

      11:                     await mediaCaptureMgr.StartPreviewAsync();

      12:     }

      13: }

    A continuación bastaría con agregar una llamada a está función desde el sitio que deseemos (Botón, constructor…)

    La primera vez que se ejecute la aplicación nos pedirá permiso para ejecutar la cámara.

    Os dejo el ejemplo, y espero que os sea de utilidad.

     

    Saludos!

    [Evento]Novedades de Vs2012

    Desde MadNug, se está moviendo un  evento con algunas de las novedades de VS2012, con varios ponentes de autentico lujo.

    Se planea que sea el Jueves 20 de Septiembre, y aunque aun no está cerrada la agenda, y fijado al 100% el día, resérvalo en tu agenda insensato para que no te lo pierdas, porque te aseguro que te gustara.

    Saludos!

    PD: Espero volver a escribir nuevos post técnicos ASAP, ya que me encuentro en una época de cambios laborales y necesito reorganizarme.

    [Eventazo] Megathon Windows 8 ¿Te lo vas a perder?

    Bueno, este post es para lo que dice el titulo anunciar un eventazo que va a tener lugar los días 7,8 y 9 de Septiembre en varias ciudades españolas:

    – Barcelona

    – Bilbao

    – Canarias

    – Cordoba

    – Coruña

    – Logroño

    – Madrid

    – Santander

    – Sevilla.

    Como veis no hay escusa para no asistir =p.

    El evento va a consistir en desarrollo de aplicaciones para el nuevo sistema operativo Windows 8.

    Bueno  no me enrollo mas, teneis toda la información relativa al evento en Megathon Win8

    ¿Te lo vas a perder?

    Saludos!

    PD: Añadidas Murcia y Palma gracias @DarioDBA

    [VS2012] Información del llamante

    Introducción:

    Lo primero que poco me gustan algunas traducciones, así que vamos a llamar las cosas por su nombre, en este post vamos a hablar de una de las novedades de .NET 4.5 “Caller Information”.

    Una de las cosas novedosas de esta nueva versión del Framework viene a facilitarnos la vida a la hora de realizar trace y log de errores de nuestras aplicaciones (aunque en este post vamos a ver otra utilidad de esta información).

    Dentro del espacio de nombres “System.Runtime.CompilationServices” se han agregado tres atributos que van a poder ser aplicados sobre parámetros de un método:

    – CallerFilePath: Va a cualificar un parámetro que almacenará el nombre del fichero que ha provocado la llamada.

    – CallerLineNumber: Va a cualificar un parámetro que indicará la línea donde se encontraba la llamada al método.

    – CallerMemberName: Va a cualificar un parámetro que indicará el nombre del método que contenía la llamada.

     

    La aplicación de estos atributos, se realizará sobre parametros opcionales, los cuales tendrán que ser inicializados con algun valor:

     

    public static  void Log([CallerFilePath]string path="",[CallerLineNumber]int line=0,[CallerMemberName] string method="")
    {
    //Do Actions
    }

    Podríamos invocar a este método desde cualquier parte de la aplicación y tendríamos la información indicada.

    Os dejo un ejemplo de una aplicación de consola para que veais el funcionamiento.

    Un ejemplo:

    Un sitio donde puede ser interesante de utilizar es en la implementación del patrón MVVM (que tanto trabajo va a tener de cara al futuro).

    Podríamos aplicarlo al definir un ViewModelBase donde se realice la implementación del evento PropertyChanged:

       1:  public class VMBase : INotifyPropertyChanged
       2:     {
       3:         public event PropertyChangedEventHandler PropertyChanged;
       4:         public void ChangeProperty([CallerMemberName]string property = "")
       5:         {
       6:             if (PropertyChanged != null)
       7:                 PropertyChanged(this, new PropertyChangedEventArgs(property));
       8:             MessageBox.Show(property);
       9:         }
      10:     }

    Espero que os sea de utilidad.

    Saludos!!!

    [Tip] Extendiendo TypeConverter para tratar con nulos

    Introducción

    En este mini post voy a definir un método extensor al tipo TypeConverter para el tratamiento de valores nulos provenientes de la BD.

    Al Lio

    Como todos sabeis ( y sino muy mal…) un nulo proveniente de la Base de Datos va a ser DbNull.Value (no es el mismo null que en c#), bien para evitar problemas con el uso de TypeConverter, vamos a definir la siguiente extensión:

     

     

     public static class TypeConverterExtensions

        {

            public static object ConvertToWithNullableValues(this TypeConverter converter, object value, Type propertyTipe)

            {

                if ((value == null || value == DBNull.Value))

                    return null;

               if (value.GetType().Equals(propertyType)) return value;

                return converter.ConvertTo(value, propertyTipe);



            }

        }

    Un ejemplo de su utilización sería:

    reg.GetType().GetProperty(prop.Name).SetValue(reg, converter.ConvertToWithNullableValues(reader[prop.Name], prop.PropertyType), null);

    En el ejemplo estoy usando Reflection porque accedo dinamicamente a las propiedades…

    Bueno espero que os sea de utilidad.

     

     

    Saludos!

    PD: He añadido una condición más para que si los tipos del objeto y el tipo a convertir coincidan no intente hacer una conversión.

    [MVC] Editando Colleciones con un Template

    Introduccion

    El otro día el Gran Eduard (@Eiximenis) me resolvió una duda que tenia acerca del modelBinder y el potente enlace de datos que presenta ASP.NET MVC.

    Ha raíz de este post y del comentario de “ar7uro”, en el que planteaba la posibilidad de evitar las llamadas al servidor para ir agregando elementos a la colección.

    Como resolverlo

    Podríamos definir una variable javascript donde escribiéramos todo el código o hacerlo a través de la obtención del Html de la vista. Yo me he decantado por esta segunda versión.

    Así que partiendo del ejemplo de Eduard, vamos a realizar algunos cambios:

    – Dentro de la vista parcial:

       1:  @model MvcApplication5.Models.Direccion
       2:   
       3:  <div class="editor-label">
       4:      @Html.LabelFor(model => model.Calle)
       5:  </div>
       6:  <div class="editor-field">
       7:      @Html.Editor(string.Format("{0}[{1}].{2}", "Direcciones", "xxx", "Calle"))
       8:      @Html.ValidationMessage(string.Format("{0}[{1}].{2}","Direcciones", "xxx", "Calle"))
       9:   
      10:  </div>
      11:  <div class="editor-label">
      12:      @Html.LabelFor(model => model.Numero)
      13:  </div>
      14:  <div class="editor-field">
      15:      @Html.Editor(string.Format("{0}[{1}].{2}", "Direcciones", "xxx", "Numero"))
      16:      @Html.ValidationMessage(string.Format("{0}[{1}].{2}", "Direcciones", "xxx", "Numero"))
      17:  </div>

    Hemos eliminado el Prefix y el número que se le va a asignar.

    – Dentro de la vista de Cliente:

    He modificado el código javascript, para realizar una primera llamada para obtener el html, y para que en el click del botón incremente el contador de Direcciones, y reemplace ‘xxx’ por dicho valor.

       1:  <script type="text/javascript">
       2:      var idx = 0;
       3:      var direccionTemplate = "";
       4:      $(document).ready(function () {
       5:          alert('hola');
       6:          $.get('@Html.Raw(Url.Action("CreateDir","Direcciones"))', function (data) {
       7:              direccionTemplate = data;
       8:          });
       9:   
      10:          $('#cmdNewDir').click(function () {
      11:              var newTemplate = direccionTemplate.replace(/xxx/g,idx.toString());
      12:              idx++;
      13:              $('#direcciones').append(newTemplate);
      14:          });
      15:   
      16:   
      17:      });
      18:  </script>

     

    Espero que os sea de utilidad!!!