M-V-VM

9 articles

MvvmLight 5.0 et la navigation

Nouveautés

Une grande nouveauté de MVVMLight5 est l’apparition du INavigationService.

Le INavigationService est un Pattern permettant la navigation dans l’application sans utiliser la couche visuelle. Il est alors possible de migrer le même code sous différentes plateformes sans les particularités de la navigation.

Il sera également possible de tester les actions de navigation grâce aux tests unitaires automatisés.

Poursuivre la lecture

Migration du LongListSelector en Universal Apps

Après les ressources destinées aux traductions, nous continuons le tour d’horizon des éléments nécessaires pour migrer d’un projet Windows Phone 8.0 en Universal apps.

LongListSelector WP81

Le LongListSelector est un élément de liste très souvent utilisé : Il est apparu en 8.0 mais existait déjà dans la version 7.0 sous forme d’un composant tiers du Windows Phone Toolkit.

Avec les Universal Apps, ce composant disparaît au profit d’autres composants déjà présents dans Windows 8.0 : Listbox, ListView, GridView.

Liste Simple

Le cas le plus simple est lorsque LongListSelector est utilisé en mode simple Liste (sans regroupement).

Exemple de code :

<phone:LongListSelector
   ItemsSource="{Binding AllItemsViewModel}"    
   IsGroupingEnabled="False"
   ItemTemplate="{StaticResource ItemTemplate}" />

Poursuivre la lecture

Icones Segoe UI Symbol et C#

 

Les icônes Segoe UI Symbol

Microsoft depuis Windows 8 recommande d’utiliser des icônes provenant d’une police de caractères « Segoe UI Symbol ».

C’est très pratique, il suffit de choisir cette fonte et de connaître ensuite le code pour directement accéder à l’image vectorielle de très bonne qualité, et personnalisable avec de la couleur.

Certains caractères ont une largeur nulle permettant également de faire un contour d’une autre couleur ou encore de créer un cercle autour de l’cône.

Les palettes d’icônes Segoe UI Symbol sont consultables sur différents sites :

exemple :

 

SgoeUiSymbol

 

C’est assez simple, dans une application XAML, il suffit de codifier le caractère avec les tags XML standards.

Poursuivre la lecture

Pinch to Zoom avec Windows et Windows Phone 8.1

Comment rendre une image zoomable?

Pour l’application Infografx, j’ai eu besoin de gérer le zoom d’un graphique à travers un « pinch to zoom »

Zoom-Gesture

 

Lors de l’utilisation d’une image, l’utilisateur doit pouvoir zoomer et se déplacer dans le Zoom.

Mon premier réflex a été de coder l’utilisation de se zoom et du scale à partir des évenements de manipulation. Et puis comme j’étais dans un modèle M-V-VM j’ai même utilisé un behavior pour rendre le code plus propre.

Tout celà pour rien, car il existe une manière bien plus simple et bien plus efficace…

Avant

Avant, il fallait coder les gestes de l’utilisateur intervenant sur l’image.

Voici un exemple de code qui fait intervenir 2 évènements sur le contrôle ManipulationStart et ManipulationDelta.

    private void image_OnManipulationDelta(object sender, ManipulationDeltaEventArgs e)
    {
        var transform = (CompositeTransform)image.RenderTransform;

        // pan
        transform.TranslateX = _translationX + e.CumulativeManipulation.Translation.X;
        transform.TranslateY = _translationY + e.CumulativeManipulation.Translation.Y;

        // zoom
        if (e.PinchManipulation != null)
        {
            transform.CenterX = e.PinchManipulation.Original.Center.X;
            transform.CenterY = e.PinchManipulation.Original.Center.Y;

            transform.ScaleX = _scaleX * e.PinchManipulation.CumulativeScale;
            transform.ScaleY = _scaleY * e.PinchManipulation.CumulativeScale;
        }
    }

    private void image_OnManipulationStarted(object sender, ManipulationStartedEventArgs e)
    {
        // the user has started manipulating the screen, set starting points
        var transform = (CompositeTransform)image.RenderTransform;
        _scaleX = transform.ScaleX;
        _scaleY = transform.ScaleY;
        _translationX = transform.TranslateX;
        _translationY = transform.TranslateY;
    }

Le code est assez long, le résultat n’est pas parfait car un peu rigide (pas de gestion de l’inertie) et pas facile à insérer dans un modèle M-V-VM.

Il existe un moyen pourtant bien plus simple.

Le ScrollViewer

Avec Windows 8 et les projets Windows Phone 8.1 (non Silverlight), le scrollviewer est enrichi d’un Zoom.

En Initialisant la propriété ZoomMode avec « Enabled », vous bénéficiez d’un Pinch To Zoom sur n’importe quel contenu du ScrollViewer

D’autres propriétés permettent également de paramétrer votre zoom :

  • MinZoomFactor : Pour fixer le zoom minimum (exemple 0.25)
  • MaxZoomFactor : Pour fixer le zoom maximum (exemple 3.0)
  • IsZoomInertiaEnabled : Pour gérer l’inertie du zoom (exemple false)

