Developpement Windows Phone - partie 20

Data Binding

Cet article fait partie d’une série d’articles sur le développement Windows Phone. Il s’agit d’une traduction des articles se trouvant sur la MSDN.

Sommaire

Bien débuter et fondamentaux

Visuels et média

Travailler avec les données

Sondes et autres fonctionnalités spécifiques au téléphone


Data Binding

La plupart des applications Windows Phone affichent des données dans les contrôles. Dans de nombreux cas, les données sont des objets business tels que des actions en bourse, des titres de news ou des images. En plus, vous voulez souvent autoriser l'utilisateur à sélectionner un élément depuis une liste puis afficher les détails relatifs à cet élément dans un autre contrôle comme par exemple une zone de texte.

Ce tutoriel montre comment lier un contrôle à un simple élément et comment lier un contrôle de liste à une collection d'éléments, De plus, vous verrez au sein de cet article comment personnaliser l'affichage des éléments, comment implémenter une vue détaillée basée sur une sélection et comment convertir les données avant de les afficher.

Ce tutoriel contient les sections suivantes:

Lier un contrôle à un élément unique

Une liaison de données (data binding) consiste en une source et une cible. La cible du binding est généralement une propriété d'un contrôle et doit être une DependencyProperty.

L'exemple suivant montre un contrôle lié à un élément unique. La cible est la propriété Text d'un contrôle Textbox. La source est une simple classe Recording.

XAML

  1. <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  2. <TextBox VerticalAlignment="Top" IsReadOnly="True" Margin="5"
  3. TextWrapping="Wrap" Height="120" Width="400"
  4. Text="{Binding}" x:Name="textBox1" />
  5. </Grid>

C#

  1. // Constructor

  2. public MainPage()

  3. {

  4. InitializeComponent();

  5. // Set the data context to a new Recording.

  6. textBox1.DataContext = new Recording("Chris Sells", "Chris Sells Live",

  7. new DateTime(2008, 2, 5));

  8. }

  9. // A simple business object

  10. public class Recording

  11. {

  12. public Recording() { }

  13. public Recording(string artistName, string cdName, DateTime release)

  14. {

  15. Artist = artistName;

  16. Name = cdName;

  17. ReleaseDate = release;

  18. }

  19. public string Artist { get; set; }

  20. public string Name { get; set; }

  21. public DateTime ReleaseDate { get; set; }

  22. // Override the ToString method.

  23. public override string ToString()

  24. {

  25. return Name + " by " + Artist + ", Released: " + ReleaseDate.ToShortDateString();

  26. }

  27. }

Visual Basic

  1. ' Constructor

  2. Public Sub New()

  3. InitializeComponent()

  4. ' Set the data context to a new recording.

  5. textBox1.DataContext = New Recording("Chris Sells", "Chris Sells Live", _

  6. New DateTime(2008, 2, 5))

  7. End Sub

  8. Public Class Recording

  9. Public Sub New()

  10. End Sub

  11. Public Sub New(ByVal artistName As String, ByVal cdName As String, _

  12. ByVal release As DateTime)

  13. Artist = artistName

  14. Name = cdName

  15. ReleaseDate = release

  16. End Sub

  17. Public Property Artist As String

  18. Public Property Name As String

  19. Public Property ReleaseDate As DateTime

  20. ' Override ToString.

  21. Public Overloads Overrides Function ToString() As String

  22. Return Name + " by " + Artist + ", Released: " + releaseDate.ToShortDateString()

  23. End Function

  24. End Class

Voici le résultat:

image_thumb1

Pour afficher un enregistrement musical dans une zone de texte, la propriété Text du contrôle est définie sur un Binding en utilisant une extension de balisage (markup extension). Dans cet exemple, le mode de binding par défaut est BindingMode.OneWay, ce qui signifie que les données sont récupérées de la source, mais les changements ne sont pas propagés vers la source. Pour plus d'informations sur les markup extensions et leur syntaxe, lisez l'article MSDN Binding Markup Extension.

La classe Recording possède trois propriétés publiques et une surcharge de la méthode ToString(). Les propriétés sont Artist, Name, et ReleaseDate. La méthode ToString est importante car si aucun formatage n'est spécifié, la méthode ToString est appelée sur un objet lié pour des raisons d'affichage. La propriété Binding.Source n'est pas définie directement, au contraire, la propriété FrameworkElement.DataContext de la TextBox est paramétrée sur un nouvel objet Recording.

