Initiation à WPF

Au travers de la réalisation d'un mini lecteur MP3, cet tutoriel aborde différents concepts de la technologie WPF comme le DataBinding, les styles et les thèmes ainsi que le format de tag ID3Tag(1) (1)

N'hésitez pas à commenter cet article ! Commentez Donner une note à l'article (5)

Article lu   fois.

L'auteur

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   
Image non disponibleImage non disponibleImage non disponible

I. SPECIFICATIONS

Image non disponible

L'application se présente de la façon suivante : Un lecteur MP3 rudimentaire reposant sur la brique WPF pour l'aspect visuel et DirectX.AudioVideoPlayBack pour les fonctionnalités audios, plus quelques fonction d'édition de tags MP3.

Fonctionnalités requises
  1. Lecture d?un morceau MP3
  2. Pause
  3. Arrêt
  4. Parcourir de fichier sur le PC pour sélectionner le fichier à lire
  5. Un éditeur de tags pour modifier les tags associés au morceau MP3 en cours de lecture
  6. Une image d'album associée au morceau MP3, qui peut être redimensionnée à la volée via un slider

Liste des composants dans la partie Lecteur audio

Nom ComposantTypeTitre
Lecteur DirectX.AudioVideoPlayBack.Audio  
btnParcourir Button ...
lTitre Label Titre de la chanson
btnPause Button Pause
btnArret Button Arrêt
btnLecture Button Lecture
imgAlbum Image  
sliderImg Slider  
cbxStyle comboBox Style Garçon / Style Fille

Liste des composants dans la partie Editeur de tags MP3

Nom ComposantTypeTitre
txtbTitre TextBox  
txtbAuteur TextBox  
btnOk Button Enregistrer

II. PRE-REQUIS

Pour exécuter l'application
  1. .Net Framework 3.0
  2. Direct X 9.0 (DirectX.AudioVideoPlayBack.dll, mais aussi DirectX.dll) SDK DirectX 9
Pour réaliser l'application
  1. Visual C# Express 2008 ici

III. ARCHITECTURE

Pour construire une application modulaire et évolutive, l'approche MDA conseille de distinguer 3 couches au sein de l'application, qui interagissent entre-elles:

  1. la couche graphique (classe Dialogue)
  2. la couche métier (classes Contrôle)
  3. la couche données (classe Entité)

Ca tombe bien, car WPF en décrivant les interfaces grâce à une syntaxe déclarative (le Xaml), isole la couche graphique du reste de l'application. En ce qui concerne la couche métier, on recense deux classes,
une concernant les fonctions de lecture et une concernant les fonctions d'édition de tags.

Image non disponible

La réalisation de l'application suivra le sens suivant : Classe d'entité -> Classes de contrôle -> Classe de dialogue.
Car la classe de dialogue encapsule (et donc dépend de) les classes de contrôle qui elles-mêmes encapsulent la classe d'entité. En effet, la classe DialogueIHMLecteur appellera les méthodes des classes
ControleLecture et ControleEditeur, suivant les actions de l'utilisateur.

IV. REALISATION

Ouvrir Visual C# Express 2008. Choisir dans le Menu File -> New Project -> WPF Application

IV-A. Conception de la couche Entité (EntiteMorceau.cs)

Cette couche ne contient que la définition de la structure strTagsMP3 qui est une représentation d'un fichier MP3 avec ses tags titre, artiste, et genre

 
Sélectionnez

public struct strTagsMP3
{
    public string tagOK;	    // 03 car
    public String titre;       // 30 car
    public String artiste;     // 30 car
    public short genre;        // 01 car
    // total                     128 car
}

La classe EntiteMorceau implémente cette structure et contient simplement les accesseurs pour accéder en lecture / modification à chacun des tags.

 
Sélectionnez

public class EntiteMorceau
{
    

    private strTagsMP3 TagsMP3;
   
    public strTagsMP3 accTagsMP3
    {
        get
        {
            return TagsMP3;
        }

        set
        {
            TagsMP3.tagOK = value.tagOK;
            TagsMP3.titre = value.titre;
            TagsMP3.artiste = value.artiste;
            TagsMP3.genre = value.genre;
        }

    }

    public string accTagOk
    {
        get
        {
            return TagsMP3.tagOK;
        }
        set
        {
            TagsMP3.tagOK = value;
        }
    }

    public String accTitre
    {
        get
        {
            return TagsMP3.titre;
        }
        set
        {
            TagsMP3.titre = value;
        }
    }