Ce qui donne en XAML

 <ScrollViewer Width="Auto" Height="Auto" VerticalScrollBarVisibility="Visible"
                          HorizontalScrollBarVisibility="Visible" Margin="4"
                          ZoomMode="Enabled"                           
                          MinZoomFactor="0.25"
                          MaxZoomFactor="3.0"
                          IsZoomInertiaEnabled="False"
                          >
                <Grid VerticalAlignment="Top" HorizontalAlignment="Left"
                       >
...

 

Et voilà! En quelques lignes de code XAML le tour est joué. vous avez un zoom parfait, sans code à maintenir et 100% M-V-VM.

Utilisation des Images resources avec Windows Phone

Je vous propose un petit retour d’expérience sur l’utilisation des ressources dans le développement Windows Phone dans un modèle M-V-VM.

Différentes façon de coder

L’image que l’on souhaite afficher provient des ressources et devrait pouvoir s’afficher à travers une propriété Image de type BitmapImage dans un ViewModel. A noter que le dans l’exemple ci dessous, UIThreadPool permet d’afficher cette image même lorsque celle-ci est alimentée depuis un Thread qui tourne en tâche de fond.

SynchronizationContext UIThread = SynchronizationContext.Current;

public BitmapImage Image
       {
           get { return _image; }
           set
           {
               UIThread.Post(_ =>
                   {
                       _image = value;
                       RaisePropertyChanged("Image");
                   }, null);
           }
       }

Comment afficher une image incluse dans les ressources de l’application ?

Attention les 2 premières méthodes décrites sont à proscrire et à ne surtout pas reproduire. Allez jusqu’à la fin de l’article pour voir comment implémenter correctement l’affichage d’une image ressource. Poursuivre la lecture

WPF, ListView d’images, MVVM et Drag and Drop… – Fin

Introduction

Les projets précédents ont été redécoupés afin de fournir 2 assemblies directement utilisable.

Pour ceux qui souhaitent ajouter rapidement un treeview d’images avec une gestion de Drag&Drop (Voir les 4 précédents chapitres ) voici les étapes de réalisation.

L’exemple suivant montre comment réaliser une application respectant l’architecture M-V-VM avec les briques Drag and Drop et Listview d’images

Application M-V-VM exemple avec Liste en arbre de type TreeView

Il vous faudra :

  1. Ajouter les assemblies
  2. Définir un objet possédant l’Interface IImageFile (et IParentItem si vous souhaiter des structures hiérarchiques)
  3. Définir un objet ViewModel dérivant de CustomImageFileViewModel si vous voulez gérer le DragAndDrop provenant d’applications externes
  4. Initialiser les images dans CollectionImageViewModel

Implémentation

Ajouts des assemblies

La première étape est de télécharger ou compiler les assemblies suivantes (à la fin de l’article) :

  • ImageFileListView : Contient la partie visuelle, le View Model et les interfaces du modèle à implémenter
  • DragDropManager : Contient les mécanismes de Drag and Drop qui pourront être appliqués sur la lise

Ajout de la liste dans la View

Pour ajouter la liste dans la View vous devez définir une référence dans le XAML à l’assemblie ImageFileListView.

xmlns:m="clr-namespace:ImageFileListView.View;assembly=ImageFileListView"

Poursuivre la lecture

WPF, ListView d’images, MVVM et Drag and Drop… – Partie 3

Introduction

Vu précédemment

Nous avons vu dans la première partie comment implémenter une liste de fichiers en WPF avec le pattern MVVM.

Dans la deuxième partie, nous avons vus comment optimiser l’interface utilisateur avec le VirtualizingStackPanel, le multi Thread, les animations d’attente WPF. Nous avons eu également un aperçu de la manipulation des images pour utiliser lorsqu’elles existent les informations EXIF ou encore une transformation classique de ces images.

Je vous propose de voir dans cette troisième partie :

  • La mise en cache des images (améliorons l’interface utilisateur encore un petit peu)
  • Le Drag and Drop avec une sélection multiple d’éléments

Optimisation avec mise en cache

Implémentation d’un système de cache

Le but est de garder les x dernières images déjà chargée afin d’éviter un rechargement permanent de ces images.

Pour cela nous mettons en place une liste partagée en appel static, ainsi que son verrou (nous sommes dans un environnement multi-thread) afin de garantir l’écriture correcte des données.

const int maxThumbnailInCache = 300;
private static readonly List<ImageFileViewModel> _cacheThumbnail 
= new List<ImageFileViewModel>();
private static readonly object _lockCacheThumbnail = new object();

Puis nous implémentons la méthode static AddThumbnailInCache

 

 private static void AddThumbnailInCache(ImageFileViewModel p)
{
  if (p == null) return;
  if (_cacheThumbnail.Contains(p))
  {
      lock (_lockCacheThumbnail)
      {
          _cacheThumbnail.Remove(p);
      }
  }

  lock (_lockCacheThumbnail)
  {
      _cacheThumbnail.Add(p);
      if (_cacheThumbnail.Count > maxThumbnailInCache)
          lock (_lockCacheThumbnail)
          {
              _cacheThumbnail.Remove(_cacheThumbnail[0]);
          }
  }
}

