Share via


Cet article a fait l'objet d'une traduction automatique.

Windows Phone

Liaison de données Windows Phone

Jesse Liberty

Téléchargez l'exemple de Code

Pratiquement chaque application Windows Phone utile a certains types de données, et la capacité de relier les données aux éléments de l'interface utilisateur (la vue) est absolument essentielle.Il existe plusieurs façons de le faire par programmation (affectation de valeurs que vous allez), mais une des caractéristiques plus puissants et les plus essentiels de la programmation de XAML est la capacité à lier des données aux contrôles.

Voici la bonne nouvelle :

  • Il n'est pas difficile à comprendre.
  • Il n'est pas difficile à mettre en œuvre.

Pour illustrer la liaison de données, vous allez créer la page montrée Figure1.Lorsqu'il charge, il sera rempli d'un objet de la personne que vous allez créer.Chaque valeur dans l'interface utilisateur sera lié à une propriété dans l'objet de la personne, et la liaison réelle des données aux contrôles sera automatique, pas besoin de code c#.

The Data Binding View in Windows PhoneFigure 1 vue de liaison de données dans Windows Phone

 Mise en route

Pour commencer, créez une nouvelle application Windows Phone dans Visual Studio et nommez-le DataBinding.Commencez par créer la classe qui servira de données à laquelle vous allez lier (également connu sous le nom le DataContext).Faites un clic droit sur le projet et sélectionnez Ajouter | Nouveau | Classe et nom de la classe Person.cs.

Personne contiendra (au moins) toutes les propriétés que vous voudrez afficher dans l'affichage.La classe se compose d'une énumération et un ensemble de propriétés automatiques, comme le montre Figure 2.

La figure 2 la classe Person

public class Person
{
  public enum Sex
  {
    Male,
    Female,
  }
  public string Name { get; set; }
  public bool Moustache { get; set; }
  public bool Goatee { get; set; }
  public bool Beard { get; set; }
  public Sex WhichSex { get; set; }
  public double Height { get; set; }
  public DateTime BirthDate { get; set; }
  public bool Favorite { get; set; }
}