Lier un contrôle à une collection d'objets

L'exemple suivant démontre la syntaxe que vous utilisez pour lier des données à un contrôle mais n'est pas très réaliste. Un scénario plus commun est de lier une collection d'objets métier. La classe générique ObservableCollection est un bon choix pour le data binding car elle implémente les interfaces INotifyPropertyChanged et INotifyCollectionChanged. Ces interfaces fournissent les notifications de changement aux contrôles liés lorsque qu'un élément de la liste ou une propriété de la liste elle-même change. Si vous voulez que vos contrôles liés se mettent à jour lorsque les propriétés des objets de la collection changent, alors ces objets doivent également implémenter INotifyPropertyChanged.

L'exemple suivant lie une collection d’enregistrements musicaux à une ComboBox. Cliquez sur la flèche de la combobox pour voir la liste des éléments liés.

Get Microsoft Silverlight

XAML

  1. <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  2. <ComboBox x:Name="ComboBox1" ItemsSource="{Binding}"
  3. Foreground="Black" FontSize="18" Height="50" Width="400"/>
  4. </Grid>

C#

  1. public ObservableCollection<Recording> MyMusic = new ObservableCollection<Recording>();
  2. public Page()
  3. {
  4. InitializeComponent();
  5. // Add items to the collection.
  6. MyMusic.Add(new Recording("Chris Sells", "Chris Sells Live",
  7. new DateTime(2008, 2, 5)));
  8. MyMusic.Add(new Recording("Luka Abrus",
  9. "The Road to Redmond", new DateTime(2007, 4, 3)));
  10. MyMusic.Add(new Recording("Jim Hance",
  11. "The Best of Jim Hance", new DateTime(2007, 2, 6)));
  12. // Set the data context for the combo box.
  13. ComboBox1.DataContext = MyMusic;
  14. }

Visual Basic

  1. Public MyMusic As New ObservableCollection(Of Recording)()

  2. Public Sub New()

  3. InitializeComponent()

  4. ' Add items to the collection.

  5. MyMusic.Add(New Recording("Chris Sells", "Chris Sells Live", _

  6. New DateTime(2008, 2, 5)))

  7. MyMusic.Add(New Recording("Luka Abrus", "The Road to Redmond", _

  8. New DateTime(2007, 4, 3)))

  9. MyMusic.Add(New Recording("Jim Hance", "The Best of Jim Hance", _

  10. New DateTime(2007, 2, 6)))

  11. ' Set the data context for the combo box.

  12. ComboBox1.DataContext = MyMusic

  13. End Sub

Pour afficher les enregistrements musicaux dans la ComboBox, la propriété ItemsControl.ItemsSource est définie sur un Binding, et la propriété FrameworkElement.DataContext du contrôle ComboBox est définie sur une collection d'objets Recording. Un ComboBoxItem est créé pour chaque élément de la collection. La méthode ToString est automatiquement appelée sur chaque objet Recording à afficher dans l'item de la combobox.

Afficher les éléments dans un contrôle en utilisant un data template

Vous pouvez afficher les éléments dans une liste en utilisant la méthode ToString() de chaque élément. Néanmoins, le scénario le plus courant est de fournir un affichage personnalisé grâce à l'utilisation d'un DataTemplate. Un DataTemplate vous permet de personnaliser la façon dont les éléments sont affichés dans le contrôle. Typiquement, vous définissez le data template en utilisant la propriété ContentControl.ContentTemplate d'un contrôle de contenu ou la propriété ItemsControl.ItemTemplate d'un contrôle à éléments.

L'exemple suivant montre la même liste d’enregistrements liés à une combobox en utilisant un data template. Une combobox est un ItemsControl, ce qui signifie que vous établissez un data template pour chaque élément en définissant sa propriété ItemTemplate sur un data template. Pour essayer cet exemple, cliquez sur la flèche du bas pour voir la liste des enregistrements. Notez comment l'enregistrement apparait différemment de l'exemple suivant. L'artiste et le nom du CD sont affichés dans un format personnalisé.

Get Microsoft Silverlight