    public String accArtiste
    {
	...
    }

    public short accGenre
    {
	...
    } 
}
}

IV-B. Conception de la couche Contrôle (ControleEditeurTags.cs et ControleLecture.cs))

La classe ControleEditeur contient en particulier les 3 méthodes OuvrirFichier, PossedeTag et EcrireTag qui sont des adaptations du code source du hors-série code(r) #4. La méthode PossedeTag ouvre un filestream
sur le fichier passé en paramètre, se positionne 128 bits avant la fin du fichier, lit les 3 premiers octets du filestream et détecte si le tableau de bits ainsi stocké contient la chaîne " TAG ".
Si la chaîne " TAG " est stocké, c'est que ce fichier MP3 contient effectivement des tags.

 
Sélectionnez

private bool PossedeTag(string fichier)
{
		// ouvrir le fichier
		FileStream f = new FileStream(fichier, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
		// se positionner sur le tag
		f.Seek(-128, SeekOrigin.End);
		
		//ouverture d'un binaryreader sur le fichier
		BinaryReader br = new BinaryReader(f);
		
		byte[] tagArray = br.ReadBytes(3);
		// lire les 3 premiers octets
		string tag = System.Text.Encoding.Default.GetString(tagArray);
		br.Close();
		
		// si ces octets contiennent "TAG", c'est qu'il y a un tag
		if (tag.CompareTo("TAG")==0)
			return true;
		else
			return false;
}

La méthode OuvrirFichier prend en paramètre le chemin du fichier à ouvrir (type String), lit les tags du fichier en se positionnant 128 bits avant la fin du fichier puisque c'est à cet endroit d'un fichier MP3 que les tags sont stockés.
Elle vide la structure de l'objet de type EntiteMorceau de ses éventuelles valeurs en mémoire. Elle appelle la méthode PossedeTag. Si le fichier ne possède pas de tag MP3, elle rend l'objet Morceau tel quel, cad vide.
Sinon, la méthode se positionne 128 bits avant la fin du fichier pour lire les tags (f.seek(-128, SeekOrigin.End)). On lit alors le contenu des tags, en éliminant le caractère " / " qui fonctionne comme un espace vide.
Pour le dernier caractère, on utilisera la méthode PeekChar, pour le lire, sans avancer dans le fichier, sinon une exception est levée.
Puis on attribue grâce aux accesseurs les tags adéquats titre, artiste, genre. Concernant les genres musicaux, on a simplifié la liste en ne gardant que 6 genres principaux :

  • genres[8] => "Jazz";
  • genres[9] => "Metal";
  • genres[13] => "Pop";
  • genres[15] => "Rap";
  • genres[18] => "Techno";
  • genres[32] => "Classical";

Si le fichier contient un genre différent, on lui attribue le genre[0] c'est-à-dire " divers "

 
Sélectionnez

public class ControleEditeurTags
{
   private EntiteMorceau Morceau = null; 
    
	
    public EntiteMorceau OuvrirFichier(String fichier)
  {
        if (fichier != null)
        {
            Morceau = new EntiteMorceau();
            // on "vide" le tag
            Morceau.accTagOk = "TAG";
            Morceau.accTitre = "";
            Morceau.accArtiste = "";
            Morceau.accGenre = -1;

        // si le mp3 ne possède pas de tag à lire, on retourne le tag vide
            if (!PossedeTag(fichier))
            {
                return Morceau;
            }

         // ouvrir le fichier
FileStream f = new FileStream(fichier, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            // se positionner sur le tag
            f.Seek(-128, SeekOrigin.End);

            //ouverture d'un binaryreader sur le fichier
            BinaryReader br = new BinaryReader(f);


            char charsToTrim = '/';

            // lire chaque élément
            Morceau.accTagOk = System.Text.Encoding.Default.GetString(br.ReadBytes(3));
            Morceau.accTitre = System.Text.Encoding.Default.GetString(br.ReadBytes(30));
            Morceau.accTitre = Morceau.accTitre.TrimEnd(charsToTrim);
            Morceau.accArtiste = System.Text.Encoding.Default.GetString(br.ReadBytes(30));
            Morceau.accArtiste = Morceau.accArtiste.TrimEnd(charsToTrim);
            Morceau.accGenre = (short)br.PeekChar();
			
//Attribution d'un genre par défaut "Divers", si le fichier n'appartient à aucune des grandes familles de genres musicaux
			
	if (Morceau.accGenre != 8 && Morceau.accGenre != 9 && Morceau.accGenre != 13 && Morceau.accGenre != 15 && Morceau.accGenre != 18 && Morceau.accGenre != 32)
            {
                Morceau.accGenre = 0;

            }

// fermeture du fichier (la fermeture du BinaryReader ferme le FileStream)
            br.Close();

      // retourner le tag lu
            return Morceau;
        }
        else
        {
            return null;
        }
}
	
}			
			

Le contenu de notre objet Morceau, généré à partir des boites de dialogue de l'IHM est écrit dans les différents tags. Mais vu que chaque champ de tag a une taille fixe dans le fichier MP3, on complète les espaces vides
par le caractère " / ", qui sera ignoré à la lecture.

  • Titre : 30 car
  • Artiste : 30 car
  • Genre : 1 car
 
Sélectionnez

public void EcrireTag( string fichier)
	{
		// ouvrir le fichier
		FileStream f = new FileStream(fichier, FileMode.Open, FileAccess.Write, FileShare.ReadWrite);
		// se positionner suivant qu'il y a un dj tag ou pas
		if( PossedeTag(fichier) )
			f.Seek(-128, SeekOrigin.End);
		else
			f.Seek(0, SeekOrigin.End);

		// écrire les infos avec un BinaryWriter
		BinaryWriter bw = new BinaryWriter(f);
		bw.Write(System.Text.Encoding.Default.GetBytes(Morceau.accTagOk));
		
		// pour chaque élément, s'il ne fait pas la longueur voulue, on rajoute le car "/"
		bw.Write(System.Text.Encoding.Default.GetBytes(Morceau.accTitre));
		for(int i = 0; i < 30-Morceau.accTitre.Length; i ++) bw.Write((char)'/');

		bw.Write(System.Text.Encoding.Default.GetBytes(Morceau.accArtiste));
        for (int i = 0; i < 30 - Morceau.accArtiste.Length; i++) bw.Write((char)'/');

		bw.Write((short) Morceau.accGenre);

		bw.Close();
		
	}      

On génère l'objet Morceau à partir du stackpanel de l'IHM contenant les contrôles et on appelle la méthode EcrireTag

 
Sélectionnez

public void EditerTag(StackPanel objStckPan, string fichierATagger)
    {
        if (Morceau != null)
        {
            Morceau.accTitre = ((TextBox)objStckPan.FindName("txtbTitre")).Text;
            Morceau.accArtiste = ((TextBox)objStckPan.FindName("txtbAuteur")).Text;
            Morceau.accGenre = short.Parse(((ComboBox)objStckPan.FindName("cbxType")).SelectedValue.ToString());

         }

            EcrireTag(fichierATagger);
    }

La classe ControleLecture encapsule un objet DirectX AudioVideoPlayBack.Audio. Les méthodes _lire(), _arreter(), _interrompre(), ne font qu'appeler les méthodes correspondantes de l'objet Audio : play(), stop(), pause().
L'espace de nom à ajouter est bien Microsoft.DirectX.AudioVideoPlayBack. Pour ouvrir le fichier MP3 en lecture, on utilisera la classe OpenFileDialog, sans oublier d'ajouter l'espace de nom System.IO dans les directives
Using du fichier. Une énumération typeFichier permet de factoriser la méthode _ouvrir en l'utilisant aussi bien pour l'ouverture de fichiers musicaux que de fichiers d'images.

 
Sélectionnez

public class ControleLecture
{
    public Audio Lecteur;
    
    public void _lire()
    {
        if (Lecteur != null)
        {
            Lecteur.Play();
        }
        
    }

    public string _ouvrir(typeFichier tf)
    {
       OpenFileDialog ofd = new OpenFileDialog();
       if (tf == typeFichier.musique)
       {
           ofd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic);
           ofd.Filter = "mp3 files (*.mp3)|*.mp3";
           ofd.FilterIndex = 2;
           ofd.RestoreDirectory = true;

           if (ofd.ShowDialog() == DialogResult.OK)
           {
               try
               {
                   if (ofd.OpenFile() != null)// On attribue le chemin du fichier à lire au 
                   {
                       Lecteur = new Audio(ofd.FileName, false);
                       return ofd.FileName;

                   }
               }
               catch (Exception ex)
               {
                   MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                   return null;
               }
           }
           return null;
       }
       else if (tf == typeFichier.image)
       {
           ofd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
           ofd.Filter = "JPG (*.jpg)|*.jpg";
           ofd.FilterIndex = 2;
           ofd.RestoreDirectory = true;

           if (ofd.ShowDialog() == DialogResult.OK)
           {
               try
               {
                   if (ofd.OpenFile() != null)// On attribue le chemin du fichier à lire au 
                   {
                       
                       return ofd.FileName;

                   }
               }
               catch (Exception ex)
               {
                   MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                   return null;
               }
           }
           return null;
       
       }
       return null;
    }

    public void _arreter()
    {
        if (Lecteur != null)
        {
            Lecteur.Stop();
        }
    }

    public void _interrompre()
    {
        if (Lecteur != null)
        {
            Lecteur.Pause();
        }
    }  
}

IV-C. Conception de la couche Dialogue (DialogueIHMLecteur.xaml)

L'IDE Xaml de Visual Studio est scindé en deux horizontalement : une interface RAD ou on dépose les contrôles, et une page affichant le code Xaml correspondant.

Image non disponible

Dans le fichier DialogueIHMLecteur.xaml, tapez le texte suivant :

 
Sélectionnez

   <Page x:Class="LecteurAudioXaml.Dialogues.DialogueIHMLecteur"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Page1" Height="505" Width="600">
<Grid>	
    <TabControl Margin="10,35,36,39" Name="tabControl1">
        <TabItem Name="tbiLecteur">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="12*" />
                    <ColumnDefinition Width="532*" />
                </Grid.ColumnDefinitions>
                <Button Click="btnLecture_Click" Grid.Column="1" Height="70" HorizontalAlignment="Left" 
				Margin="140,106.5,0,0" Name="btnLecture" VerticalAlignment="Top" Width="70">Lecture</Button>
                <Button Click="btnPause_Click" Grid.Column="1" Height="70" Margin="253,106.5,209,0" Name="btnPause" 
				VerticalAlignment="Top">Pause</Button>
                <Button Click="btnArret_Click" Grid.Column="1" Height="70" HorizontalAlignment="Right" Margin="0,106.5,97,0" 
				Name="btnArret" VerticalAlignment="Top" Width="70">Arrêt</Button>
                <Button Click="btnParcourir_Click" Grid.Column="1" Height="70" HorizontalAlignment="Right" Margin="0,25,97,0" 
				Name="btnParcourir" VerticalAlignment="Top" Width="70">...</Button>
                <Label Grid.Column="1" Height="32" HorizontalAlignment="Left" Margin="12,25,0,0" Name="lTitre" 
				VerticalAlignment="Top" Width="219">Titre de la chanson</Label>
                <Button Click="btnImg_Click" Grid.Column="1" HorizontalAlignment="Right" Margin="0,196,80,145" Name="btnImg" Width="70">
				...</Button>
                <Image Grid.Column="1" Margin="140,182,192,29" Name="imgAlbum" Stretch="Fill" />
                <Slider Grid.Column="1" Height="21" HorizontalAlignment="Right" Margin="0,0,8,97" 
				Maximum="200" Name="sliderImageAlbum" StyleTickFrequency="1" Value="200" 
				VerticalAlignment="Bottom" Width="175" />
            </Grid>
        </TabItem>
        <TabItem Name="tbiEditeur">
            <StackPanel Name="stckPEditeur">
                <Label>Titre</Label>
                <TextBox Name="txtbTitre" />
                <Label>Auteur</Label>
                <TextBox Name="txtbAuteur" />
                <Label>Type</Label>
                <ComboBox Height="23"  Name="cbxType" Width="120" />
                <Button Click="btnOk_Click" Name="btnOk" VerticalAlignment="Top" Width="75">Enregistrer</Button>
            </StackPanel>
        </TabItem>
    </TabControl>
    <ComboBox Height="23" HorizontalAlignment="Left" Margin="15,10,0,0" Name="cbxStyle" VerticalAlignment="Top" Width="120">
        <ComboBoxItem IsSelected="True">Style Garçon</ComboBoxItem>
        <ComboBoxItem>Style Fille</ComboBoxItem>
    </ComboBox>
</Grid>
</Page>

ce qui devrait donner un résultat proche de ceci pour l'onglet Lecteur :

Image non disponible

et ceci pour l'onglet éditeur :

Image non disponible

IV-C-1. Liaison de données (DataBinding) avec une source Xml, en WPF

Pour peupler notre liste déroulante dans l'onglet éditeur, qui contient les différents styles musicaux, nous allons utiliser un fichier Xml comme source. Voici le fichier type_morceau.xml :

 
Sélectionnez

<?xml version="1.0"?>
<types>
<Item>
<titre>divers</titre>
<valeur>0</valeur>
</Item>
<Item>
<titre>jazz</titre>
<valeur>8</valeur>
</Item>
<Item>
<titre>métal</titre>
<valeur>9</valeur>
</Item>
<Item>
<titre>pop-rock</titre>
<valeur>13</valeur>
</Item>
<Item>
<titre>rap</titre>
<valeur>15</valeur>
</Item>
<Item>
<titre>techno</titre>
<valeur>18</valeur>
</Item>
<Item>
<titre>classique</titre>
<valeur>32</valeur>
</Item>
</types>

Il contient un nombre restreint de styles musicaux mais bien suffisant pour notre démonstration Nous rajouterons donc comme ressource à notre fichier DialogueIHMLecteur.xaml, le fournisseur Xml (XmlDataProvider) type_morceau.xml dont
l'identifiant désignée par la balise x :key sera dataProvider.

 
Sélectionnez

<Window.Resources>
<XmlDataProvider x:Key="dataProvider" XPath="types" Source="../type_morceau.xml"></XmlDataProvider>
</Window.Resources>

Nous n'avons donc plus qu'à assurer le mappage entre la liste déroulante (Text et Value) et les 2 champs (titre et valeur) de la source Xml, grâce aux instructions DisplayMemberPath et SelectedValuePath,
sans oublier de préciser grâce à la requête XPath que le champ du fichier source concerné est Item.

 
Sélectionnez


<ComboBox Height="23" Width="120"  Name="cbxType" ItemsSource="{Binding Source={StaticResource dataProvider},XPath=Item}" 
DisplayMemberPath="titre" SelectedValuePath="valeur">
</ComboBox>

Voici donc sans une seule ligne de code (mais uniquement avec des balises Xaml), ce que vous devriez obtenir :

Image non disponible

IV-C-2. Lier une propriété à la valeur d'un contrôle

Un des gros avantages de WPF, c'est que le rendu graphique est entièrement vectoriel. Nous allons illustrer cette idée, par la mise au point d'une image qui diminue à la volée suivant la valeur d'un slider.

Image non disponible
Image non disponible

Pour faire cela une simple instruction de binding suffit dans la balise du contrôle Image :

 
Sélectionnez

<Image Margin="140,182,192,29" Name="imgAlbum" Stretch="Fill" Width="{Binding ElementName=sliderImageAlbum, Path=Value}" 
Height="{Binding ElementName=sliderImageAlbum, Path=Value}"  
Grid.Column="1" />
<Slider Height="21" Margin="0,0,8,97" Name="sliderImageAlbum"  Style="{DynamicResource TplSlider}" 
Value="200" Maximum="200" TickFrequency="1" HorizontalAlignment="Right" 
				VerticalAlignment="Bottom" Width="175" Grid.Column="1" />

IV-C-3. Mettre un peu de style dans notre application (DialogueIHMLecteur.xaml)

Que diriez-vous de personnaliser un peu le style de l'application, comme on peut le voir sur certains sites web où l'utilisateur choisit la feuille de style qui veut appliquer sur la page. Il faut alors définir les propriétés
de chaque contrôle dans une page Xaml que l'on désigne par le terme de Theme. Notre fichier s'appelle ThemeGarcon.xaml et voici son contenu

 
Sélectionnez

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


<Style x:Key="TplArrierePlan">
    <Setter Property="Control.Background" Value="CornflowerBlue"/>
</Style>

<Style BasedOn="{StaticResource TplArrierePlan}"
   TargetType="Button"
   x:Key="TplBouton">
    <Setter Property="HorizontalAlignment" Value="Left"/>
    <Setter Property="FontSize" Value="13"/>
    <Setter Property="FontFamily" Value="Arial"/>
    <Setter Property="VerticalAlignment" Value="Top"/>
    <Setter Property=" HorizontalAlignment" Value="Left"/>
    <Setter Property="Width" Value="70"/>
    <Setter Property="Height" Value="70"/>
</Style>
<Style BasedOn="{StaticResource TplArrierePlan}"
   TargetType="Label"
   x:Key="TplLabel">
    <Setter Property="FontSize" Value="14"/>
    <Setter Property="FontFamily" Value="Arial"/>
    <Setter Property="VerticalAlignment" Value="Top"/>
    <Setter Property=" HorizontalAlignment" Value="Left"/>
    <Setter Property="Width" Value="300"/>
    <Setter Property="Height" Value="32"/>
</Style>
<Style BasedOn="{StaticResource TplArrierePlan}"
   TargetType="Slider"
   x:Key="TplSlider">
    <Setter Property="Width" Value="100"/>
    <Setter Property="Height" Value="32"/>
    <Setter Property="VerticalAlignment" Value="Bottom"/>
    <Setter Property="HorizontalAlignment" Value="Right"/>

</Style>

<Style BasedOn="{StaticResource TplArrierePlan}"
   TargetType="ComboBox"
   x:Key="TplCbx">

</Style>

</ResourceDictionary>

Un style de base dont l'identifiant est TplArrierPlan, qui applique une couleur d'arrière plan bleue aux contrôles :

 
Sélectionnez

<Style x:Key="TplArrierePlan">
    <Setter Property="Control.Background" Value="CornflowerBlue"/>
</Style>

Tous les autres styles se référent à ce style de base, pour définir d'autres propriétés plus spécifiques. Ici le style TplBouton dont le contrôle cible est de type Button, définit des propriétés de police, alignement, de longueur, de hauteur.

 
Sélectionnez

<Style BasedOn="{StaticResource TplArrierePlan}"
   TargetType="Button"
   x:Key="TplBouton">
    <Setter Property="HorizontalAlignment" Value="Left"/>
    <Setter Property="FontSize" Value="13"/>
    <Setter Property="FontFamily" Value="Arial"/>
    <Setter Property="VerticalAlignment" Value="Top"/>
    <Setter Property=" HorizontalAlignment" Value="Left"/>
    <Setter Property="Width" Value="70"/>
    <Setter Property="Height" Value="70"/>
</Style>

On définit avec des valeurs différentes le thème Fille dans le fichier ThemeFille.xaml. Ces 2 fichiers sont placés dans le répertoires Themes de l'application Par défaut, on attribue le thème
Garçon à l'application, en appliquant cette directive dans le fichier App.xaml

 
Sélectionnez

<ResourceDictionary x:Name="Style">
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary  Source="Themes\StyleGarcon.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>

Maintenant, dans le fichier DialogueIHMLecteur.xaml nous devons lier chaque contrôle avec son style définit dans le thème, grâce à la directive Style, en précisant bien que c'est une ressource dynamique,
puisque le style des contrôles est susceptibles d'évoluer suivant les actions de l'utilisateur.

 
Sélectionnez

<Button Name="btnLecture" Click="btnLecture_Click"   Margin="140,106.5,0,0"  Style="{DynamicResource TplBouton}"  
Grid.Column="1" Height="70" VerticalAlignment="Top" HorizontalAlignment="Left" Width="70">Lecture</Button>

                <Label  Name="lTitre"  Margin="12,25,0,0" Style="{DynamicResource TplLabel}" Grid.Column="1" 
				Height="32" VerticalAlignment="Top" HorizontalAlignment="Left" Width="219">Titre de la chanson</Label>

Puis grâce à une liste déroulante, on donne le choix à l'utilisateur de sélectionner son style préféré.

 
Sélectionnez

private void cbxStyle_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        ResourceDictionary rd = new ResourceDictionary();

        
        ResourceDictionary newDictionary = new ResourceDictionary();
        switch (cbxStyle.SelectedIndex)
        {
            case 0:
                newDictionary.Source =  new Uri("Themes/StyleGarcon.xaml",UriKind.Relative);
                break;
            case 1:
                newDictionary.Source =  new Uri("Themes/StyleFille.xaml",UriKind.Relative);
                break;
        }
        System.Windows.Application.Current.Resources.MergedDictionaries[0] = newDictionary;
        
    }

Voici, le style appliqué lorsque l'utilisateur choisit dans la liste déroulante " Style Fille"

Image non disponible

V. CONCLUSION

Par ce bref tutoriel vous avez appris à réaliser un mini lecteur MP3 en utilisant les technologies WPF et XAML. Ces technologies semblent prometteuses, puisqu'elles ont l'énorme avantage de dissocier totalement
la couche Présentation de la couche Métier, idée relativement évidente dans une architecture web, mais plutôt étrangère aux architectures Windows classiques. XAML se propose donc de réunir le meilleur du monde Windows et du monde Web.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   


Organisme ID3Tag : http://www.id3.org/

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2008 Hervé Labénère. 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.