Vous pouvez le voir assez rapidement comment ces propriétés mappent aux divers contrôles d'entrée montre Figure 1. Les valeurs booléennes peuvent être soit des cases à cocher ou des cases d'option (selon qu'ils sont mutuellement exclusifs).

Création de la forme

La tâche suivante consiste à créer le formulaire, que vous allez utiliser pour lier les données. Faites un clic droit sur le projet et sélectionnez « Ouvrir dans Expression Blend ». En règle générale, j'ai tendance à créer mon UI dans Expression Blend et écrire mon code dans Visual Studio.

Créer des six lignes et deux colonnes dans la grille de contenu et faites glisser sur les contrôles d'entrée appropriés. Figure 3 affiche le code XAML vous aurez envie de produire.

La figure 3 le code XAML pour créer le formulaire

<Grid
  x:Name="ContentPanel"
  Grid.Row="1"
  Margin="24,0,0,0">
  <Grid.ColumnDefinitions>
    <ColumnDefinition
      Width="0.384*" />
    <ColumnDefinition
      Width="0.616*" />
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition
      Height="0.1*" />
    <RowDefinition
      Height="0.1*" />
    <RowDefinition
      Height="0.1*" />
    <RowDefinition
      Height="0.1*" />
    <RowDefinition
      Height="0.1*" />
    <RowDefinition
      Height="0.1*" />
    <RowDefinition
      Height="0.2*" />
  </Grid.RowDefinitions>
  <TextBlock
    x:Name="NamePrompt"
    TextWrapping="Wrap"
    Text="Name"
    Grid.Row="0"
    HorizontalAlignment="Left"
    VerticalAlignment="Center" />
  <TextBlock
    x:Name="SexPrompt"
    Grid.Row="2"
    TextWrapping="Wrap"
    HorizontalAlignment="Left"
    VerticalAlignment="Center"
    Text="Sex" />
  <TextBlock
    x:Name="HeightPrompt"
    TextWrapping="Wrap"
    Text="Height, StringFormat=F3"
    HorizontalAlignment="Left"
    Grid.Row="3"
    d:LayoutOverrides="Height"
    VerticalAlignment="Center" />
  <TextBlock
    x:Name="FavoritePrompt"
    TextWrapping="Wrap"
    Text="Favorite"
    HorizontalAlignment="Left"
    Grid.Row="4"
    d:LayoutOverrides="Height"
    VerticalAlignment="Center" />
  <TextBox
    x:Name="Name"
    TextWrapping="Wrap"
    d:LayoutOverrides="Height"
    Grid.Column="1"
    HorizontalAlignment="Left"
    Width="200"
    VerticalAlignment="Center"
    Text="{Binding Name}" />
  <StackPanel
    x:Name="BeardStackPanel"
    Grid.ColumnSpan="2"
    Grid.Row="1"
    Orientation="Horizontal">
    <CheckBox
      x:Name="Moustache"
      Content="Moustache"
      HorizontalAlignment="Left"
      VerticalAlignment="Center"
      IsChecked="{Binding Moustache}" />
    <CheckBox
      x:Name="Goatee"
      Content="Goatee"
      IsChecked="{Binding Goatee}" />
    <CheckBox
      Content="Beard"
      IsChecked="{Binding Beard}"/>
  </StackPanel>
  <StackPanel
    x:Name="SexStackPanel"
    Grid.Column="1"
    Grid.Row="2"
    Orientation="Horizontal">
    <RadioButton
      x:Name="Male"
      Content="Male"
      IsChecked="True"
      GroupName="Sex" />
    <RadioButton
      x:Name="Female"
      Content="Female"
      GroupName="Sex" />
  </StackPanel>
  <StackPanel
    x:Name="HeightStackPanel"
    Grid.Column="1"
    Grid.Row="3"
    Orientation="Horizontal">
    <TextBlock
      TextWrapping="Wrap"
      Text="{Binding Height}"
      VerticalAlignment="Center"
      HorizontalAlignment="Left"
      Margin="0,0,0,0" />
    <TextBlock
      VerticalAlignment="Center"
      HorizontalAlignment="Left"
      Margin="5,0,0,0"
      Text="meters" />
  </StackPanel>
  <ToggleButton
    x:Name="Favorite"
    Content="Favorite"
    Grid.Column="1"
    Grid.Row="4"
    d:LayoutOverrides="Width, Height"
    HorizontalAlignment="Left"
    VerticalAlignment="Center"
    IsChecked="{Binding Favorite}" />
</Grid>

Liaison

Chacun des champs de saisie de texte a maintenant sa valeur définie à l'aide de la syntaxe de liaison. Par exemple, pour indiquer la zone de texte à lier, déterminer lequel de ses attributs exigera des données — dans ce cas, l'attribut de texte — et utiliser la syntaxe de liaison, comme indiqué précédemment.

Liaisons sont dans les accolades, et ils utilisent le mot clé obligatoire, généralement suivi du nom de la propriété à laquelle vous êtes lie l'attribut. Par exemple, ce code XAML déclare que le texte de la zone de texte est obtenus par une propriété publique nommée Nom :

<TextBox
  x:Name="Name"
  TextWrapping="Wrap"
  d:LayoutOverrides="Height"
  Grid.Column="1"
  HorizontalAlignment="Left"
  Width="200"
  VerticalAlignment="Center"
  Text="{Binding Name}" />

De même, avec les cases à cocher pour les poils du visage, la propriété IsChecked est liée à la propriété appropriée :

<CheckBox
  x:Name="Moustache"
  Content="Moustache"
  HorizontalAlignment="Left"
  VerticalAlignment="Center"
  IsChecked="{Binding Moustache}" />

Vous ne savez pas encore quel objet aura ces propriétés (nom et Moustache). Tel que mentionné précédemment, l'objet qui contient la propriété pouvant être liée est connu comme le DataContext. Il peut être n'importe quoi, mais dans ce cas, vous allez créer une instance de la classe personne, et puis vous allez définir cet objet personne est le DataContext de la vue d'ensemble.

Notez que vous pouvez définir un DataContext d'un conteneur, dans ce cas la page, et tous les contrôles de la vue à l'intérieur de ce conteneur seront partageront ce DataContext — même si vous êtes libre d'attribuer d'autres données­contextes à un ou plusieurs contrôles individuels.

Vous pouvez instancier la personne dans le gestionnaire d'événements de chargement de la page codebehind. L'événement Loaded est appelé une fois le chargement de la page et les contrôles sont initialisés, comme le montre Figure 4.

Figure 4 l'événement Loaded est appelé sur la Page de chargement

private Person _currentPerson;
private Random _rand = new Random();
public MainPage()
{
  InitializeComponent();
  Loaded += MainPage_Loaded;
}
void MainPage_Loaded( object sender, RoutedEventArgs e )
{
  _currentPerson = new Person
  {
    Beard = false,
    Favorite = true,
    Goatee = false,
    Height = 1.86,
    Moustache = true,
    Name = "Jesse",
    WhichSex = Person.Sex.Male
  };
}

Maintenant, vous pouvez définir le DataContext pour chaque contrôle dans le ContentPanel l'objet _currentPerson que vous juste instancié (dans le gestionnaire de l'événement Loaded) :

