Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Vko

WPF, Interfaces Utilisateurs et .NET

Tags

WPF and Silverlight Designer for Visual Studio 2010

Un nouvel espace dédié au designer de Visual Studio 2010 pour WPF et Silverlight vient d'ouvrir ses portes.

On pourra y trouver des resources (blog, articles, webcast) sur tout ce qui concerne WPF et Silverlight dans Visual Studio 2010.

Hop ! Ca se passe par là : http://windowsclient.net/wpfdesigner/

Posted: jeudi 28 mai 2009 09:40 par Vko | 0 commentaire(s)
Classé sous : ,
[WPF] Afficher l'utilisation CPU à l'aide d'une jauge

Voici une des démonstrations que j'avais présenté à la BDC 2008 afin de démystifier Blend. L'objectif était de transformer une barre de progression en jauge, tout ça en 10 minutes.

Pour réaliser cette démonstration, j'ai "simplement" créé un ControlTemplate avec Blend que j'ai ensuite appliquer à la barre de progression.

L'image ci-dessous présente la barre de progression avant et après :

jauge0 

Télécharger le code source

A noter que le format écrit n'est pas le meilleur format : un WebCast devrait arriver pour présenter la solution sous Blend. Mes explications ici seront assez expéditives :)

Visualiser l'utilisation du CPU

Pour rendre la barre de progression un peu plus dynamique, elle affiche l'utilisation du CPU. J'ai donc créé une DependencyProperty, nommée CpuUsage, au niveau de la fenêtre :

public int CpuUsage
{
    get { return (int)GetValue(CpuUsageProperty); }
    set { SetValue(CpuUsageProperty, value); }
}
 
public static readonly DependencyProperty CpuUsageProperty = DependencyProperty.Register("CpuUsage", typeof(int), typeof(SolutionWindow), new UIPropertyMetadata((int)0));

Et "bindée" cette propriété au niveau d'une ProgressBar :

<ProgressBar Value="{Binding Path=CpuUsage, ElementName=Window}" />

Il ne reste plus qu'à utiliser la classe PerformanceCounter pour récupérer le pourcentage d'utilisation du CPU, et d'un DispatcherTimer afin de mettre à jour la valeur de la propriété CpuUsage :

private void CreatePerformanceCounter()
{
    cpuCounter  = new PerformanceCounter();
    cpuCounter.CategoryName = "Processor";
    cpuCounter.CounterName = "% Processor Time";
    cpuCounter.InstanceName = "_Total";
 
    timer = new DispatcherTimer();
    timer.Tick += OnTimerTicker;
    timer.Interval = TimeSpan.FromMilliseconds(1000);
    timer.Start();
}
 
private void OnTimerTicker(Object sender, EventArgs e)
{
    this.CpuUsage = (int)cpuCounter.NextValue();
}

A ce stade, nous avons une barre de progression qui affiche l'utilisation du CPU.

Notez que dans la solution téléchargeable j'ai utilisé une animation afin de rendre le changement plus progressif et fluide.

Créer le Template

Le Template va permettre de tranformer la barre de progression en jauge, et notamment d'afficher la valeur de la ProgressBar sous la forme d'une aiguille qui tourne. La contrainte étant de pouvoir recréer ce Template en 5 minutes.

La première chose est de réfléchir à la structure graphique de la jauge, la figure ci-dessous montre le découpage de la jauge :

jauge

Dans cette jauge, il y a deux choses qui ne peuvent pas (enfin ci ... mais bon) être faites avec Blend :

  • Les graduations. Pour afficher les graduations, j'ai créé un petit contrôle qui affiche des rectangles à intervalles réguliers.
  • La conversation de l'utilisation du CPU exprimée en pourcentage en une valeur angulaire. Ceci sera fait par un Converter nommé PercentageConverter.

Vous pourrez retrouver ces deux éléments au niveau de la solution.

Pour le reste, il suffit d'ouvrir Blend, de créer un ControlTemplate vierge, et de superposer les différents éléments graphiques identifiables dans la figure précédentes à savoir :

  • Un effet chromé : une ellipse avec un RadialGradientBrush
  • Un fond noir : une ellipse avec un LineraGradientBrush
  • Les graduations : le contrôle de graduations
  • L'aiguille qui tournera : un rectangle
  • Le centre de l'aiguille : encore une ellipse
  • Et enfin le petit reflet : perso j'ai utilisé un Path