XAML

  1. <ComboBox x:Name="ComboWithTemplate" Margin="5"
  2. Width="450" Height="50" HorizontalAlignment="Left"
  3. ItemsSource="{Binding}" Foreground="Black" FontSize="18" >
  4. <ComboBox.ItemTemplate>
  5. <DataTemplate>
  6. <StackPanel Orientation="Horizontal" Margin="2">
  7. <TextBlock Text="Artist:" Margin="2" />
  8. <TextBlock Text="{Binding Artist}" Margin="2" />
  9. <TextBlock Text="CD:" Margin="10,2,0,2" />
  10. <TextBlock Text="{Binding Name}" Margin="2" />
  11. </StackPanel>
  12. </DataTemplate>
  13. </ComboBox.ItemTemplate>
  14. </ComboBox>

Dans le XAML, vous pouvez voir la définition du data template. Le data template contient un StackPanel avec quatre contrôles TextBlock. Le StackPanel a une orientation horizontale pour que les quatre blocs de texte apparaissent côte à côte. Deux des contrôles TextBlock sont liés aux propriétés Artist et Name de l'objet Recording. Les deux autres contrôles TextBlock affichent du texte statique. Pour chaque élément lié, le binding fournit le chemin vers la propriété sur l'objet Recording. Comme dans l'exemple précédent, ce binding se base sur le fait que le data context soit lié à la liste des objets Recordings.

Ce XAML utilise la syntaxe par propriété d'élément. Pour plus d'informations sur cette syntaxe, lisez le tutoriel XAML QuickStart.

Ajouter une vue détails

Pour afficher les détails d'un élément lorsqu'il est sélectionné dans une collection, vous devez créer une UI appropriée et lier l'UI aux données que vous voulez afficher. De plus, vous devez utiliser une CollectionViewSource en tant que contexte de données pour permettre à la vue détails de lier l'élément courant.

L'exemple suivant montre la même liste d'enregistrements mais cette fois la liste est la source de données d'une instance de CollectionViewSource. Le contexte de données de l'élément racine du layout est défini sur la CollectionViewSource et la combobox ainsi que la vue détails héritent du contexte de données de l'élément racine. Cela permet à la combobox d'afficher la liste d'éléments pendant que la vue détails affiche les informations de l'élément courant.

Get Microsoft Silverlight

XAML

  1. <!--The UI for the details view-->
  2. <StackPanel x:Name="RecordingDetails">
  3. <TextBlock FontWeight="Bold" Text="{Binding Artist}" Margin="5,0,0,0"/>
  4. <TextBlock FontStyle="Italic" Text="{Binding Name}" Margin="5,0,0,0"/>
  5. <TextBlock Text="{Binding ReleaseDate}" Margin="5,0,0,0" />
  6. </StackPanel>

C#

  1. //ComboWithTemplate.DataContext = MyMusic;
  2. LayoutRoot.DataContext = new CollectionViewSource { Source = MyMusic };

Visual Basic

  1. 'ComboWithTemplate.DataContext = MyMusic
  2. LayoutRoot.DataContext = New CollectionViewSource With {.Source = MyMusic}

Dans cet exemple, un StackPanel est ajouté au user control qui contient la combobox existante. Un Rectangle sert de ligne de division sous la ComboBox. A côté se trouve un StackPanel qui contient quatre blocs pour afficher les détails de l'enregistrement. La propriété TextBlock.Text de chaque bloc de texte est liée à une propriété de l'objet Recording.

Convertir des données pour les afficher dans des contrôles

Si vous voulez formater et afficher un type non-string dans un contrôle, tel qu'un textbox, vous pouvez utiliser un convertisseur. Par exemple, vous pourriez afficher un label et une date formatée plutôt que la date. (Note : vous pouvez utiliser la propriété BindingBase.StringFormat si vous souhaitez uniquement modifier le format de la date.)

L'exemple suivant montre l'implémentation d'un convertisseur pour la date de sortie dans la liste des enregistrements. Pour essayer cet exemple, cliquez sur la flèche du combobox et sélectionnez un élément différent. Notez que l'affichage de la date dans la liste déroulante et dans la vue détaillée est affiché dans un format personnalisé.

Get Microsoft Silverlight

