Présentation du Silverlight Control Toolkit

Benjamin Roux

Cet article vous présentera toutes les nouveautés contenues dans le Silverlight Control Toolkit.

- Titre : Présentation du Silverlight Control Toolkit

- Auteur : Benjamin Roux

- Parution : 9 novembre 2008

- Licence : Copyright ® 2008 Benjamin Roux. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- 1. Silverlight Control Toolkit

- 1-1. Présentation

- 1-2. Installation

- 1-3. Préparation de l'article

- 2. Les contrôles

- 2-1. Le TreeView

- 2-1-1. Les bases

- 2-1-2. Le DataBinding

- 2-1-3. Les problèmes connus

- 2-2. L'AutoCompleteBox

- 2-2-1. Les bases

- 2-2-2. Le DataBinding

- 2-2-3. Utilisation avancée

- 2-2-4. Les problèmes connus

- 3. Les Layouts

- 4. Les graphiques

- 5. Les thèmes

1 - Silverlight Control Toolkit

1-1 - Présentation

1-2 - Installation

1-3 - Préparation de l'article

Tout au long de cet article, nous allons utiliser 2 classes, Town et Neighborhood, afin de réaliser divers scénarios selon les contrôles.

Neighborhood.cs

public class Neighborhood
{
public string Name { get; set; }
public int Rate { get; set; }
}

Town.cs

public class Town
{
public string Name { get; set; }
public int Rate { get; set; }
public List<Neighborhood> Neighborhoods { get; set; }

public override string ToString()
{
return this.Name;
}
}

List<Town> towns = new List<Town>
{
new Town
{
Name = "San Francisco",
Rate = 5,
Neighborhoods = new List<Neighborhood>
{
new Neighborhood { Name = "Union Square", Rate = 5 },
new Neighborhood { Name = "Pacific Heights", Rate = 5 },
new Neighborhood { Name = "Mission District", Rate = -1 },
new Neighborhood { Name = "North Beach", Rate = 4 },
new Neighborhood { Name = "Tenderloin", Rate = 1 }
}
},
new Town
{
Name = "New York",
Rate = -1,
Neighborhoods = new List<Neighborhood>
{
new Neighborhood { Name = "Harlem" },
new Neighborhood { Name = "Liberty Island" },
new Neighborhood { Name = "Civic Center" },
new Neighborhood { Name = "Queens" },
new Neighborhood { Name = "Manhattan" }
}
},
new Town { Name = "Berkeley", Rate = 4 },
new Town { Name = "Oakland", Rate = -1 },
new Town { Name = "San Jose", Rate = -1 },
new Town { Name = "Seattle", Rate = -1 }
};

Nous allons également utiliser un Converter pour nos scénarios de DataBinding.

Rate2ImageConverter.cs

public class Rate2ImageConverter : IValueConverter
{

#region IValueConverter Members

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is int)
{
int rate = (int)value;
if (rate == -1) return null;
else return new BitmapImage(new Uri(string.Format("Images/star{0}.png", rate), UriKind.Relative));
}
return null;
}

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

#endregion
}

Ce Converter permet de convertir un int en BitmapImage. On s'en servira pour afficher une image selon la notation (Rate) d'une ville ou d'un quartier.

2 - Les contrôles

2-1 - Le TreeView

2-1-1 - Les bases

Première nouveauté dans ce pack de contrôles : le TreeView.

Rien de bien compliqué pour arriver à ce résultat :

<control:TreeView x:Name="tvTowns">
<control:TreeViewItem Header="San Francisco">
<control:TreeViewItem Header="Union Square" />
<control:TreeViewItem Header="Pacific Heights" />
<control:TreeViewItem Header="Mission District" />
<control:TreeViewItem Header="North Beach" />
<control:TreeViewItem Header="Tenderloin" />
</control:TreeViewItem>
<control:TreeViewItem Header="New-York">
<control:TreeViewItem Header="Harlem" />
<control:TreeViewItem Header="Liberty Island" />
<control:TreeViewItem Header="Civic Center" />
<control:TreeViewItem Header="Queens" />
<control:TreeViewItem Header="Manhattan" />
</control:TreeViewItem>
</control:TreeView>

Il s'agit ni plus ni moins que d'une suite de TreeViewItem imbriqués.

On peut également arriver à ce résultat en code-behind.

TreeViewItem sf = new TreeViewItem();
sf.Header = "San Francisco";
sf.Items.Add("Union Square");
sf.Items.Add("Pacific Heights");
sf.Items.Add("Mission District");
sf.Items.Add("North Beach");
sf.Items.Add("Tenderloin");

TreeViewItem ny = new TreeViewItem();
ny.Header = "New-York";
ny.Items.Add("Harlem");
ny.Items.Add("Liberty Island");
ny.Items.Add("Civic Center");
ny.Items.Add("Queens");
ny.Items.Add("Manhattan");