La subtilité de ce Template réside au niveau de l'aiguille qui doit :

  • Etre centrée au milieu de la jauge
  • Tourner à sa base en fonction de la propriété Value de la ProgressBar.

Pour résoudre la première problématique, on peut utiliser une grille avec deux lignes et positionnée l'aiguille dans la première ligne et centrée horizontalement au milieu (c'est bien plus simple à comprendre sous Blend) :

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="0.5*"/>
        <RowDefinition Height="0.5*"/>
    </Grid.RowDefinitions>
    <Rectangle Width="3" HorizontalAlignment="Center" />
</Grid>

Pour le problème de rotation de l'aiguille, il suffit d'utiliser une RotateTransform sur le rectangle. On n'oublie pas de modifier la propriété RenderTransformOrigin afin que la rotation se fasse à la base du rectangle :

<Rectangle RenderTransformOrigin="0.5,1" Width="3" HorizontalAlignment="Center" >
    <Rectangle.RenderTransform>
        <TransformGroup>
            <RotateTransform>
                <RotateTransform.Angle>
                    <Binding Path="Value" RelativeSource="{RelativeSource TemplatedParent}">
                        <Binding.Converter>
                            <converters:PercentageConverter/>
                        </Binding.Converter>
                    </Binding>
                </RotateTransform.Angle>
            </RotateTransform>
        </TransformGroup>
    </Rectangle.RenderTransform>
</Rectangle>

Enfin, on utilise une expression de Binding. Cette expression permet de lier la valeur de la propriété Value de la ProgressBar (qui représente le pourcentage CPU) à l'angle de la rotation de l'aiguille.

On n'utilise le PercentageConverter décrit plus haut afin de transformer la valeur d'utilisation CPU en valeur angulaire.

Enjoy !!

[WPF] HyperLink + Document + Copier/Coller = NotSupportedException

La classe FlowDocument vous permet d'afficher n'importe quel type de contenu : texte, image, lien hypertexte, etc., extrêmement pratique ! Toutefois, elle présente un léger problème lorsqu'on utilise un HyperLink.

Exemple : le code ci-dessous permet d'afficher le texte "Voici un lien" :

   1: <FlowDocument>
   2:     <Paragraph>
   3:         <Run>Voici un</Run>
   4:         <Hyperlink Command="local:Window1.MaCommande">lien</Hyperlink>
   5:     </Paragraph>
   6: </FlowDocument>
   1: public partial class Window1 : Window
   2: {
   3:     public static readonly RoutedCommand MaCommande = new RoutedCommand("MaCommande", typeof(Window1));
   4:     ...
   5: }

La particularité de ce code est la présence d'une commande au niveau de l'HyperLink.

Si vous exécutez ce code, que vous sélectionnez tout le texte et faites un Copier (ou un Drag), vous allez avoir une belle "NotSupportedException" : 'CommandConverter' is unable to convert 'System.Windows.Input.RoutedCommand' to 'System.String'.

Comme le souligne le texte de l'Exception, WPF n'arrive pas à convertir une Command en String. En utilisant Reflector, on peut s'apercevoir que le code de la méthode ConvertTo de la classe CommandConverter n'autorise que la conversion des commandes fournies par WPF !

La solution la plus simple pour contourner le problème est donc d'utiliser une des commandes de WPF:

  • Dans la classe System.Windows.Input.ApplicationCommands
  • Ou bien System.Windows.Input.NavigationCommands

Exemple :

   1: <Hyperlink Command="input:NavigationCommande.GoToPage">lien</Hyperlink>

D'autres solutions existent, comme recréér la classe HyperLink ou ne pas utiliser les Commandes, mais j'avoue que j'aime bien la solution facile :p

Posted: mardi 10 mars 2009 20:11 par Vko | 0 commentaire(s)
Classé sous :
Performances avec WCF

Si comme beaucoup de gens vous vous posez encore la question "WCF est-il plus performant que Remoting (ou WSE) ?" - oui il y a des gens qui se posent encore la question - je vous conseille d'aller voir ce petit comparatif de l'MSDN :

