WPF, Webbrowser & Content DataBinding
Aujourd’hui j’ai été confronté a un petit problème. Je voulais afficher les résultats d’une recherche avec une mise en forme un peut travailler à la manière des résultats retourné par les recherches dans l’ancien HelpViewer de la MSDN 2008. (Bien meilleur que celui actuel, malgré le retour en arrière fait sur le v1.1 qui reste énormément moins ergonomique à mon gout et beaucoup plus lent, fin’ bref…)
Pour cela j’avais l’idée de rajoute comme result viewer un webbrowser intégré dont le contenu serait bindé a un string contenant la page html avec les résultats mis en forme. Seul hic a cette solution, impossible actuellement de binder le contenu d’un webbrowser avec le moteur de binding wpf…
Voici donc une petite Attached Property qui vous permettra de passer outre ce petit problème.
public class WebBrowserHelper {
public static readonly DependencyProperty BodyProperty =
DependencyProperty.RegisterAttached("Body",
typeof(string),
typeof(WebBrowserHelper),
new PropertyMetadata(OnBodyChanged));
public static string GetBody(DependencyObject dependencyObject)
{
return (string)dependencyObject.GetValue(BodyProperty);
}
public static void SetBody(DependencyObject dependencyObject, string body)
{
dependencyObject.SetValue(BodyProperty, body);
}
private static void OnBodyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var webBrowser = (WebBrowser)d;
webBrowser.NavigateToString((string)e.NewValue);
}
}
Il suffit de rajouter la classe et de rajouter une référence vers son mainspace dans les xmlns de votre contrôle. Ensuite on l’utilise comme ceci :
<WebBrowser src:WebBrowserHelper.Body="{Binding MyHtml}" />
A vous les joie du binding avec un control WebBrowser en Wpf ^^
Inform@tiquement
Istace Emmanuel
Src : http://thomasfreudenberg.com/blog/archive/2010/08/01/binding-webbrowser-content-in-wpf.aspx
Mvvm Light : Partie 2 – Commandes & Events
Background Worker en C# : Et Dieu papota
Salut à tous ! Aujourd’hui, nous allons parler des travailleurs de l’ombre, les threads. Mais pas n’importe quel thread, le background worker, une encapsulation des threads classiques très utile dans le cas d’utilisation d’interface graphique. Ras-le-bol d’avoir un freeze de votre IHM lors d’une connexion à une DB ou un traitement lourd ? Alors le background workers est fait pour vous ^^ (Intervention divine en sus)
Au commencement il n’y avait que le néant et Dieu en haut à gauche, près de la machine à café
Pour commencer à jouer de manière confortable avec les background workers, pas besoin de se retaper la théorie sur les locks, la synchronisation et tout le tsouin-tsouin habituel des threads, 3 events, 2 attributs et 3 méthodes suffisent pour rendre votre application fluide comme un long fleuve tranquille :D
Pour utiliser les BackgroundWorkers vous devez ajouter une référence à System.Threading. Dans le cadre de ce how to, l’exemple choisi est un chronomètre threadé qui tourne séparément, l’interface étant mise à jour séquentiellement.
Voici le code XAML de l’interface en WPF : http://pastebin.com/TQGDNjJZ
Et voici le code-behind en C# que nous allons compléter au fur et à mesure : http://pastebin.com/QcndwztY
Et le code final qu’il serait bien d’utiliser pour suivre les explications ^^ : http://pastebin.com/2xuy7v2j
Ce qui nous donnera :
Au niveau du code, on a un timespan qui représentera la durée affichée à l’utilisateur et notre bgworker que l’on abordera au point suivant.
Dans l’IHM on a donc un label, qui affichera le temps et trois boutons, start, pour (re)lancer le chronomètre, pause et reset. Le chronomètre pouvant être mis en pause puis reprise ou remis à zéro avec reset.
Une petite précision au passage, il se peut que le chronomètre mette quelques centièmes de seconde à s’arrête ; en fait, le chronomètre s’est bien arrêté au moment du clic, il s’agit juste que la mise à jour du label qui subit un peu de latence. (Elle peut être visible si votre machine rame un peu, ce qui arrive toujours quand on a Outlook, firefox, Word, Visual Studio, le debugger de lancée attaché à l’application et de la musique avec winamp ;) )
Lors du premier jour Dieu dit « définit les attributs seront » et définis les attributs furent (jeune jedi)
Pour commencer on va initialiser notre objet de manière standard.
Ceci étant fait, il y a deux principaux attributs, ReportProgress et SupportConcelation.
Le premier nous permettra, pendant l’exécution du thread, d’appeler une fonction que l’on définira après. Cette fonction sera appel avec la méthode ReportProgress. Elle est très utile pour mettre à jour pendant le traitement l’interface graphique. Par exemple pour une progress bar ou, dans notre cas, afficher le temps.
En effet, notre chronomètre sera en fait un thread infini qui ne s’arrêtera que quand on le mettra en pause ou quand on le resettera, donc afin de pouvoir mettre à jour l’interface, on utilisera dans cette boucle un appel à cette fonction.
Le second permet d’arrêter à tout moment le thread, sans cela, le thread ne s’arrêtera que lorsque son traitement sera terminé. Ce qui nous arrange pas des masses dans ce cas-ci vu que l’on stoppera le thread à la main ^^:/
On va donc mettre ces deux attributs à true.
Lors du second jour, Dieu dit « codés tes handler seront » et codés les handler furent.
Ensuite on rentre dans le vif du sujet, les backgrounds workers reposent sur les événements. Si vous n’êtes pas familiarisés avec cette notion, reportez-vous à la msdn sur <link MSDN TODO>les routed events</link>. Pour tout de même suivre la suite, les événements peuvent être dans leur forme basique (mais qui suffira ici) des sortes de variables qui prennent comme valeur une méthode. Cette méthode sera exécutée au moment où il sera déclenché au moyen par exemple d’une autre méthode. Par exemple, on peut avoir un événement Work qui une fois déclenché exécute la méthode DisplayNames() et est déclenché par DoWork(), ainsi quand on appelleDoWork, l’événement déclenché exécute la méthode associée DisplayName. L’avantage étant que l’on peut définir de manière dynamique la méthode exécutée par l’événement et, par exemple, l’adapter à la situation.
Ces méthodes, qui sont exécutées lors du déclenchement d’un événement, sont appelées des handlers, que l’on peut traduire par gestionnaires car ils gèrent l’action effectuée lors du déclenchement de l’événement.
Pour les backgrounds workers on a accès à 4 handlers dont 3 seront utilisés ici.
Je vais tout d’abord présenter succinctement les événements et donc leur handler afin d’avoir une vision d’ensemble du processus.
Le premier, le principal, est doWork. C’est le handler qui réalisera le cœur de la tâche que l’on veut threader. Dans notre cas, il incrémentera le chronomètre. Les handlers doivent vous être familiers si vous avez déjà travaillé avec wpf par exemple car très grandement utilisés. Ce thread ne peut dialoguer avec le thread gérant l’ihm, mais les gens de chez Microsoft n’étant pas des branques, ils ont tout prévu et nous verrons plus loin comment contourner de manière élégante ce petit problème.
Ensuite viens le handler reportProgress, ce handler permet de dialoguer directement avec l’ihm. C’est à cet endroit que l’on pourra par exemple mettre à jour l’ihm.
Il existe encore deux événements, RunWorkerCompleted, lui, est exécuté lorsque le bgworker s’est exécuté jusqu’au bout et le dernier, disposed, est exécuté lorsque l’on aura libéré le worker une fois fini.
Le handler pour doWork prend deux arguments, le premier est le bgworker lui-même. L’intérêt de faire cela est que l’on peut ainsi, de l’intérieur du thread obtenir son état ainsi que ses méthodes et événements. Le second argument est un doWorkEventArgs. Il comporte trois champs. Le premier, Arguments, peut être utilisé pour transmettre des arguments au thread lors de son lancement, le second, Cancel, permet de savoir si le thread doit ou non être stoppé et enfin Result permet de stocker la valeur de retour de notre thread qui sera principalement utilisée dans RunWorkerCompleted.
Nous avons maintenant presque tout pour comprendre notre méthode doWork, à la première ligne on récupère le worker passé en argument et on le cast. Ensuite on crée un objet DateTime qui représentera le moment ou le chronomètre est lancé. Ensuite, on entre dans une boucle infinie. Dans cette boucle un if est présent. Il teste la valeur CancellationPending qui sera à true si l’on demande l’arrêt du thread. Si c’est le cas, on sort de la boucle avec un break, sinon on appelle ReportProgress dont voici le contenu :
Report Progress est similaire à DoWork excepté qu’il prend en argument un integer qui représente le pourcentage où en est la tâche et des arguments « libres ». Dans notre cas, on n’utilisera pas le pourcentage, on peut donc le laisser à un à chaque appel. Dans le cas où l’on aurait une progressbar par exemple, cette valeur serait très utile afin de définir l’état d’avancement de la barre. Ensuite on peut passer un second argument de type object, en gros ce qu’on veut.
Le handler prend en argument un ProgressEventChangedArgs qui contient deux arguments, un premier avec la valeur du pourcentage et le second avec l’objet passé en argument. Cette méthode peut interagir avec l’ihm, c’est donc ici que l’on mettra à jour notre label sans que le debugger le hurle à la mort que l’on viole une quelconque restriction de portée :D
L’objet passé en argument étant de type timespan, on le re-cast, le convertit en string et l’affectons à la valeur du Text du label.
Retournons maintenant sur doWork, pour obtenir le décompte. C’est assez simple, on prend le temps au moment de l’appel de la fonction ProgressChanged moins le temps au moment du début du thread. Et afin de pouvoir relancer le chronomètre, on y ajoute la valeur de last qui est la valeur qu’avait le thread lors de la mise en pause que nous allons voir tout de suite. A chaque itération, on met le thread en pose sinon il va utiliser tout le CPU et bien que l’action soit parallélisée, elle aura tendance à freezer la machine. Ici je mets un sleep de 10 millisecondes ce qui est suffisant pour permettre aux autres process de s’exécuter. (à part quelques chanceux munis de FPGA ou d’un cluster de calcul, on reste quand à quelques process réellement parallèles, 8 étant déjà beaucoup, et quand on sait qu’il y en a des 10énes qui tournent simultanément).
Lorsque l’utilisateur demande à stopper le thread, on sort de la boucle via le break. Ensuite on assigne la valeur courante de, comme pour un progress changed a Result. Ceci permettra de récupérer cette valeur une fois dans la méthode RunWorkerComplete. Notre méthode doWork se termine et c’est maintenant, la dernière, runWorkerComplete qui s’exécute.
Ce qui est intéressant ici c’est le RunWorkerCompletedEventArgs qui contient trois attributs, tout d’abord Cancelled qui permet de savoir si l’opération a été annulée ou non, Error qui récupère les erreurs possibles lors de l’exécution du thread et enfin Result qui contient la valeur que nous avons affectée précédemment dans doWork. Je pourrais très bien ne rien faire ici dans notre cas, mais voulant permettre de mettre en pause le chronomètre, je vais ici stocker dans last la valeur actuelle du chronomètre afin de pouvoir par la suite l’additionner au temps lors de la reprise. Addition que nous effectuons donc dans DoWork au moment du ReportProgress.
Bon, bien y a plus qu’à tester tout cela.
Lors du troisième jour Dieu dit « DoWork tu feras ». Et DoWork il fit.
Pour lancer le bgworker, rien de plus simple :
On vérifie qu’il n’est pas déjà lancé, et si ce n’est pas le cas, on le lance avec ma méthode runWorkerAsync. Et voilà… Il tourne ^^ Au moment où on lance cela, l’événement DoWork est déclenché et donc le handler associé est exécuté.
Ensuite pour le mettre en pause il suffit de vérifier qu’il est bien lancé (il n’appréciera pas que l’on veuille mettre en pause un worker qui ne fait rien) et si c’est le cas on appelle CancelAsync .
Le reste est déjà codé, c’est dans DoWork, via CancellationPending, que l’on sortira de la boucle et vous connaissez la suite.
Enfin, pour le stopper, c’est-à-dire le réinitialiser à zéro, idem que pour la pause sauf que l’on remet ensuite last à nul et, pour une question d’esthétique, le label à « 0 ».
Chacune de ces commandes sont bien entendu bindées dans le code XAML et appelées via un des buttons control. Je prépare en fait un second article, plus ciblé sur WPF, dans lequel je réutiliserai cet exemple de chronomètre, d’où l’utilisation de command et command binding plutôt que le simple mouseclick event handler. Mais ça fonctionnera tout aussi bien avec un event handler, je vous rassure ^^
Lors du quatrième jour, Dieu en glanda pas deux… En utilisant un background worker, il avait gagné la moitié de son temps.
Et voilà, it works ! Pour ceux qui utilisaient les threads classiques, je pense que l’efficacité des bgworkers et surtout leur simplicité d’utilisation n’est plus à démontrer. Avec quelques handlers assez simples on a un thread pleinement fonctionnel. Il est vrai que l’exemple ici est très simple et inutile, mais c’est dans le but de ne pas rajouter à la compréhension des bgworkers, la compréhension de la tâche à exécuter qui n’a pas de rapport avec le sujet. Si j’avais pris un exemple avec une requête sur un serveur de base de données, un traitement lourd et long, un processus serveur/client, une parallélisassion de programme, … la complexité inhérente à la compréhension de la tâche effectuée aurait fortement handicapé ce how to, expliquer le calcul du chronomètre en deux lignes ok, mais tout LinqToX… c’est autre chose…
En résumé, les bgworkers c’est :
3 attributs : Est-ce que je peux le stopper manuellement ? Est-ce qu’il rapporte l’avancement ? Est-ce qu’il attend d’être arrêté ?
4 events : La tâche, le rapport de l’avancement de la tâche, la fin de la tâche, la libération du worker
3 méthodes : RunAsync pour débuter, CancelAsync pour stopper, IsBusy pour savoir son état
Une fois ces quelques éléments en tête, il n’y a plus grand-chose de compliqué.
Lors des 5, 6 et 7émes jours… faut combler… Chabbat bien et vous ?
Le prochain article, qui se basera sur celui-ci, parlera de l’utilisation des notificationt askbar de windows 7 avec WPF4 afin de proposer des contrôles dans la miniature de prévisualisation. Ceci en complément de mon précédent article sur le drag’n’drop.
Et pour répondre aux posts, non je ne vis pas reclus depuis deux semaines, oui je sais, cela fait 2 semaines que je suis à presque 2 articles par jour et surtout non ce n’est pas du copié/collé, d’ailleurs, j’ai vu il y a 3 jours que c’était l’inverse (hein Rodt-G :p )
Inform@tiquement
Istace Emmanuel – Manu404
AD&D – Another Drag & Drop en WPF
Bonjour à tous, si certains sont tombé ici en cherchant des informations sur le célèbre jeu de rôle Advanced Donjon et Dragon, ils peuvent passer leur chemin, par contre, si des fonctionnalités de drag’n'drop en WPF vous intéresse, ce qui vas suivre vas vous intéresser. Descendez dans le labo et tuez le gobelin Hobo qui garde la porte afin de récupéré le 6éme statuette du Dieu Khewl et ainsi déjouer ses plans démoniaque !
Présentation du Drag’n'Drop
Le drag’n'drop consiste à transporter des informations de manière visuelle à l’aide d’un pointeur. Dans la plupart des cas il s’agira d’une souris, mais si vous avez la chance d’avoir une device tactile, votre doigt pourra également faire ce drag’n'drop. On peut décomposer en 2 le drag’n'drop, le drag, qui consiste à choisir les données, souvent déclenché par le clic gauche de la souris et le drop qui dépose les données, le plus souvent au moment où l’on relâche le bouton gauche de la souris.
L’application
Notre application comprend 3 éléments de type label. Deux représentant des armes un le gobelin Hobo qui garde la porte. Le but étant d’attaquer le gobelin en déplaçant l’arme choisie sur le gobelin. A ce moment-là, le label de Hobo indiquera qu’il a reçu une attaque et quel arme l’a attaqué. Pendant le déplacement une status bar dans le bas se mettra a jours.