ContentPanel.DataContext = _currentPerson;

Une fois qu'il sait son DataContext, TextBox peut résoudre la propriété Name et obtenir la valeur (« Jesse ») à afficher. Le même est vrai pour tous les autres contrôles, chacun lié à une propriété dans le nouvel objet personne.

Exécutez l'application et vous devriez voir tous les champs liés de façon appropriée.

Changer le DataContext

Pour conduire la maison la relation entre la fixation et l'affichage, Let's créer un certain nombre d'objets Person et afficher un par un. Pour ce faire, modifiez MainPage.xaml.cs pour créer une liste de personnes (créés au hasard) et ensuite effectuer une itération dans la liste avec un nouveau bouton « Next » sur l'interface, vous devez ajouter à la rangée du Bas :

<Button
  Name="Next"
  Content="Next"
  Grid.Row="5"
  HorizontalAlignment="Center"
  VerticalAlignment="Center" />

Voici le code modifié pour interagir avec le bouton suivant :

void MainPage_Loaded( object sender, RoutedEventArgs e )
{
  SetDataContext();
  Next.Click += Next_Click;
}
private void SetDataContext()
{
  ContentPanel.DataContext = GeneratePerson();
}
void Next_Click( object sender, RoutedEventArgs e )
{
  SetDataContext();
}

Avis de fois la page chargée l'événement et le gestionnaire d'événements click pour le bouton suivant doit définir le DataContext, donc j'ai factorisé que sortir en une méthode distincte : SetDataContext. Cette méthode appelle à son tour, la méthode de GeneratePerson, dont le travail consiste à créer une personne au hasard.

Vous pouvez maintenant faire toutes les modifications dans le codebehind. Tout d'abord, arrêter la personne actuelle de câblage et au lieu de le définir en appelant la méthode GeneratePerson.

Génération d'une personne au hasard

Voici l'ensemble de la méthode GeneratePerson ; vous verrez que j'ai pris en compte la tâche de choisir une valeur true ou false dans une méthode appelée FlipCoin :

private Person GeneratePerson()
{
  var newPerson = new Person
  {
    Beard = FlipCoin(),
    Favorite = FlipCoin(),
    Goatee = FlipCoin(),
    Height = _rand.NextDouble() + 1,
    Moustache = FlipCoin(),
    Name = names[_rand.Next(0, names.Count - 1)]
  };
  return newPerson;
}

FlipCoin utilise le générateur de nombres aléatoires pour retourner true 50 % du temps :

private  bool FlipCoin()
{
  return _rand.Next( 1, 3 ) % 2 == 0;
}

Enfin, pour choisir un nom, créer une liste de noms une demi-douzaine qui peuvent être assignés à des hommes ou des femmes et utiliser le générateur de nombres aléatoires pour choisir un décalage dans la liste :

private readonly List<string> names = new List<string>()
{
  "Stacey",
  "Robbie",
  "Jess",
  "Robin",
  "Syd",
  "J.J.",
  "Terri",
  "Moonunit",
};

Exécutez l'application et cliquez sur le bouton suivant. Chaque objet personne est créée, elle est définie comme DataContext et ses propriétés sont liées à des contrôles d'interface utilisateur.

INotifyPropertyChanged

Que se passe-t-il si l'une des propriétés de votre objet personne change ? Cela pourrait facilement se produire si l'objet est contenu dans une base de données et d'autres utilisateurs ont accès à l'objet même. Vous vouliez votre interface utilisateur mise à jour.

Pour que cela fonctionne, votre classe (le DataContext) doit implémenter INotifyPropertyChanged — une interface simple qui permet à chaque propriété d'informer l'interface utilisateur lorsque la valeur change. Il est courant de créer une méthode d'assistance qui vérifie pour s'assurer que l'événement a au moins une méthode inscrite à ce. Dans l'affirmative, la méthode déclenche l'événement, passant au nom de la propriété mise à jour.

Pour voir cela au travail, ajouter un nouveau bouton à l'interface utilisateur, changement de nom. Lorsque vous cliquez sur le bouton modifier, changez la propriété nom de « Jacob » :

void Change_Click( object sender, RoutedEventArgs e )
{
  _currentPerson.Name = "Jacob";
}