tvTowns.Items.Add(sf);
tvTowns.Items.Add(ny);

Voyons maintenant comment remplir notre TreeView via du DataBinding.

2-1-2 - Le DataBinding

Nous allons utiliser la liste de Town précédemment créée dans la partie 1-3.

On pourrait tout d'abord penser qu'il faille faire comme pour tous les autres contrôles, mais ici il faut prendre en compte l'imbrication des éléments, et c'est là qu'un nouveau DataTemplate intervient : HierarchicalDataTemplate

Ce DataTemplate est utilisé pour afficher des éléments sous forme hiérarchique (ce qui est le cas pour un TreeView). Les éléments à afficher doivent obligatoirement avoir une collection d'enfants (Neighborhoods pour le cas de notre classe Town).

<control:TreeView x:Name="tvTowns">
<control:TreeView.ItemTemplate>
<control:HierarchicalDataTemplate ItemsSource="{Binding Neighborhoods}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
<Image Source="{Binding Rate, Converter={StaticResource Rate2Image}}" Margin="10,0,0,0" />
</StackPanel>
</control:HierarchicalDataTemplate>
</control:TreeView.ItemTemplate>
</control:TreeView>

Une nouvelle propriété apparait dans le HierarchicalDataTemplate : ItemsSource. Il s'agit ni plus ni moins que du nom de la propriété contenant les éléments fils.

On affecte notre liste à notre TreeView et voici le résultat :

2-1-3 - Les problèmes connus

Voici une liste non exhaustive des problèmes connus avec le TreeView. Ils seront normalement corrigés dans la prochaine release.

- DisplayMemberPath ne fonctionne pas

- On ne peut pas imbriquer les HierarchicalDataTemplate.

- Utiliser à la fois ItemStyle et ItemTemplate empêche la visualisation dans Blend

Vous trouverez surement d'autre Issues sur le site officiel : http://www.codeplex.com/Silverlight/WorkItem/List.aspx

2-2 - L'AutoCompleteBox

2-2-1 - Les bases

L'AutoCompleteBox est une TextBox proposant des suggestions selon ce que l'utilisateur tape.

Pour arriver à ce résultat, c'est très simple. Un ajoute tout d'abord notre contrôle dans notre XAML.

<control:AutoCompleteBox x:Name="acTowns" />

On ajoute ensuite les suggestions.

acTowns.ItemsSource = new string[] { "San Francisco", "New-York", "Berkeley", "Oakland", "San Jose", "Seattle" };

Et on obtient le résultat montré plus haut.

Voyons à présent les différentes possibilités proposées :

Maintenant il serait intéréssant d'ajouter les suggestions au fur et à mesure par rapport à ce que tape l'utilisateur mais aussi agrémenter l'affichage.

2-2-2 - Le DataBinding

On va tout d'abord agrémenter l'affichage. On reprend notre liste de Town, et on va afficher une image selon la notation.

<control:AutoCompleteBox x:Name="acTowns">
<control:AutoCompleteBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
<Image Source="{Binding Rate, Converter={StaticResource Rate2Image}}" Margin="10,0,0,0" />
</StackPanel>
</DataTemplate>
</control:AutoCompleteBox.ItemTemplate>
</control:AutoCompleteBox>

Voyons maintenant comment binder nos suggestions sur un WebService, selon ce que l'utilisateur tape. Pour cela nous allons utiliser le service de suggestions de Live.com.

On modifie légèrement le XAML.

<control:AutoCompleteBox x:Name="acSearch" Populating="acSearch_Populating" />

On s'abonne simplement à l'évènement Populating qui est appelé chaque fois que quelque chose est tapé dans l'AutoCompleteBox.

private void acSearch_Populating(object sender, PopulatingEventArgs e)
{
AutoCompleteBox box = sender as AutoCompleteBox;

WebClient client = new WebClient();
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(new Uri("http://api.search.live.net/qson.aspx?query=" + box.Text));
}

void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
try
{
List<string> suggests = new List<string>();

JsonObject jso = ((JsonObject)JsonObject.Parse(e.Result))["SearchSuggestion"] as JsonObject;

foreach (JsonObject suggest in (JsonArray)jso["Section"])
{
suggests.Add(suggest.Values.First());
}

acSearch.ItemsSource = suggests;
acSearch.PopulateComplete();
}
catch { }
}
}

Une fois les suggestions récupérées à partir du service Live, nous les affectons à notre AutoCompleteBox, rien de plus compliqué.

2-2-3 - Utilisation avancée

2-2-4 - Les problèmes connus

3 - Les Layouts

4 - Les graphiques

5 - Les thèmes