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
- Bien démarrer (Hello World)
- Créer une interface utilisateur pour Windows Phone en XAML
- Utiliser des contrôles
- Types de contrôles
- Contrôles Panorama et Pivot
- Travailler avec du texte sur le Windows Phone
- Mise en page sur l’écran
- Orientations de l’écran
- Saisie tactile
- Navigation
- Exécuter votre application en arrière-plan (tombstoning)
- Notifications Push pour le développement Windows Phone
- Publier votre application sur le Marketplace
Visuels et média
Travailler avec les données
- Obtenir des données dans vos applications Windows Phone
- Data binding
- Isolated storage
- Accéder à un service Web REST
- Consommer des données Windows Azure
Sondes et autres fonctionnalités spécifiques au téléphone
- Lanceurs et choosers
- Détecter des mouvements (accéléromètres)
- Développer avec le GPS Windows Phone (Services de localisation)
- Développer avec l’appareil photo du Windows 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
- Lier un contrôle à une collection d'objets
- Afficher les éléments dans un contrôle en utilisant un data template
- Ajouter une vue détails
- Convertir des données pour les afficher dans des contrôles
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
- <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
- <TextBox VerticalAlignment="Top" IsReadOnly="True" Margin="5"
- TextWrapping="Wrap" Height="120" Width="400"
- Text="{Binding}" x:Name="textBox1" />
- </Grid>
C#
// Constructor
public MainPage()
{
InitializeComponent();
// Set the data context to a new Recording.
textBox1.DataContext = new Recording("Chris Sells", "Chris Sells Live",
new DateTime(2008, 2, 5));
}
// A simple business object
public class Recording
{
public Recording() { }
public Recording(string artistName, string cdName, DateTime release)
{
Artist = artistName;
Name = cdName;
ReleaseDate = release;
}
public string Artist { get; set; }
public string Name { get; set; }
public DateTime ReleaseDate { get; set; }
// Override the ToString method.
public override string ToString()
{
return Name + " by " + Artist + ", Released: " + ReleaseDate.ToShortDateString();
}
}
Visual Basic
' Constructor
Public Sub New()
InitializeComponent()
' Set the data context to a new recording.
textBox1.DataContext = New Recording("Chris Sells", "Chris Sells Live", _
New DateTime(2008, 2, 5))
End Sub
Public Class Recording
Public Sub New()
End Sub
Public Sub New(ByVal artistName As String, ByVal cdName As String, _
ByVal release As DateTime)
Artist = artistName
Name = cdName
ReleaseDate = release
End Sub
Public Property Artist As String
Public Property Name As String
Public Property ReleaseDate As DateTime
' Override ToString.
Public Overloads Overrides Function ToString() As String
Return Name + " by " + Artist + ", Released: " + releaseDate.ToShortDateString()
End Function
End Class
Voici le résultat:
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.
XAML
- <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
- <ComboBox x:Name="ComboBox1" ItemsSource="{Binding}"
- Foreground="Black" FontSize="18" Height="50" Width="400"/>
- </Grid>
C#
- public ObservableCollection<Recording> MyMusic = new ObservableCollection<Recording>();
- public Page()
- {
- InitializeComponent();
- // Add items to the collection.
- MyMusic.Add(new Recording("Chris Sells", "Chris Sells Live",
- new DateTime(2008, 2, 5)));
- MyMusic.Add(new Recording("Luka Abrus",
- "The Road to Redmond", new DateTime(2007, 4, 3)));
- MyMusic.Add(new Recording("Jim Hance",
- "The Best of Jim Hance", new DateTime(2007, 2, 6)));
- // Set the data context for the combo box.
- ComboBox1.DataContext = MyMusic;
- }
Visual Basic
Public MyMusic As New ObservableCollection(Of Recording)()
Public Sub New()
InitializeComponent()
' Add items to the collection.
MyMusic.Add(New Recording("Chris Sells", "Chris Sells Live", _
New DateTime(2008, 2, 5)))
MyMusic.Add(New Recording("Luka Abrus", "The Road to Redmond", _
New DateTime(2007, 4, 3)))
MyMusic.Add(New Recording("Jim Hance", "The Best of Jim Hance", _
New DateTime(2007, 2, 6)))
' Set the data context for the combo box.
ComboBox1.DataContext = MyMusic
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é.
XAML
- <ComboBox x:Name="ComboWithTemplate" Margin="5"
- Width="450" Height="50" HorizontalAlignment="Left"
- ItemsSource="{Binding}" Foreground="Black" FontSize="18" >
- <ComboBox.ItemTemplate>
- <DataTemplate>
- <StackPanel Orientation="Horizontal" Margin="2">
- <TextBlock Text="Artist:" Margin="2" />
- <TextBlock Text="{Binding Artist}" Margin="2" />
- <TextBlock Text="CD:" Margin="10,2,0,2" />
- <TextBlock Text="{Binding Name}" Margin="2" />
- </StackPanel>
- </DataTemplate>
- </ComboBox.ItemTemplate>
- </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.
XAML
- <!--The UI for the details view-->
- <StackPanel x:Name="RecordingDetails">
- <TextBlock FontWeight="Bold" Text="{Binding Artist}" Margin="5,0,0,0"/>
- <TextBlock FontStyle="Italic" Text="{Binding Name}" Margin="5,0,0,0"/>
- <TextBlock Text="{Binding ReleaseDate}" Margin="5,0,0,0" />
- </StackPanel>
C#
- //ComboWithTemplate.DataContext = MyMusic;
- LayoutRoot.DataContext = new CollectionViewSource { Source = MyMusic };
Visual Basic
- 'ComboWithTemplate.DataContext = MyMusic
- 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é.
XAML
<phone:PhoneApplicationPage
x:Class="MyExample.MainPage"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyExample"
...
>
<phone:PhoneApplicationPage.Resources>
<local:StringFormatter x:Key="StringConverter"/>
</phone:PhoneApplicationPage.Resources>
...
<!--ContentPanel - place content here-->
<StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ComboBox x:Name="ComboWithTemplate" Margin="5"
Width="450" Height="50" HorizontalAlignment="Left"
ItemsSource="{Binding}" Foreground="Black" FontSize="18" >
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="2">
<TextBlock Text="Artist:" Margin="2" />
<TextBlock Text="{Binding Artist}" Margin="2" />
<TextBlock Text="CD:" Margin="10,2,0,2" />
<TextBlock Text="{Binding Name}" Margin="2" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!--The UI for the details view-->
<StackPanel x:Name="RecordingDetails">
<TextBlock Text="{Binding Artist}" />
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding ReleaseDate,
Converter={StaticResource StringConverter},
ConverterParameter=Released: \\cf1 {0:d\\cf1 }}" />
</StackPanel>
</StackPanel>
...
</phone:PhoneApplicationPage>
C#
public class StringFormatter : IValueConverter
{
// This converts the value object to the string to display.
// This will work with most simple types.
public object Convert(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
// Retrieve the format string and use it to format the value.
string formatString = parameter as string;
if (!string.IsNullOrEmpty(formatString))
{
return string.Format(culture, formatString, value);
}
// If the format string is null or empty, simply
// call ToString() on the value.
return value.ToString();
}
// No need to implement converting back on a one-way binding
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Visual Basic
Public Class StringFormatter
Implements IValueConverter
' This converts the DateTime object to the string to display.
Public Function Convert(ByVal value As Object, ByVal targetType As Type, _
ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) _
As Object Implements IValueConverter.Convert
' Retrieve the format string and use it to format the value.
Dim formatString As String = TryCast(parameter, String)
If Not String.IsNullOrEmpty(formatString) Then
Return String.Format(culture, formatString, value)
End If
' If the format string is null or empty, simply call ToString()
' on the value.
Return value.ToString()
End Function
' No need to implement converting back on a one-way binding
Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, _
ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) _
As Object Implements IValueConverter.ConvertBack
Throw New NotImplementedException()
End Function
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.