Cela aura aucun effet à moins que la personne implémente INotifyPropertyChanged et la propriété Name déclenche l'événement PropertyChanged, comme le montre Figure 5.

Figure 5 l'Interface INotifyPropertyChanged

public class Person : INotifyPropertyChanged
{
  public string _name;
  public string Name
  {
    get { return _name; }
    set
    {     
      _name = value;
      PropChanged( "Name" );
    }
  }
// Other properties
  public event PropertyChangedEventHandler PropertyChanged;
  private void PropChanged(string propName)
  {
    if (PropertyChanged != null)
    {
      PropertyChanged( this, new PropertyChangedEventArgs( propName ) );
    }
  }
}

Dans ce lieu, lorsque vous cliquez sur le bouton modifier le nom indiqué dans l'interface utilisateur va changer pour le nouveau nom de l'objet (Jacob).

Liaison bidirectionnelle

Que se passe-t-il si l'utilisateur interagit avec l'interface utilisateur et modifie une valeur directement (par exemple, les types un nouveau nom dans la zone de texte nom) ? (Généralement), vous aurez envie que changement vers l'arrière pour les données sous-jacentes (l'objet DataContext). Pour ce faire, vous allez utiliser la liaison bidirectionnelle.

Pour modifier le programme à utiliser une liaison bidirectionnelle sur la propriété Name, trouver la liaison de nom et le modifier pour cela :

<TextBox
  x:Name="Name"
  TextWrapping="Wrap"
  d:LayoutOverrides="Height"
  Grid.Column="1"
  HorizontalAlignment="Left"
  Width="200"
  VerticalAlignment="Center"
  Text="{Binding Name, Mode=TwoWay}" />

Il existe trois modes de liaison :

  1. Liaison unique signifie que les données sont liées, mais alors jamais mis à jour, même si les données sont mises à jour par l'utilisateur.
  2. Liaison unidirectionnelle est la valeur par défaut ; données sont extraite de la source de l'interface utilisateur mais pas repoussées à la source.
  3. Liaison bidirectionnelle permet aux données d'être extraite de la source et repoussée à la source, si dans l'interface utilisateur de modification.

Liaison d'élément

Changer la ligne pour le bouton suivant pour la ligne 6 et faites glisser un contrôle de curseur sur la ligne 5. Il y a un certain nombre de paramètres qui sont importants pour un curseur, y compris :

  • Minimum
  • Maximale
  • Value
  • LargeChange
  • SmallChange

Vous pouvez voir ces reflétée dans le code de Figure 6.

La figure 6, ajout d'un curseur

<Slider
  x:Name="Likability"
  Grid.Row="5"
  Grid.Column="0"
  BorderBrush="White"
  BorderThickness="1"
  Background="White"
  Foreground="Blue"
  LargeChange="10"
  SmallChange="1"
  Minimum="0"
  Width="199"
  Maximum="100"
  Value="50"
  Height="90" />

Minimale et maximale définie la plage du curseur. Dans ce cas, parce que je suis en utilisant les pourcentages, j'ai défini les 0 et 100, respectivement.

Valeur est la valeur actuelle du slider et sera : Minimum < = valeur < = Maximum

LargeChange et SmallChange sont utilisés autant qu'ils sont dans les barres de défilement ; ils indiquent quels en cliquant sur le curseur fera et ce qu'en utilisant un autre contrôle (peut-être les flèches) à progressivement le curseur fera, respectivement.

Mettre en place les TextBlocks

Dans la colonne de droite, vous allez utiliser trois TextBlocks ; le premier et le troisième comme fixe des étiquettes (avec les valeurs « amabilité: » et « % », respectivement). Le milieu TextBlock affiche une représentation numérique de la valeur du curseur.

Pour ce faire, lier la propriété valeur texte du TextBlock moyen à la propriété Value du slider, identification de l'élément que vous êtes à une liaison avec le mot clé ElementName, comme le montre Figure 7.

La figure 7, liaison à la propriété Value d'un TextBlock

<StackPanel
  x:Name="LikeabilityPercentStackPanel"
  Grid.Row="5"
  Grid.Column="1"
  Orientation="Horizontal">
  <TextBlock
    Text="Likeability: "
    HorizontalAlignment="Left"
    VerticalAlignment="Center"
    Margin="20,0,5,0" />
  <TextBlock
    x:Name="SliderValue"
    Text="{Binding Value, ElementName=Likeability, StringFormat=F3}"
    HorizontalAlignment="Left"
    VerticalAlignment="Center"
    Margin="5,0,0,0"/>
  <TextBlock
    Text="%"
    HorizontalAlignment="Left"
    VerticalAlignment="Center" />