XAML

  1. <phone:PhoneApplicationPage

  2. x:Class="MyExample.MainPage"

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

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

  5. xmlns:local="clr-namespace:MyExample"

  6. ...

  7. >

  8. <phone:PhoneApplicationPage.Resources>

  9. <local:StringFormatter x:Key="StringConverter"/>

  10. </phone:PhoneApplicationPage.Resources>

  11. ...

  12. <!--ContentPanel - place content here-->

  13. <StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

  14. <ComboBox x:Name="ComboWithTemplate" Margin="5"

  15. Width="450" Height="50" HorizontalAlignment="Left"

  16. ItemsSource="{Binding}" Foreground="Black" FontSize="18" >

  17. <ComboBox.ItemTemplate>

  18. <DataTemplate>

  19. <StackPanel Orientation="Horizontal" Margin="2">

  20. <TextBlock Text="Artist:" Margin="2" />

  21. <TextBlock Text="{Binding Artist}" Margin="2" />

  22. <TextBlock Text="CD:" Margin="10,2,0,2" />

  23. <TextBlock Text="{Binding Name}" Margin="2" />

  24. </StackPanel>

  25. </DataTemplate>

  26. </ComboBox.ItemTemplate>

  27. </ComboBox>

  28. <!--The UI for the details view-->

  29. <StackPanel x:Name="RecordingDetails">

  30. <TextBlock Text="{Binding Artist}" />

  31. <TextBlock Text="{Binding Name}" />

  32. <TextBlock Text="{Binding ReleaseDate,

  33. Converter={StaticResource StringConverter},

  34. ConverterParameter=Released: \\cf1 {0:d\\cf1 }}" />

  35. </StackPanel>

  36. </StackPanel>

  37. ...

  38. </phone:PhoneApplicationPage>

C#

  1. public class StringFormatter : IValueConverter

  2. {

  3. // This converts the value object to the string to display.

  4. // This will work with most simple types.

  5. public object Convert(object value, Type targetType,

  6. object parameter, System.Globalization.CultureInfo culture)

  7. {

  8. // Retrieve the format string and use it to format the value.

  9. string formatString = parameter as string;

  10. if (!string.IsNullOrEmpty(formatString))

  11. {

  12. return string.Format(culture, formatString, value);

  13. }

  14. // If the format string is null or empty, simply

  15. // call ToString() on the value.

  16. return value.ToString();

  17. }

  18. // No need to implement converting back on a one-way binding

  19. public object ConvertBack(object value, Type targetType,

  20. object parameter, System.Globalization.CultureInfo culture)

  21. {

  22. throw new NotImplementedException();

  23. }

  24. }

Visual Basic

  1. Public Class StringFormatter

  2. Implements IValueConverter

  3. ' This converts the DateTime object to the string to display.

  4. Public Function Convert(ByVal value As Object, ByVal targetType As Type, _

  5. ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) _

  6. As Object Implements IValueConverter.Convert

  7. ' Retrieve the format string and use it to format the value.

  8. Dim formatString As String = TryCast(parameter, String)

  9. If Not String.IsNullOrEmpty(formatString) Then

  10. Return String.Format(culture, formatString, value)

  11. End If

  12. ' If the format string is null or empty, simply call ToString()

  13. ' on the value.

  14. Return value.ToString()

  15. End Function

  16. ' No need to implement converting back on a one-way binding

  17. Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, _

  18. ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) _

  19. As Object Implements IValueConverter.ConvertBack

  20. Throw New NotImplementedException()

  21. End Function

  22. End Class

Un convertisseur (converter) est une classe qui implémente l'interface IValueConverter. IValueConverter possède deux méthodes : Convert et ConvertBack. Pour un binding unidirectionnel (one-way) de la source vers la cible, vous n'avez besoin que d'implémenter la méthode Convert. Le convertisseur dans cet exemple est très générique. Vous pouvez passer la chaine de formatage comme paramètre et le convertisseur utilisera la méthode Format pour effectuer la conversion. Si aucune chaine de formatage n'est passée alors le convertisseur appelle simplement la méthode ToString() sur l'objet.

Une fois que vous implémentez le convertisseur, vous créez une instance de la classe du convertisseur et dites au binding d'utiliser cette instance. Dans cet exemple, ceci est effectué en XAML. Une instance du convertisseur est créée en tant que ressource statique et est assignée à une clé. La clé est utilisée lorsque la propriété Converter est définie par le binding.

Pour plus d'informations sur l'utilisation des convertisseurs, lisez la documentation IValueConverter sur MSDN.

Voir aussi


Cliquez ici pour revenir au sommaire de la liste d’articles