Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Lorsque l'on souhaite développer une application de gestion, l'une des premières tâches effectuées est la liaison de données entre une collection(d'objet métier) et des contrôles visuelles: une liste déroulante, une liste de données. Il est alors possible de faire des modifications de données à deux niveaux : Soit via le contrôle visuelle, soit via la stucture de données liée directement.

Une chose intéressante dans le DataBinding c'est sa bidirectionnalité à savoir que si nous modifions les données liées au contrôle par son intermédiaire, la structure de données sous-jacente est modifiée et inversemement.

Nous regarderons donc comment faire en sorte que, lorsque l'on modifie nos données métier, les contrôles sont automatiquement mis à jour.

Ce post fait suite à un précédent concernant le Databinding en WPF que vous trouerez ici

Première étape: notre application WPF

image 

Notre application affiche des personnes qui ont été ajoutées dans une collection elle même liée à une listbox.

Deux boutons permettent d'interagir avec la liste:

  • Insert : Ajoute une nouvelle personne dans la liste,
  • Modification : Modifie le premier élément de la liste en changeant le texte "Myamoto" en "Samouraï Musashi".

Seconde étape: la strucutre de données

Pour réaliser notre application nous allons nous appuyer sur deux classes :

  • Personne : correspondant à une personne,
  • PersonneCollection : Correspondant à une collection de personne (collection typée donc).

La classe personne est comme suit :

public class Person : { private string surname; public string Surname { get { return surname; } set { surname = value; } } private string name; public string Name { get { return name; } set { name = value; } } private string adress; public string Adress { get { return adress; } set { adress = value; } } public Person() { } }

La classe PersonneCollection est comme suit :

public class PersonCollection : Collection<Person> { }

Troisième étape : le code de la fenêtre

<Window x:Class="WpfApplicationDataBindingPart2.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplicationDataBindingPart2" Title="Liste de personnes" Height="300" Width="300" Loaded="Window_Loaded"> <Window.Resources> <local:PersonCollection x:Key="Persons"> <local:Person Name="Myamoto" Surname="Musashi" Adress="Bewise" /> <local:Person Name="Delta" Surname="Kosh" Adress="Bewise" /> <local:Person Name="Lolo" Surname="Suchii" Adress="Bewise" /> </local:PersonCollection> <DataTemplate x:Key="dtPerson"> <StackPanel> <TextBlock Text="{Binding Path=Name}" FontSize="14" FontWeight="Bold" /> <TextBlock Text="{Binding Path=Surname}" /> <TextBlock Text="{Binding Path=Adress}" /> </StackPanel> </DataTemplate> <Style x:Key="ListBoxItemStyle" TargetType="{x:Type ListBoxItem}"> <Setter Property="Margin" Value="2" /> </Style> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition Height="75*" /> <RowDefinition Height="25*" /> </Grid.RowDefinitions> <Border BorderBrush="DarkGoldenrod" BorderThickness="3" Grid.Row="0"> <ListBox x:Name="lstPerson" ItemsSource="{Binding}" DataContext="{StaticResource Persons}" ItemTemplate="{StaticResource dtPerson}" ItemContainerStyle="{StaticResource ListBoxItemStyle}"/> </Border> <StackPanel Grid.Row="1"> <Button x:Name="btInsert" Content="Insert" Width="120" Height="20" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="2" Click="btInsert_Click"/> <Button x:Name="btModify" Content="Modification" Width="120" Height="20" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="2" Click="btModify_Click"/> </StackPanel> </Grid> </Window>

Je ne rentre pas trop dans le détail voici un focus sur les points importants :

  • L'instanciation de la collection personne faite de cette façon :

<local:PersonCollection x:Key="Persons"> <local:Person Name="Myamoto" Surname="Musashi" Adress="Bewise" /> <local:Person Name="Delta" Surname="Kosh" Adress="Bewise" /> <local:Person Name="Lolo" Surname="Suchii" Adress="Bewise" /> </local:PersonCollection>

  • Le Binding dans la listbox :

<ListBox x:Name="lstPerson" ItemsSource="{Binding}" DataContext="{StaticResource Persons}" ItemTemplate="{StaticResource dtPerson}" ItemContainerStyle="{StaticResource ListBoxItemStyle}"/>

Notre souci est donc comment faire réagir le contrôle listbox dés lors que l'on  :

  • Ajoute un élément dans la ListBox,
  • Modifie les propriétés d'une personne de la liste en question.

Quatrième étape : Faire réagir le contrôle à l'ajout d'un élément de notre liste

Pour notifier et rafraichir notre contrôle lors de l'ajout d'un élément dans notre liste, il faut que notre collection personnalisée hérite d'une interface nommée INotifyCollectionChanged. Cette interface va nous permettre d'implémenter un évènement que l'on déclenchera lors de l'ajout et la suppression d'élément dans notre liste. Le code de notre collection devient donc :

public class PersonCollection : Collection<Person>, INotifyCollectionChanged { public void Add(Person item) { base.Add(item); ExecuteCollectionChanged(NotifyCollectionChangedAction.Add, item); } public void Remove(Person item) { base.Remove(item); ExecuteCollectionChanged(NotifyCollectionChangedAction.Remove, item); } void ExecuteCollectionChanged(NotifyCollectionChangedAction action, Person item) { if (CollectionChanged != null) { CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, item)); } } #region INotifyCollectionChanged Members public event NotifyCollectionChangedEventHandler CollectionChanged; #endregion }