Et voici le code XAML, assez simple :
<Window x:Class="DND.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="AD&D - Another Drag And Drop" Height="250" Width="350"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="28"/> <RowDefinition Height="*" /> <RowDefinition Height="30" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Label Name="data1" Grid.Row="0" Grid.Column="0" Content="Rapière" Foreground="CornflowerBlue" /> <Label Name="data2" Grid.Row="0" Grid.Column="1" Content="Fronde" Foreground="Crimson"/> <Label Name="receiver" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Content="Hobo le goblin, endormi devant la porte du laboratoire..." Foreground="Lime" Background="Black"/> <StatusBar Name="Status" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" > <StatusBarItem Name="StatusContent" /> </StatusBar> </Grid> </Window>
Création du Drag
Pour réaliser le Drag il suffit de rajouter un gestionnaire d’évènement sur le mouse move. Ainsi, si la souris survole l’élément, l’évènement sera déclenché.
Voici à quoi ressemblent nos deux labels après cela :
<Label Name="data1" Grid.Row="0" Grid.Column="0" Content="Rapière" Foreground="CornflowerBlue" MouseMove="pickData_MouseMove" /> <Label Name="data2" Grid.Row="0" Grid.Column="1" Content="Fronde" Foreground="Crimson" MouseMove="pickData_MouseMove" />
Maintenant, il faut coder notre gestionnaire d’évènement
private void pickData_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
DragDropEffects effects;
DataObject obj = new DataObject();
Label source = (Label)sender;
obj.SetData(typeof(string), source.Content);
effects = DragDrop.DoDragDrop(source, obj, DragDropEffects.Copy | DragDropEffects.Move);
}
}
Dans un premier temps on vérifie l’état de la souris afin de savoir sur le bouton gauche est pressé. Si oui on crée un objet de donnée dans lequel on stockera la valeur du label cliqué puis on « copiera » les données dans le presse papier avec la source et des options définissant les actions possible pour le drag’n'drop. Si vous rajouter un Messagebox, vous verrez qu’il s’affichera quand vous cliquerez puis, tout en laissant la souris cliqué, bougerez la souris.
Création du Drop
Pour le drop nous allons utiliser deux évènements, un premier qui est le DragOver et le second le Drop.
Voici le code Xaml du contrôle avec le gestionnaire d’évènements en plus :
<Label Name="receiver" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Content="Hobo le goblin, endormi devant la porte du laboratoire..." Foreground="Lime" Background="Black" AllowDrop="True" DragOver="receiver_DragOver" Drop="receiver_Drop"/>
Le premier sera utilisé pour notifier dans la statusbar l’action qui va se produire, dans le cas ou le presse papier contient des données et que le type de donnée est celui accepté.
private void receiver_DragOver(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(string)))
this.StatusContent.Content = "Action : Hobbo vas se prendre un coup...";
else
e.Effects = DragDropEffects.None;
}
Dans le second on récupère les données et on met a jours le label ainsi que la statusbar dans le cas ou des données du bon type sont présente dans le presse papier.
private void receiver_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(string)))
{
e.Effects = DragDropEffects.Copy;
string weapon = (string)e.Data.GetData(typeof(string));
this.receiver.Content += ("\n... se prend un coup de " + weapon);
this.StatusContent.Content = "";
}
else
e.Effects = DragDropEffects.None;
}
Résultat
Voici ce que cela nous donne, dans une petite vidéo de 20 secondes :
Contrôle de service en DotNet – Partie 2
DotNet : Le datagrid en WPF
De base, en WPF, les datagrid (“grille à la Exel” pour les barbares), ne sont pas présentent. Heureusement, le WPF ToolKit est là… il compte bien réparé cette erreur et venger le WPF du winform à grand coup de tatanne…
WPF TOOLKIT
La première chose à faire, si vous ne l’avez pas déjà, c’est de l’installer. Il est disponible sur http://wpf.codeplex.com/releases/view/40535
Ce toolkit contient plusieurs éléments destiné a enrichir le framework dotnet actuel.
Dans les features venant d’être released on peut trouver :
* DataGrid
* DatePicker/Calendar
* VisualStateManager (VSM)
Et dans ce qui va venir :
* Chart controls – Check out a preview here
* Autocomplete
* NumericUpDown
En bref, des fonctions que l’on souhaite souvent voir apparaître en temps que developpeur pour rendre encore plus ergonomiques nos IHM.
L’installation, eh bien, il suffit de lancer le msi. Une fois cela fait, on lance Visual Studio et on créé un projet WPF. Enfin, il suffit de rajouter dans les Références des références vers WPFToolkit. Ce qui donne ceci :
Enfin, nous allons rajouter le champ Name et un namespace xmlns, dg.
Enfin, un using.
Notre projet est maintenant configuré et prêt à l’utilisation.
Les Winforms vont morflé !
LE DATAGRID – PARTIE WPF
Dans ce tutoriel, nous allons faire un datagrid qui liste un repertoire et créé un tableau en readOnly de ces élèments. Il y aura trois colonnes, un colonne nom, une colonne dir et un colonne file. La première est du texte, les suivantes sont des checkbox selon le type de fichier (file ou dir). On rajoute également au tableau un comportement qui permet de naviguer dans les dossiers en cliquant sur l’item. Une sorte d’explorateur de fichier.
Voici le code WPF a renseigné :
En Ligne 7-8-9 on créé notre DataGrid, on bind ItemSource sur This.DemoData, on désactive l’auto génération des colonnes on le passe en ReadOnly et on rajoute un gestionnaire d’evenement lorsque la selection change. (pour la naviguation). Je pensse que jusque la, il n’y a rien de spécial. Nous allons ensuite définie les colonnes, il y a plusieurs types de colonnes :