</StackPanel>

Exécutez le programme. Le curseur est modifié, la valeur dans le TextBlock est mis à jour instantanément.

Convertisseurs de données

Certaines propriétés ne se lient correctement à un contrôle d'interface utilisateur donné, ou vous pourriez plus de contrôle sur la façon dont la valeur est affichée. Un exemple simple, nous allons afficher date de naissance de l'utilisateur en descendre une rangée de boutons et en insérant une ligne avec une invite (« date de naissance ») et la valeur de date de naissance de la personne.

Pour ce faire, vous devez modifier la méthode GeneratePerson dans MainPage.xaml.cs pour générer une date de naissance valide, que vous faites en ajoutant cette ligne pour créer une date de naissance au hasard dans le passé 20 ans :

BirthDate = DateTime.Now - TimeSpan.FromDays(_rand.Next(1,365*20)),

Si vous liez simplement à la propriété Date de naissance, vous verrez la date de naissance et l'heure. Mais vous ne voulez pas le temps, seulement la date, au format de date courte. Pour ce faire, vous devez un DataConverter.

DataConverters sont les classes qui implémentent IValueConverter. Cette interface requiert deux méthodes, dans Figure 8.

Figure 8 l'Interface IValueConverter

public object Convert(
  object value,
  Type targetType,
  object parameter,
  System.Globalization.CultureInfo culture )
{
  throw new NotImplementedException();
}
public object ConvertBack(
  object value,
  Type targetType,
  object parameter,
  System.Globalization.CultureInfo culture )
{
  throw new NotImplementedException();
}

Dans ce cas, vous devez seulement le premier des deux (le second sera jamais appelé). La méthode est assez simple à mettre en œuvre ; Assurez-vous que le type cible est string et le type valeur DateTime. Dans ce cas, prendre de la valeur, il cast en DateTime et puis appelez ToShortDateString, comme dans Figure 9.

Figure 9 la méthode Convert pour raccourcir un DateTime

public object Convert(
  object value,
  Type targetType,
  object parameter,
  System.Globalization.CultureInfo culture )
{
  if (targetType == typeof( string ) &&
    value.GetType() == typeof( DateTime ))
  {
    return (( DateTime ) value).ToShortDateString();
  }
  else  // Unable to convert
  {
    return value;
   }
}
public object ConvertBack(
  object value,
  Type targetType,
  object parameter,
  System.Globalization.CultureInfo culture )
{
  throw new NotImplementedException();
}

Dans ce lieu, vous avez besoin d'un moyen pour le code XAML accéder au convertisseur de valeur ; vous pouvez accomplir cela en rendant le convertisseur une ressource. Ouvrez App.xaml et ajouter un espace de noms pour votre convertisseur, basée sur l'espace de noms de votre application :

xmlns:mine="clr-namespace:DataBinding">

Ensuite, dans le même fichier, recherchez le <Application.Resource> l'article et ajouter une ressource pour votre convertisseur de valeur :

<Application.Resources>
  <mine:DateConverter   x:Key="dateConverter" />
</Application.Resources>

Vous pouvez maintenant utiliser la clé dans votre fichier XAML. Mise à jour de la fixation de la date de naissance à utiliser la ressource :

<TextBlock
  Grid.Row="6"
  Grid.Column="1"
  VerticalAlignment="Center"
  Text="{Binding BirthDate, Converter={StaticResource dateConverter}}" />

Exécutez le programme et vous devriez voir la date indiquée en bref format de date.

Applications puissantes

Liaison de données vous permet de créer des applications puissantes de Windows Phone fiable de gérer la relation entre les données sous-jacentes et les contrôles et les vues qui affichent les données. Dans cet article, vous avez vu comment créer la liaison de données simples et la liaison de données bidirectionnelle, comment lier à des éléments et comment utiliser des convertisseurs de données pour massage les données dans le format que vous souhaitez.

Jesse Liberty est un évangéliste expérimenté pour la communauté des développeurs au sein de l'équipe Windows Phone. Liberté accueille le populaire encore un autre Podcast (jesseliberty.com/podcast) et son blog (jesseliberty.com) est une lecture obligatoire. Il est l'auteur de nombreux livres Best-seller, y compris « Programmation réactive Extensions et LINQ » (Apress, 2011) et « Migration de Windows Phone » (Apress, 2011). Vous pouvez suivre Jesse Liberty sur Twitter à l'adresse twitter.com/JesseLiberty.

Merci à l'expert technique suivant d'avoir relu cet article : Jason Shaver