Une fois cette interface implémentée sur notre liste, L'interface réagit lors du click sur insert et le nouvel élément s'affiche à l'écran. le code du bouton insert est le suivant :

private void btInsert_Click(object sender, RoutedEventArgs e) { PersonCollection people = this.Resources["Persons"] as PersonCollection; people.Add(new Person { Name = "Mim", Surname = "Mimetis", Adress = "Bewise" }); }

Le résultat de l'affichage après l'ajout de MIM dans la liste :

image

Cinquième étape : Faire réagir le contrôle à la modification d'une propriété d'un élément de la liste

De la même manière, nous souhaitons faire réagir notre contrôle dés que nous modifions une propriété d'une personne de la liste. Pour cela, comme pour notre collection, nous devons utiliser une  interface implémentée par notre classe Personne. Elle se nomme : INotifyPropertyChanged. une fois implémenté, notre classe personne est la suivante :

public class Person : INotifyPropertyChanged { private string surname; public string Surname { get { return surname; } set { if (value != surname) { surname = value; NotifyPropertyChanged("Surname"); } } } private string name; public string Name { get { return name; } set { if (value != name) { name = value; NotifyPropertyChanged("Name"); } } } private string adress; public string Adress { get { return adress; } set { if (value != adress) { adress = value; NotifyPropertyChanged("Adress"); } } } public Person() { } private void NotifyPropertyChanged(string property) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(property)); } } #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; #endregion }

Nous déclenchons donc l'évènement de notification de changement à chaque fois qu'une propriété est modifiée. Le code suivant du bouton "Modification" est donc désormais fonctionnel et chaque changement met à jour la listbox.

Le code du bouton Modification est le suivant :

private void btModify_Click(object sender, RoutedEventArgs e) { PersonCollection people = this.Resources["Persons"] as PersonCollection; Person musashi = people[0] as Person; musashi.Name = "Samouraï Musashi"; }

Le résultat de la modification est là :

image 

Sixième étape : remarque sur les collections

Nous avons, pour bien comprendre le mécanisme de notification, utiliser une collection personnalisée pour réaliser le DataBinding. Il faut savoir que WPF met à notre disposition une collection générique qui hérite déjà de INotifyCollectionChanged c'est l' ObservableCollection<T>. Celle - ci nous permet donc de nous passer de PersonnCollection. Elle se déclare de la façon suivante

ObservableCollection<Person> people;