Nous allons créé ici deux DataGridCheckBoxColumn et DataGridTextColumn. Nous allons binder le premier sur path, le second sur dir et le troisième sur path. Le header se nomme de la même manière, il s’agit ici du nom qui sera affiché en haut de la colonne. Voilà, on referme le tout, on compile et on obtient… TADA !!! Un tableau vide
…
Bon, ok… Mais il nous manque encore le plus important, il faut lui donner à manger à ce tableau, dans ce cas ci, la liste des répertoires et fichier.. Allez, hop, on retrouse ses manches et on plonge ses mains dans le code, direction Window1.xaml.cs.
LE DATAGRID – PARTIE C#
La première chose des de définir un objet de type Datatable, nous allons le nommer _DemoData et le rendre privé. Pour que notre Datagrid, via le binding, puisse y acceder, nous allons rajouter un getter, DemoData.
Ensuite dans le constructeur, nous allons initialiser _DemoData puis appeler la méthode add avec en argument, un objet de type DataColumn. Nous utiliserons sa seconde surcharge qui prend en premier le nom de la colonne et en second le type de données. Nous faisons égallement un appel initial a UpdateGUI() que nous verons plustard. Le contructeur devrait donc ressembler a ceci :
Maintenant il ne nous reste plus qu’a créé une méthode qui va lister un répertoire et renvoyer son contenu ainsi qu’une seconde qui se chargera de mettre à jour l’affichage du tableau. La première est assez basique et plutôt hors de sujet, sachez juste que il y a deux méthodes. Un première permettant d’avoir une liste d’object FileItem du répertoire passé en argument et une seconde qui permet de recupéré le FileItem sélectionné selon l’index selectionné dans le DataGrid. Voici le diagramme de classe de FileItem :
Passons donc au gestionnaire d’évenement associé au DataGrid. Nous vérifions d’abord que l’index selectionné n’est pas null, ensuite nous appelons la méthode getFile() avec l’index en argument. Enfin, On vérifie qu’il s’agit bien d’un dossier et si oui, on appel UpdateGUI.
Update() GUI est l’élément qui permet de mettre à jour le tableau. On vide tout d’abord le tableau avec Clear(), ensuite on récupère une List<FileItem> que l’on parcours avec un foreach. Pour rajouter des row à un Datagrid, il suffit de créé une variable NewRow, pour affecter des valeurs aux diffèrentes colonnes, il suffit de mentionner son nom (celui définit dans le constructeur), ensuite on rajoute la row au datagrid.
Voilà, basiquement, comment créer un DataGrid simple. Les possibilités du DataGrid sont bien plus vaste encore et des dizaines de tutos pourraient lui être entièrement dédié. J’éspère ceci dit que vous avec compris les bases de l’utilisation du DataGrid. Voici le résultat final de notre application :
Et voici une version un peu plus “riche” de cette dernière.
DotNet : Utiliser les GridSplitter WPF
Yop tout le monde, aujourd’hui, encore du DotNet. Je prépare deux Webcast sur les Windows Services en C# mais en attendant, voici un article sur l’utilisation des GridSplitter qui vous permettrons de redistribuer très facilement l’espace entre deux colonnes ou lignes. Halala, c’est beau le WPF tout de même…
Qu’est-ce qu’un GridSplitter ?
Comme dit juste au dessus, un est Gridsplitter est :
Un contrôle qui redistribue l’espace entre les colonnes ou les lignes d’un contrôle Grid.
Nous allons faire un GridSplitter en xaml uniquement, mais si vous saisissez son principe, il n’y aura aucun soucis à se faire pour le rajouter en C#, en VB en F# ou en C++.
Il faut tout d’abord distinguer deux “types” de gridsplitter, les gridsplitter horizontaux et verticaux. La différence entre les deux réside dans les valeurs qu’ont HorizontalAlignement et VerticalAlignement. Un tableau résumé très bien ces valeurs sur la msdn. Tableau que voilà :