La méthode teste si l’élément est présent. Si il est présent, l’élément est replacé à la fin de la liste.

Si le nombre d’éléments dépasse le maximum d’élément fixés dans le cache (maxThumbnailInCache), l’élément en haut (le plus ancien) est supprimé. Poursuivre la lecture

WPF, ListView d’images, MVVM et Drag and Drop… – Partie 2

Introduction

Vu précédemment

Nous avons vu dans la première partie comment implémenter une liste de fichiers en WPF avec le pattern M-V-VM. Nous allons voir dans cette partie comment ajouter les vignettes images “Thumbnails” représentant les images miniatures de ces fichiers.

alt

L’exemple utilisé reprend l’application précédente (sans les vignettes) qui sera complétée au fur et à mesure.

Pour revoir la première partie :

WPF, ListView d’images, MVVM et Drag and Drop… – Partie 1

Ajout des vignettes

Le premier réflex est de modifier la partie View-Modèle pour exposer la lecture du fichier image. Nous avons besoin du nom de fichier complet avec le chemin sur le disque dur. Nous ajoutons pour cela une nouvelle classe ImageFileViewModel qui va hériter de FileViewModel. Cette classe va s’occuper uniquement de l’affichage des vignettes.

Ajout de ImageFileViewModel.cs dans le ViewModel

Il nous faut ensuite ajouter la propriété FileName dans la classe ImageFileViewModel. La propriété va renvoyer le nom complet de l’objet ImageFile contenu dans _imageFile.

ImageFileCollectionViewModel retourne désormais une collection d’objet ImageFileViewModel.

 

public string FileName
{
  get { return _imageFile.FileName; }
}

 

Puis dans la partie View, nous ajoutons l’image dans le UserControl ImageFileListView.xaml

Ajout de l'image dans ImageFileListView

Le Binding est fait sur la propriété Source de l’Image avec {Path=FileName}

<ListView SelectionMode="Extended"  x:Name="ListViewImage"
         ItemsSource="{Binding Path=AllImages}"  Margin="0,20,0,0">
   <ListView.ItemTemplate>
       <DataTemplate>
           <StackPanel Orientation="Horizontal">
               <Image Source="{Binding Path=FileName}" Width="25" Height="25"/>
               <TextBlock Text="{Binding Path=ShortName}" />
           </StackPanel>
       </DataTemplate>
    </ListView.ItemTemplate> 
</ListView>

Nous pouvons lancer l’application qui fonctionne…

Premier résultat catastrophique

et pleurer… SmileyCry parce que c’est très Lennnnnt…

Poursuivre la lecture

WPF, ListView d’images, MVVM et Drag and Drop… – Partie 1

Introduction

Pour les besoins d’un logiciel orienté « Photos », j’ai eu besoin des fonctionnalités essentielles suivantes :

  • Affichage des images sous forme de vignettes dans une liste et dans une arborescence de type TreeView
  • Cet affichage doit permettre de gérer un nombre imposant de photos (>5000 !) sans générer de débordement mémoire ou de ralentissement
  • L’affichage et la génération des vignettes doit pouvoir se faire en mode asynchrone (en lisant les informations EXIF si elles existent,…)
  • La multi-sélection doit permettre de sélectionner plusieurs éléments.
  • Les éléments sélectionnés doivent pouvoir être déplacés ou copiés dans la liste (ou l’arbre) par Drag And Drop

Et le tout en DotNet WPF respectant le pattern MVVM !!!

MVVM Pattern

Je ne ferai pas un gros article sur la nécessité de développer en WPF selon une architecture MVVM (Séparation des fonctions, réutilisation, rôle des objets mieux ciblés, accès déclaratifs…). Voici quelques liens au cas où vous ne seriez toujours pas convaincus…

http://www.orbifold.net/default/?p=550
http://japf.developpez.com/tutoriels/dotnet/mvvm-pour-des-applications-wpf-bien-architecturees-et-testables/
http://msdn.microsoft.com/fr-fr/magazine/dd419663.aspx
http://www.c2i.fr/Article/Detail/a3809f7b-196a-4d8c-bb48-164f591920bb

MVVM et ListView

Cette première partie présente l’implémentation de la liste d’images avec le modèle MVVM.

Exemple d’application

Voici le descriptif fonctionnel de l’exemple que nous allons mettre en place : Un petit croquis vaut mieux qu’un long discours.

Draft MVVM application

L’application est extrêmement simpliste. La saisie d’un répertoire se fait en haut, le click sur le bouton affiche la liste des images et leur nombre total.

Découpage de l’application

L’application est découpée en 4 parties :

  • Model : l’objet “métier” image
  • ViewModel : les objets nécessaires à la manipulation des objets “Model” images par la couche “View” (Détail de l’image et liste des images)
  • View : L’affichage XAML-WPF de la liste des images
  • Controler : Les actions nécessaires : Remplissage de la liste par exemple

Poursuivre la lecture