Dans le prochain Post sur le DataBinding nous analyserons les BindingExpression et regarderons sur un cas concret comment mettre en oeuvre le DataBinding de manière efficace et performante

Musa.

Posté le jeudi 3 juillet 2008 09:36 par musashi | 0 commentaire(s)
Classé sous :

La BDC 2008 terminé, vous pouvez désormais retrouver tous les WebCasts des sessions en ligne à cette adresse : Les WebCasts 

La session plénière avec 1h15 de Silverlight 2, DeepZoom, WCF, ASP.NET Dynamic Data et autres LINQ, un bonheur pour le speaker, un bonheur pour les spécateurs à revivre ci-dessous:

Part 1 : http://www.bewise.fr/fr-FR/technos/Pages/DetailWebcast.aspx?ID=25

Part 2 : http://www.bewise.fr/fr-FR/technos/Pages/DetailWebcast.aspx?ID=26

Part 3 : http://www.bewise.fr/fr-FR/technos/Pages/DetailWebcast.aspx?ID=27

Part 4 : http://www.bewise.fr/fr-FR/technos/Pages/DetailWebcast.aspx?ID=28

Sinon feriez-vous confiance à cette bande de geek la ?

60 

pour vous donner un ordre d' idée, la session plénière ça donnait ça  :

BEWISE-pleniaire

Retrouvez d'autres ressources et articles ici : http://www.bewise.fr/fr-FR/technos/Pages/Articles.aspx

Retrouvez d'autres WebCast ici : http://www.bewise.fr/fr-FR/technos/Pages/Webcasts.aspx

Bon visionnage.

Musashi.

Un des effets sympa que l'on utilise très courament c'est le rollover sur un bouton. En quoi cela consiste pour le néophyte ? C'est simplement le fait d'appliquer une modification visuelle sur un objet dés que la souris passe dessus. Alors comme ça c'est simple mais en Silverlight les choses se complique un peu et je m'en vais vous expliquer comment ajouter cet effet. L'avantage c'est que cela nous permettra de faire le tour de quelques notions sympa en Silverlight comme les styles et les templates. Alors prenons l'exemple d'nu bouton "insert"

Lorsque le bouton est dans son état normal il a ce rendu là : 

image

Une foi la souris passé dessus voilà le rendu :

image

Bien sur rien de magique la dedans j'ai juste utilisé deux images différentes. Il est à noter qu'un bouton Silverlight à d'origine cette tête là :

image

Je remercie mitch pour le design comme d'hab un développeur WPF et Silverlight n'est rien sans le meilleur designer :o)

 

Création d'un bouton avec deux images:

La création d'un bouton en Xaml est réalisé par la classe "Button"

<Button Width="140" Height="30" x:Name="insertButton" Click="insertButton_Click" />

Pour bien comprendre notre bouton, une petite explication s'impose , définissons ce que sont les Styles et les Templates.

Les styles

Ils correspondent au style css, ils permettent de spécifier des valeurs à des propriétés pour un type donné. ils sont basés sur la classe Style. Par exemple si je veux créer des boutons qui sont toujours espacés de 3 pixels il suffit de créer le style suivant :

<Style x:Key="ButtonStyle" TargetType="Button"> <Setter Property="Margin" Value="3" /> </Style>

Puis pour qu'ils soient appliqués à un bouton, il faut affecter la propriété Style de ce dernier à notre "ButtonStyle":

<Button Width="140" Height="30" x:Name="insertButton" Style="{StaticResource ButtonStyle}" Click="insertButton_Click" />

Les Templates

Les templates correspondent au rendu du bouton. Par exemple si je veux que mon bouton soit elliptique au lieu de carré, si je veux qu'il comporte une image au lieu de son rendu actuel c'est le rôle du Template.

Dans notre cas, nous allons nous attarder sur le contrôle Template et redéfinir complètement le layout de notre bouton.

Les styles et les templates peuvent se méler car le ControlTemplate est une propriété des contrôles silverlight. On peut donc créer un style qui modifie le ControlTemplate. Ce sera notre cas.