http://msdn.microsoft.com/en-us/library/bb310550.aspx

Posted: vendredi 6 mars 2009 09:36 par Vko | 2 commentaire(s)
Classé sous :
Comment faire un screenshoot d'un contrôle WPF ?

Rien de plus simple en WPF, je pense que le code ci-dessous se passe de commentaire :

   1: private void Screenshoot(FrameworkElement element, String filename)
   2: {
   3:     RenderTargetBitmap targetBitmap = new RenderTargetBitmap((int)element.ActualWidth, 
   4:                                                              (int)element.ActualHeight, 
   5:                                                              96d, 
   6:                                                              96d, 
   7:                                                              PixelFormats.Default);
   8:  
   9:     targetBitmap.Render(element);
  10:  
  11:     JpegBitmapEncoder encoder = new JpegBitmapEncoder();
  12:     encoder.Frames.Add(BitmapFrame.Create(targetBitmap));
  13:  
  14:     using (FileStream stream = File.Open(filename, FileMode.Create))
  15:     {
  16:         encoder.Save(stream);
  17:     }
  18: }
[WPF] Supprimer le padding des cellules d'une ListView

Ce qu'il y a de bien avec WPF, c'est toutes ces petites choses qu'on trouve coder en dur.

Prenez par exemple cette ListView avec un joli rectangle rouge de 20*20

<ListView DataContext="{StaticResource ds}" ItemsSource="{Binding}"> <ListView.View> <GridView> <GridView.Columns> <GridViewColumn Width="20" Header=""> <GridViewColumn.CellTemplate> <DataTemplate> <Rectangle Width="20" Height="20" Fill="Red" /> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> ...

Si on exécute une telle ListView, on se rend compte que notre joli rectangle ne fait que 8 pixels de largeur !

Après avoir chercher dans tous les ControlTemplate où pouvait bien se cacher ce ?*ù!$ padding, j'ai démarré mon outil préféré : Reflector.

Et voila ce que j'y ai trouvé dans la classe GridViewRowPresenter :

_defalutCellMargin = new Thickness(6.0, 0.0, 6.0, 0.0);

Hop, je sors ma calculatrice : 8 + 6 + 6 = 20 ... tiens drôle de coïncidence !? Malheureusement le hasard n’y est pour rien, la valeur de padding est bel et bien fixée en dur dans le code.

Il n’y a aucun moyen de modifier cette valeur proprement, une solution pour contourner le problème est d’affecter une marge de (-6,0,-6,0) au CellTemplate de la colonne, et hop le tour est joué !

<DataTemplate>
     <Rectangle Margin="-6,0,-6,0" Width="20" Height="20" Fill="Red" />
</DataTemplate>
 
Posted: lundi 8 septembre 2008 21:40 par Vko | 0 commentaire(s)
Classé sous :


Les 10 derniers blogs postés

- [Refactoring] ReSharper pour Visual Studio 2010 (Preview) par Thomas Jaskula le il y a 1 heure et 38 minutes

- [Refactoring] Analyser vos exceptions avec ReSharper Exceptional par Thomas Jaskula le il y a 2 heures et 52 minutes

- SharePoint 2007 : patterns & practices SharePoint Guidance par Philippe Sentenac [MVP SharePoint] le il y a 16 heures et 31 minutes

- [Visual Studio 2010] Les tests cases c’est bien, mais je vais devoir tout réécrire ? par Etienne Margraff le il y a 17 heures et 28 minutes

- MVP[Gribouillon].AddYear par The Grib's Lair [Sébastien PICAMELOT - MVP SharePoint] le il y a 17 heures et 43 minutes

- Clinique INSIA - Projet de fin d’Etudes (Silverlight 3 MVVM et OutOfBrowser, WCF, TFS) - Part 1 par David REI le 07-02-2009, 23:38

- C’est la crise ? Bah pourquoi cramer du budget pub alors ? par Nix's Blog le 07-02-2009, 15:31

- Soyons MVP ! par TheSaib .NET blog le 07-02-2009, 12:15

- SharePoint : Gestion des Erreurs 6398, 7076 et 6482 par Blog Technique de Romelard Fabrice le 07-02-2009, 11:53

- EF avec WPF par Matthieu MEZIL le 07-02-2009, 10:18