Le plus simple pour le mettre en place et de lui mettre à disposition une colonne ou ligne dédiée. Dans cet exemple je travaillerai avec des row. Voici à quoi devrait ressembler notre Grid avant d’y inserer notre gridsplitter. Nous avons deux Textarea. Voici le code en Xaml :

Et Voici le rendu une fois le projet lancé :

Maintenant nous allons rajouter notre GridSplitter dans la row centrale. Nous mettrons donc HorizontalAlignement a Strectch et VerticalAlignement a Center afin de redimensionner les lignes et non les colonnes. Nous le griderons dans la row 1, sa hauteur sera de 3px et nous passerons ShowPreview a True afin de ne redimensionner définitivement les deux elements qu’au moment où l’utilisateur relâche la souris. Voici donc le xaml :

Et voici le rendu… Bon un jpg ça ne sert à rien, alors voici une petite video, c’est plus explicite ^^
Enfin, voici un petit exemple inutile où je met un GridSplitter de colonne et chaque colonne contient un GridSplitter de ligne. (Je me suis aperçus sur la 2éme video qu’il y a un petit bug, quand on bouge un des splitter, son ancien emplacement reste +/- visible quelques temps, ceci est un bug du logiciel de capture, pas du programme)
Et voici la solution comprenant les deux projets.
Voila, donc rien de bien compliqué pour les GridSplitter mais c’est un élément du wpf qui n’est pas forcément le “plus connu” et qui pourtant, est juste genial d’un point de vue de l’ergonomie des IHM
Sur ce…
















Laisser un commentaire