Nous réalisons cela comme suit :

<Style x:Key="ButtonStyle" TargetType="Button"> <Setter Property="Margin" Value="3" /> <Setter Property="ControlTemplate"> <Setter.Value> <ControlTemplate> <!-- Nous mettons ici le rendu de notre Control--> </ControlTemplate> </Setter.Value> </Setter> </Style>

Le Template de notre Boutton contient donc deux images qui se superspose. Seule l'une des deux images s'affiche suivant l'état de notre contrôle. Pour cela nous jouons sur l'opacité des images. Dans notre cas, l'opacité de l'image normale est de 1 et celle de l'image s'affichant lors du rollover est de 0.

<Style TargetType="Button" x:Key="ButtonStyle"> <Setter Property="Template"> <Setter.Value> <ControlTemplate> <Grid x:Name="RootElement"> <Image x:Name="ImgInsert" Source="/Images/IcoInsert.png" Opacity="1"/> <Image x:Name="ImgInsertRO" Source="/Images/IcoInsertRO.png" Opacity="0"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>

L'animation

Une fois notre contrôle créé, il nous reste à créer l'animation et appliquer notre style au contrôle. L'animation modifiera l'opacité des boutons pour les passer de 1 à 0 et inversement. Le déclencheur sera l'évènement MouseOver.

<Style TargetType="Button" x:Key="ButtonStyle"> <Setter Property="Template"> <Setter.Value> <ControlTemplate> <Grid x:Name="RootElement"> <Image x:Name="ImgInsert" Source="/Images/IcoInsert.png" Opacity="1"/> <Image x:Name="ImgInsertRO" Source="/Images/IcoInsertRO.png" Opacity="0"/> <Grid.Resources> <Storyboard x:Key="Normal State" /> <Storyboard x:Name="StoryButton" x:Key="MouseOver State"> <DoubleAnimation Storyboard.TargetName="ImgInsert" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.1"/> <DoubleAnimation Storyboard.TargetName="ImgInsertRO" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.1"/> </Storyboard> </Grid.Resources> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>

Nous appliquons enfin ce style à notre contrôle comme vue précédement et le tour est joué.

Hope to help you !

Musashi.

Je ne le ferais pas souvent mais fort est de constater que là, j'ai été très impressionné par le travail réalisé par mon Jedi Master donc je vous transmet l'info.  Un moteur 3D entièrement en Silverlight. la démonstration est impressionante !!

Son blog est ici et la démonstration du moteur 3D est là http://www.vertice.fr/NovaLight/NovaLightTestPage.html

Quelques photos pour donner envie (je confirme qu'il n'est pas Designer :o) ) :

image

et ça :

image

 

Musashi. 

La BDC c'est des sessions, des nouveautés, un jeux concours avec une TV LCD de 94 cm à gagner  .... mais surtout plein de SQL Server 2008, SharePoint, ASP.NET, Team System et beaucoup, beaucoup de Silverlight 2

Le détail du contenu de l'évènement le plus attendu de Toulouse

Les inscriptions sont par là !

En attendant, une petite vidéo des coulisses de la préparation...

 

Retrouver Jean-Pierre sur son blog technique dédié à SQL Server et ASP.NET ici

A bientôt,

Musashi.

 

Vous l'avez surement appris, Silverlight 2.0 vient de sortir suite à l'annonce du MIX 2008. Vous pouvez télécharger tout ce qui vous est nécessaire au développement d'une application Silverlight 2.0 à ces différents liens:

Je ne parlerais pas de Blend dans ce post (c'est un outil pour graphiste ça ! pas pour développeur :o) )

Nous allons donc voir :

  • Une vue d'ensemble de Silverlight 2.0 avec VS 2008,
  • Le hosting en deux mots (vraiment deux mots),
  • développement d'une première application.

Vue d'ensemle de Silverlight avec Visual Studio 2008

Donc voici comment se présente Silverlight 2.0 lorsque l'on souhaite créer un nouveau projet dans Visual Studio 2008:

image

Deux possibilités s'offre à vous, soit créer une Application Silverlight , soit créer une Dll Silverlight. Ce sont les mêmes type de projet qui étaient à votre disposition avec la version 1.1 Alpha (mais oublions la voyons !!!!).

Lorsque vous créez une application, un assistant démarre vous proposant :

image

Comme beaucoup le savent silverlight est un plugin. Il doit donc être hébergé par une application Web (HTML ou ASP.NET) .

Ainsi cette écran vous propose soit de créer un projet Silverlight et son hôte Web en même temps (avec la possibilité de choisir Web Site ou Web application project) , soit de créer uniquement le projet Silverlight à héberger soit même à la main (c'est le cas ou vous avez déjà un site Web qui l'hébergera par exemple).

Dans le premier cas vous obtiendrez cela :

image

Donc un site Web et l'application Silverlight.

Dans le second , seulement le projet Silverlight :

image

Bon bref, voilà trois impression d'écran qui n'impressionne pas et que vous retrouverez dans tous les tutoriels mais ma joie m'obligeait de vous les présenter !

Première chose qui frappe dans le projet Silverlight , sa ressemblance avec un projet WPF !

Le hosting de Silverlight au sein de votre application ASP.NET

Mais quoi de neuf au niveau du hosting ? Ceux qui comme moi ont développé avec la version 1.0 (celle qui nous obligeait à nous torturer le Javascript) seront heureux d'apprendre que des contrôles ASP.NET existe pour héberger Silverlight dans votre DIV. Voici l'exemple que j'ai utilisé (fournit par MS):

<asp:Silverlight BorderWidth="2" BorderColor="AliceBlue" ID="Xaml1" runat="server" Source="~/ClientBin/SilverlightApplication1.xap" Version="2.0" Width="100%" Height="100%" BackColor="Black" />

 

L'application Silverlight quand à elle, présente deux fichiers

  • App.xaml : qui correspond à une instance d'Application en fait
  • Page.xaml : qui correspond  au contenu exposé par le plugin.

Mais passons aux choses sérieuses, faisons, ce que tous le monde attends : du Windows dans du Web via l'utilisation de contrôles utilisateurs RICHE !

Les contrôles et la construction d'une page

Ce n'est plus un Canvas qui nous accueil mais un UserControl qui constitue le body de notre page

<UserControl x:Class="SilverlightApplication1.Page" xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:SilverlightApplication1" Loaded="UserControl_Loaded" Width="1024" Height="780"> </UserControl

Ensuite , on se fait plaisir en ouvrant la toolbox (et on craint de ne voir que des canvas et autre ellipse ...) Mais non c'est la magnifique fenêtre suivante qui nous ouvre grand les bras:

image

Donc, non seulement la fenêtre est pleine de contrôles, mais surtout l'essentiel est là pour démarrer une application riche ce que nous allons faire !

Allez je vous propose de partir sur un truc simple, un player Vidéo :o) ah non ça c'était le seul truc que l'on pouvais montrer avec la version 1.0 ..... Donc plutôt une modeste application avec trois zones de saisie et un bouton. Cette dernière instanciera un User (Nom prénom et age) et  nous affichera son contenu dans les zones. voilà donc le résultat que nous attendons.

image

Tout d'abord nous créons une Classe User utltra simple :

using System; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace SilverlightApplication2 { public class User { public string Nom { get; set; } public string Prenom { get; set; } public int Age { get; set; } } }

puis, nous créons l'interface utilisateur : Pour cela nous avons besoin de trois zones de saisies, un bouton, et un textblock

<Grid x:Name="LayoutRoot" Background="White"> <StackPanel > <TextBox x:Name="txtNom" Margin="3" BorderThickness="2" BorderBrush="DarkViolet"/> <TextBox x:Name="txtPrenom" Margin="3" BorderThickness="2" BorderBrush="DarkViolet"/> <TextBox x:Name="txtAge"Margin="3" BorderThickness="2" BorderBrush="DarkViolet"/> <Button Content="Save" Width="150" Height="30" HorizontalAlignment="Left" Margin="3" Click="Button_Click"/> <TextBlock x:Name="txtResultat" /> </StackPanel> </Grid>

Première chose qui nous apparait :

  • Nous avons des contrôles de Layout (StackPanel, Grid, Canvas) ce qui nous facilite grandement le positionnement des objets dans nos surfaces.
  • Puis nous réalisons un positionnement relatif à l'aide de la propriété Margin

Regardons désomais le binding et notamment comment instancier un objet en XAML. Pour cela plusieurs étapes :

  • 1 - référencer votre namespace, nommé local dans notre contexte:
<UserControl x:Class="SilverlightApplication2.Page" xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:SilverlightApplication2" Width="400" Height="300">
  • 2 - Créer votre resource qui instancie votre user
<UserControl.Resources> <local:User x:Key="my" Nom="Musashi" Prenom="Myamoto" Age="32" /> </UserControl.Resources>
  • 3 - Réaliser le dataBinding
    • Ajouter votre user "my" au dataContext( l'équivalent d'une DataSource) de votre StackPanel
    • Ajouter le binding sur chacune des zones de saisie

<StackPanel DataContext="{StaticResource my}"> <TextBox x:Name="txtNom" Text="{Binding Nom}" Margin="3" BorderThickness="2"/> <TextBox x:Name="txtPrenom" Text="{Binding Prenom}" Margin="3" BorderThickness="2"/> <TextBox x:Name="txtAge" Text="{Binding Age}" Margin="3" BorderThickness="2"/> <Button Content="Save" Width="150" Height="30" HorizontalAlignment="Left" Margin="3" Click="Button_Click"/> <TextBlock x:Name="txtResultat" /> </StackPanel>

Enfin la gestion des évènements, lorsque je clique sur le bouton, j'affiche un message dans le textBlock:

  • 1  - Evènement levé lors du click sur le bouton : "Button_Click"

<Button Content="Save" Width="150" Height="30" HorizontalAlignment="Left" Margin="3" Click="Button_Click"/>
  • 2 - Réaction à l'évènement

private void Button_Click(object sender, RoutedEventArgs e) { txtResultat.Text = "Save successfull"; }

Une fois réalisé cela, on relit son code et l'on se dit : il est un peu répétitif  le code de mes textBox et surtout elles ont toutes le même Style, donc vous finaliserez votre sample avec l'ajout d'un style qui permet automatiquement de postionner les bordures et le margin de l'ensemble de nos zones de saisies.

<Style TargetType="TextBox" x:Key="myTextBoxStyle"> <Setter Property="Margin" Value="3" /> <Setter Property="BorderThickness" Value="2"/> <Setter Property="BorderBrush" Value="DarkViolet"/> </Style>

Modification et code de l'ensemble de la fenêtre pour intégrer le style mis en ressource:

<UserControl x:Class="SilverlightApplication2.Page" xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:SilverlightApplication2" Width="400" Height="300"> <UserControl.Resources> <local:User x:Key="my" Nom="Musashi" Prenom="Myamoto" Age="32" /> <Style TargetType="TextBox" x:Key="myTextBoxStyle"> <Setter Property="Margin" Value="3" /> <Setter Property="BorderThickness" Value="2"/> <Setter Property="BorderBrush" Value="DarkViolet"/> </Style> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White"> <StackPanel DataContext="{StaticResource my}"> <TextBox x:Name="txtNom" Text="{Binding Nom}" Style="{StaticResource myTextBoxStyle}"/> <TextBox x:Name="txtPrenom" Text="{Binding Prenom}" Style="{StaticResource myTextBoxStyle}"/> <TextBox x:Name="txtAge" Text="{Binding Age}" Style="{StaticResource myTextBoxStyle}"/> <Button Content="Save" Width="150" Height="30" HorizontalAlignment="Left" Margin="3" Click="Button_Click"/> <TextBlock x:Name="txtResultat" /> </StackPanel> </Grid> </UserControl>

Et là seulement tout est terminé !

Bon eh bien, je sais pas pour vous,  mais moi après ça j'ai eu un trop plein d'émotion et j'ai appelé tous mes collègues.

 

En conclusion : mon premier sentiment

Silverlight 2.0 est relativement stable, son utilisation est vraiment très très proche de celle de WPF ce qui permet de capitaliser sur ses acquis (et ça je dis un grand bravo !).

Bien sur , il manque des choses et l'on rencontre des problèmes (un intellisense capricieux, des erreurs ,dans les resources notamment)  mais mon premier sentiment après 3h d'utilisation et une bonne stabilité et un fonctionnel (contrôles, binding, template, style ...) présent et opérationnel.

Allez je vous fait bientôt un autre Post sur le développement d'une petite application de gestion qui met en jeu des choses plus avancées notamment au niveau du Databinding...

Musashi.

Je souhaitais vous faire profiter d'une petite méthode utilitaire que j'ai réalisé cette semaine pour me faciliter la vie dans mes projets.

Si comme moi vous utilisez LINQ régulièrement et que vous l'utilisez dans le cadre de projet WPF, vous aimeriez bien pouvoir transformer le produit d'une requête LINQ en une ObservableCollection, et cela, afin de faciliter le databinding (bidirectionnelle).

Ainsi, si on observe la variable users crée comme suit :

var users = from u in UserManager.GetUsers()

where u.Age >= 18

select u;

Nous aimerions bien la lier avec une ListBox à l'aide d'une ObservableCollection comme suit :

lstUser.DataContext = users.ToObservableCollection<User>();

Techniquement, il s'agit donc de transformer une collection IEnumerable<T> (résultat de la requête LINQ) en ObservableCollection <T> pour cela, je vous propose une méthode d'extension dont le code source est le suivant :

public static class ObservableCollectionTools

{

public static ObservableCollection<TSource> ToObservableCollection<TSource>(this IEnumerable<TSource> source)

{

ObservableCollection<TSource> target = new ObservableCollection<TSource>();

using (IEnumerator<TSource> enumerator = source.GetEnumerator())

{

while (enumerator.MoveNext())

{

target.Add(enumerator.Current);

}

}

return target;

}

}

Cela facilite donc notre travail nous permettant de réaliser facilement le Databinding entre une ListBox et le résultat d'une requête LINQ.

Une fois la méthode précédente insérée dans vos projets, l'utilisation est simple comme le montre le print screen suivant :

 

Solution complète

Afin de vous présenter une mise en œuvre complète, voici un exemple, qui affiche des users à partir d'une requête LINQ, en utilisant notre méthode d'extension :

Tout d'abord le code de la fenêtre WPF qui comporte la ListBox et un DataTemplate permettant d'afficher des users (Nom, prénom, âge)

< Window x : Class ="WpfExtensionObservableCollection.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:local="clr-namespace:WpfExtensionObservableCollection"

Title="Window1" Height="391" Width="510"

Loaded="Window_Loaded">

< Window.Resources >

< DataTemplate x : Key ="dtUser" DataType ="{ x : Type local : User }">

< StackPanel Orientation ="Vertical">

< TextBlock Text ="{ Binding Path =Name}" />

< TextBlock Text ="{ Binding Path =Surname}" />

< TextBlock Text ="{ Binding Path =Age}" />

</ StackPanel >

</ DataTemplate >

</ Window.Resources >

< Grid >

< StackPanel Grid.Column ="0" Orientation ="Vertical">

< ListBox x : Name ="lstUser" ItemsSource ="{ Binding }" ItemTemplate ="{ StaticResource dtUser }" Background ="Black" Foreground ="White"></ ListBox >

</ StackPanel >

</ Grid >

</ Window >

 

Il nous faut, de plus, une classe métier « User » et son manager « UserManager » pour nous exposer tous les users disponibles.

 

public class User

{