1. .NET Compact Framework, Tébourbi Riadh, SUP’COM
Développement d’applications mobiles sur
.net Compact Framework
Tébourbi Riadh
SUP’COM
2005
Partie 2
XML et données locales
Mise à jour Décembre 2006
2. .NET Compact Framework, Tébourbi Riadh, SUP’COM
I.Introduction
Bien que les périphériques mobiles soient intégrés au système d'information de l'entreprise et connectées
physiquement à son réseau, il est nécessaire de stocker des informations en local. En effet, il est rare de
disposer de périphériques mobiles connectés en permanence. Il faut donc pouvoir gérer les scénarii « Online
/ Offline » et les opérations de synchronisation des données. Pour cela, il est donc nécessaire de stocker des
données en local. Une des méthodes que propose le Compact Framework .Net pour stocker et/ou de
manipuler des données est d’utiliser des fichiers XML.
II. Le langage XML
XML (Extensible Markup Language, ou Langage Extensible de Balisage) est, comme HTML (Hypertext
Markup Language), est un langage de balisage (markup), c'est-à-dire un langage qui présente de
l'information encadrée par des balises. Mais contrairement à HTML, qui présente un jeu limité de balises
orientées présentation (titre, paragraphe, image, lien hypertexte, etc.), XML est un métalangage, qui va
permettre d'inventer à volonté de nouvelles balises pour isoler toutes les informations élémentaires (titre
d'ouvrage, prix d'article, numéro de sécurité sociale, référence de pièce…), ou agrégats d'informations
élémentaires, que peut contenir une page Web.
XML est utilisé aujourd’hui comme un langage standard pour stocker et échanger des données.
III. L’application Pays
Pour illustrer comment utiliser XML pour stocker des données en local, nous allons réaliser une application
utilisant des données sur les pays du monde. Une table pays.xml contient des informations concernant
chaque pays du monde. Voici un aperçu de ce fichier :
<pays>
<NOM>Tunisia</NOM>
<POPULATION>8620181</POPULATION>
<DEVISE>Dinar</DEVISE>
<SURFACE>155402</SURFACE>
</pays>
<pays>
<NOM>Algeria</NOM>
<POPULATION>27459230</POPULATION>
<DEVISE>Dinar</DEVISE>
<SURFACE>2320972</SURFACE>
</pays>
<pays>
…
2
3. .NET Compact Framework, Tébourbi Riadh, SUP’COM
Cette table possède donc 4 attributs : « NOM », « POPULATION », « DEVISE » et « SURFACE ».
En plus de ces informations alphanumériques, nous disposons aussi de fichiers images représentant les
drapeaux de chaque pays.
Nous allons créer une application qui affiche pour chaque pays ses informations et son drapeau. D’une façon
plus précise voici les fonctionnalités de l’application :
1. Lecture des données des pays stockées dans un fichier XML
2. Offrir à l’utilisateur la possibilité de d’entrer un nom de pays, l’application recherche alors ce pays
dans la base et si ce pays existe elle affiche ses informations et son drapeau.
3. Offrir à l’utilisateur la possibilité de rechercher un pays par mot clé. Les noms des pays trouvés son
alors affichés dans une liste et l’utilisateur, en sélectionnant un pays, il peut afficher ses informations
complètes.
Phase 1
Créer une nouvelle solution mobile (VB) appelée « dbpays_vb » sous Visual Studio 2005.
Dans « l’Explorateur de solution » ajouter le fichier fourni « pays.xml » : Click droit sur le nom du projet
« dbpays_vb » puis « AddExisting item », spécifier alors où se trouve le fichier pays.xml. Ce fichier sera
ajouté à la liste des fichiers du projet et sera copié dans le répertoire racine de la solution.
Pour que le fichier « pays.xml » soit copié sur le PocketPC lors du déploiement de la solution (en même
temps que l’exécutable) il faut modifier sa propriété « Copy to output directory » et la mettre à « Copy if
newer ».
3
4. .NET Compact Framework, Tébourbi Riadh, SUP’COM
De même créez un répertoire flags dans l’explorateur de solution (Add New Folder) et ajoutez-y les
fichiers images (drapeaux des pays).
Ajouter un contrôle « TabControl » sur la « Form ». Ce contrôle permet d’avoir plusieurs fenêtres
(« Tabpages ») accessibles par onglet.
Placer les
contrôles ici
Les onglets
permettant d’accéder
aux autres pages
Vous pouvez accéder aux propriétés du « TabContrôle » en utilisant sa propriété « TabPages ». Vous pouvez
alors personnaliser les différentes pages (« TabPages ») de ce « TabControle» :
4
5. .NET Compact Framework, Tébourbi Riadh, SUP’COM
Pour notre application nous avons besoins de deux «TabPages » (TabPage1 et TabPage2) pour placer nos
contrôles et créer l’interface graphique.
- Dans la première page « TabPage 1 » :
Sur cette page nous allons offrir la fonctionnalité 1 de l’application (afficher les informations d’un pays
donné). Pour cela, mettez l’attribut « Text » de « TabPage1 » à « Infos » et ajouter les contrôles
suivants :
5
6. .NET Compact Framework, Tébourbi Riadh, SUP’COM
TextBox
« Npays » Label
Bouton
« Info »
Label
Label Label
« Pop »
Label
Label
« Dev »
PictureBox
« Flag »
Label
« Surf »
TabControl
L’utilisateur entre un nom de pays dans la zone TextBox « Npays », clique sur le bouton « Info » , les
information du pays seront affichées sur les contrôles Label : « Pop », « Dev » et « Surf ». Le drapeau du
pays (image) sera affiché sur la PictureBox « Flag ».
6
7. .NET Compact Framework, Tébourbi Riadh, SUP’COM
- Dans la deuxième page « TabPage 2 » :
Sur cette page nous allons offrir la fonctionnalité 2 de l’application (rechercher des pays par mot clé et
afficher les informations d’un pays sélectionné). Pour cela, mettez l’attribut « Text » de « TabPage2 » à
« Rechercher » et ajouter les contrôles suivants :
7
8. .NET Compact Framework, Tébourbi Riadh, SUP’COM
Label
Bouton
« Rech »
TextBox
« Crit »
ListBox
« Result »
Bouton
« Ainfo »
L’utilisateur entre le critère de recherche dans la zone de texte « « Crit », il clique sur le bouton
« Rech », les résultats de recherche (noms de pays) seront affichés dans la ListBox « Result ». En
sélectionnant un pays de la liste et en cliquant sur le bouton « Ainfo », les informations de ce pays seront
affichés sur la page « Infos » du TabControl.
8
9. .NET Compact Framework, Tébourbi Riadh, SUP’COM
L’interface graphique (IHM) étant prête, il temps maintenant de passer à l’implémentation des
différentes fonctionnalités.
Phase 2
1) Fonctionnalité 1 : Lire les données du fichier XML utilisation des DataSet
Comme nous l’avons dis dans l’introduction, le Compact Framework .Net permet de stocker et/ou de
manipuler des données stockées dans des fichiers XML en utilisant des DataSet.
Il est possible d'avoir « une base de données en mémoire » et d'y effectuer tout type d'opérations
(recherche, mise à jours, etc). Cela est possible grâce à l'objet « DataSet » qui permet de manipuler des
tables « DataTable » constituées de DataRows (enregistrements) et de DataColumns (champs), auxquels
on peut attribuer différentes contraintes. Nous allons donc voir comment utiliser ces DataSet afin de
consulter et de manipuler des données des pays stockées dans le fichier pays.xml.
La création de DataSet se fait très simplement, il suffit de lui attribuer un ensemble de DataTable et
d'ajouter les colonnes à ces DataTable pour construire la structure de la base que l'on souhaite manipuler.
Dans notre cas, nous allons créer un DataSet « dbpays » contenant une table DataTable « pays » puis lui
ajouter quelques champs:
pays (NOM, POPULATION, DEVISE, SURFACE)
Le champ NOM est une clé primaire.
9
10. .NET Compact Framework, Tébourbi Riadh, SUP’COM
Nous allons créer alors deux variables myDs (DataSet) et myDt (DataTable) :
Dim myDs As New DataSet(quot;dbpaysquot;)
Dim myDt As DataTable = myDs.Tables.Add(quot;paysquot;)
Pour ajouter les différentes colonnes (DataColumn ) à la dataTable Mydt :
myDt.Columns.Add(quot;NOMquot;, System.Type.GetType(quot;System.Stringquot;))
myDt.Columns.Add(quot;POPULATIONquot;, System.Type.GetType(quot;System.Stringquot;))
myDt.Columns.Add(quot;DEVISEquot;, System.Type.GetType(quot;System.Stringquot;))
myDt.Columns.Add(quot;SURFACEquot;, System.Type.GetType(quot;System.Stringquot;))
Il faut ensuite utiliser la propriété PrimaryKey de myDt (myDt.PrimaryKey) pour indiquer quelles
colonnes sont des clés primaires :
Dim PrimaryKeyColumns(0) As DataColumn ‘Tableau de colonnes
PrimaryKeyColumns(0) = myDt.Columns(quot;NOMquot;) ‘premier élément du tableau contient la
colonne NOM
myDt.PrimaryKey = PrimaryKeyColumns ‘attribution de la propriété PrimaryKey
Notons que l’instruction myDt.Columns(quot;NOMquot;) permet d’accéder à la colonne NOM de la DataTable.
Pour remplir notre DataSet avec le contenu d’un fichier XML il faut utiliser l’instruction
ReadXml(nom_du_fichier_xml) passée au DataSet.
Notre fichier XML pays.xml se trouvera normalement (après déploiement de la solution sur le
PocketPC) dans le répertoire racine de l’application. Pour accéder à ce répertoire nous allons utiliser
l’instruction :
appath =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().G
etName().CodeBase)
Le répertoire racine de l’application a été sauvegardé dans une variable « appath ».
Il suffit maintenant de spécifier le chemin complet du fichier pays.xml pour lire les données à l’aide du
DataSet et de l’instruction ReadXml:
myDs.ReadXml(String.Concat(appath, quot;pays.xmlquot;))
Notons que String.Concat permet de concaténer plusieurs chaines de caractères (comme
l’opérateur +).
Remarque :
Il faut rajouter les références suivante au projet afin de pouvoir utiliser les classe liées aux traitements
des fichiers XML et ayx DataSet (Solution Explorer, nom du projet, click droit Add Reference):
10
11. .NET Compact Framework, Tébourbi Riadh, SUP’COM
Ensuite il faut importer ces références avant de pouvoir les utiliser dans Form1 :
Imports System.Data
Imports System.Data.SqlClient
Imports System.IO
Pour résumer :
Nous allons créer deux variables attributs à notre classe Form1 et nous allons effectuer les opérations
d’initialisation dans la méthode Form_Load (la première méthode exécutée au lancement de
l’application) :
Imports System.Data
Imports System.Data.SqlClient
Imports System.IO
Public Class Form1
Dim myDs As New DataSet(quot;dbpaysquot;)
Dim myDt As DataTable = myDs.Tables.Add(quot;paysquot;)
Public appath As String
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles
MyBase.Load
'init datatable
myDt.Columns.Add(quot;NOMquot;, System.Type.GetType(quot;System.Stringquot;))
myDt.Columns.Add(quot;POPULATIONquot;, System.Type.GetType(quot;System.Stringquot;))
myDt.Columns.Add(quot;DEVISEquot;, System.Type.GetType(quot;System.Stringquot;))
myDt.Columns.Add(quot;SURFACEquot;, System.Type.GetType(quot;System.Stringquot;))
11
12. .NET Compact Framework, Tébourbi Riadh, SUP’COM
' Make the NOM column the primary key column.
Dim PrimaryKeyColumns(0) As DataColumn
PrimaryKeyColumns(0) = myDt.Columns(quot;NOMquot;)
myDt.PrimaryKey = PrimaryKeyColumns
'Init path variable
appath =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly()
.GetName().CodeBase)
'fill datatable with XML file content
myDt.Clear()
myDs.ReadXml(String.Concat(appath, quot;pays.xmlquot;))
End Sub
2) Créer la classe pays :
Dans notre application nous avons à manipuler des objets pays avec leurs attributs. Il serait judicieux de
créer une classe pays (démarche OO).
Pour créer une nouvelle classe, faites un click droit sur le nom du projet « dbpays_vb » puis
« AddNew item ». Choisissez alors « Class » comme item à insérer et précisez le nom de la classe :
pays.
Ouvrez le fichier pays.vb. Notons que la déclaration d’une classe commence par :
Public Class nom_de_la_classe
Et se termine par :
End Class
12
13. .NET Compact Framework, Tébourbi Riadh, SUP’COM
Un pays est définit par ses attributs NOM, POPULATION, DEVISE, SURFACE et DRAPEAU. Il faut
alors déclarer ces attributs dans la classe pays :
Imports Microsoft.VisualBasic
13
14. .NET Compact Framework, Tébourbi Riadh, SUP’COM
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.IO
Public Class pays
Private Nom As String
Private Population As Integer
Private Devise As String
Private Surface As Integer
Private Drapeau As Byte()
….
Notons que Drapeau est déclaré comme un tableau de byte (c’est une image stockée dans un tableau de
byte).
Il est possible de rajouter à la classe pays des « getter » et des « setter », ce sont des méthodes qui
permettent d’accéder à ses différents attributs. En VB .Net (et en C# aussi) ces méthodes s’appellent des
« Properties ». Par exemple, nous allons rajouter la propriété « pNom » qui permettra d’accéder à la
propriété NOM de la classe :
Public Property pNom() As String
Get
Return Nom
End Get
Set(ByVal value As String)
Nom = value
End Set
End Property
Par la suite, pour un objet « unpays » de la classe « pays », nous pouvons accéder à son attribut NOM
par :
A = unpays.pName ‘En lecture
unpays.pName = « Tunisia » ‘En ecriture
De même nous allons rajouter des méthodes pour accéder aux autres attributs de la classe pays à savoir :
Public Property pDevise() As String
Get
Return Devise
End Get
Set(ByVal value As String)
Devise = value
End Set
End Property
Public Property pPopulation() As Integer
Get
Return Population
End Get
Set(ByVal value As Integer)
Population = value
End Set
14
15. .NET Compact Framework, Tébourbi Riadh, SUP’COM
End Property
Public Property pSurface() As Integer
Get
Return Surface
End Get
Set(ByVal value As Integer)
Surface = value
End Set
End Property
Public Property pDrapeau() As Byte()
Get
Return Drapeau
End Get
Set(ByVal value As Byte())
Drapeau = value
End Set
End Property
En ce qui concerne les constructeurs de la classe pays nous allons en définir deux : un sans paramètres
(par défaut) et un avec 4 paramètres.
Pour le constructeur sans paramètres il s’agit de construire un pays par défaut :
Public Sub New()
' ----- Default constructor.
Nom = quot;?quot;
Population = 0
Devise = quot;?quot;
Surface = 0
setDrapeau()
End Sub
Pour le constructeur ayant 4 paramètres il s’agit de passer en argument des valeurs String pour les 4
premiers attributs :
Public Sub New(ByVal n As String, ByVal pop As Integer, ByVal dev As String, ByVal
surf As Integer)
' ----- Default constructor.
Nom = n
Population = pop
Devise = dev
Surface = surf
setDrapeau()
End Sub
Notons que pour les deux constructeurs, l’attribut Drapeau de la classe sera définit dans une méthode
setDrapeau(). Cette méthode définira automatiquement le drapeau du pays à partir de son nom. En effet,
par convention, le nom du fichier image est le même que le nom du pays : par exemple pour
NOM= « Tunisia » le drapeau correspondant est : « /appath/flags/tunisia.png », pour un pays inconnu
(NOM= « ? » , définit par le constructeur vide) le fichier drapeau est « /appath/flags/unknown.png »,:
15
16. .NET Compact Framework, Tébourbi Riadh, SUP’COM
Private Sub setDrapeau()
Dim MyImg As Image
If (Nom <> quot;?quot;) Then
MyImg = New Bitmap(String.Concat(Form1.appath, quot;flagsquot;, Nom, quot;.pngquot;))
Else
MyImg = New Bitmap(String.Concat(Form1.appath, quot;flagsunknown.pngquot;))
End If
Dim MemStr As New MemoryStream()
MyImg.Save(MemStr, ImageFormat.Png)
Me.pDrapeau = MemStr.GetBuffer()
End Sub
Dans cette méthode on commence par lire le fichier image drapeau du pays (selon son Nom) et le stocker
dans la variable myImage.
Ensuite, cette image est stockée dans un flux de données (MemoryStream) au format Png , puis, on
récupère le tableau de byte par la méthode GetBuffer de la classe MemoryStream.
Phase 3
1) Fonctionnalité 2
Quand on clique sur le bouton « Info » l’application va chercher un pays dont le nom est donné par
l’utilisateur grâce à la zone de texte « Npays ». Si le pays existe ses information seront affichées si ce
pays n’existe pas des informations par défaut seront utilisées. Cette fonctionnalité est implémentée dans
une méthode afficheInfos() de la classe Form1 :
Private Sub afficheInfos()
Dim objBitmap As Bitmap
Dim strmBuffer As MemoryStream
Dim myrow As DataRow = myDt.Rows.Find(Npays.Text)
Dim p As pays
If myrow IsNot Nothing Then
p = New pays(Npays.Text, Integer.Parse(myrow(quot;POPULATIONquot;).ToString),
myrow(quot;DEVISEquot;).ToString(), Integer.Parse(myrow(quot;SURFACEquot;).ToString))
Else
p = New pays()
End If
Pop.Text = p.pPopulation
Surf.Text = p.pSurface
Dev.Text = p.pDevise.ToString
Npays.Text = p.pNom.ToString
strmBuffer = New System.IO.MemoryStream(p.pDrapeau)
objBitmap = New Bitmap(strmBuffer)
Flag.Image = objBitmap
End Sub
16
17. .NET Compact Framework, Tébourbi Riadh, SUP’COM
Pour chercher dans une table un enregistrement particulier dont la valeur d’une clé primaire est égale à
« criteria » il faut utiliser la méthode « find » :
Dim myrow As DataRow = myDt.Rows.Find(criteria)
On récupère ainsi un objet de la classe DataRow (myrow) qui est la ligne recherchée de la table (myrow
est vide si pas de résultat trouvé).
A partir de cette variable « myrow » nous pouvons ensuite construire un objet p de la classe pays (si
myrow est null un objet par défaut est construit utilisation du constructeur par défaut).
Les informations de ce pays p construit sont ensuite affichées sur la « TabPage1 ».
L’image du drapeau du pays est construite à partir de p.pDrapeau (tableau de byte) en réalisant
l’opération inverse : créer une image à partir d’un tableau de byte. Pour cela un objet MemoryStream
(strmBuffer) est encore utilisé, il est construit à partir du tableau de byte : p.pDrapeau :
strmBuffer = New System.IO.MemoryStream(p.pDrapeau)
Un objet Bitmap (objBitmap) est ensuite construit à partir du MemoryStream et sa valeur est enfin
attribuée à la propriété Image de la PictureBox « Flag » :
objBitmap = New Bitmap(strmBuffer)
Flag.Image = objBitmap
Cette méthode, afficheInfos, est appelée dans l’événement Click sur le bouton « Info » de telle
manière qu’elle est exécutée quand on clique sur ce bouton :
Private Sub Info_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles Info.Click
afficheInfos()
End Sub
2) Fonctionnalité 3 : Rechercher un pays
Quand l’utilisateur entre un critère de recherche dans la zone texte « Crit » et clique sur le bouton
« Rech » l’application recherche les pays contenant la chaine de caractères définie dans « Crit » et
affiche leurs noms dans la liste « Result ».
La méthode « select » de la classe DataSet est utilisée pour rechercher des enregistrements particuliers
selon un critère (SQL) donné. Le résultat est récupéré dans un tableau de « DataRow » (foundRows) :
Dim expression As String
Dim sortOrder As String
expression = quot;NOM LIKE quot; & quot;'%quot; & Crit.Text & quot;%'quot;
' Sort descending by Name column.
sortOrder = quot;NOM ASCquot;
' Use the Select method to find all rows matching the criteria.
Dim foundRows As DataRow() = myDt.Select(expression, sortOrder,
DataViewRowState.Added)
Les lignes trouvées de la table sont ensuite utilisées pour remplir la liste par les noms des pays trouvés :
17
18. .NET Compact Framework, Tébourbi Riadh, SUP’COM
'fill the list box with found results
Result.Items.Clear()
If foundRows.Length <= 0 Then
Exit Sub
End If
Dim row As DataRow
For Each row In foundRows
Result.Items.Add(row(quot;NOMquot;))
Next row
Pour résumer
Private Sub Rech_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles Rech.Click
Dim expression As String
Dim sortOrder As String
expression = quot;NOM LIKE quot; & quot;'%quot; & Crit.Text & quot;%'quot;
' Sort descending by Name column.
sortOrder = quot;NOM ASCquot;
' Use the Select method to find all rows matching the criteria.
Dim foundRows As DataRow() = myDt.Select(expression, sortOrder,
DataViewRowState.Added)
'fill the list box with found results
Result.Items.Clear()
If foundRows.Length <= 0 Then
Exit Sub
End If
Dim row As DataRow
For Each row In foundRows
Result.Items.Add(row(quot;NOMquot;))
Next row
End Sub
En sélectionnant un pays de la liste et en cliquant sur le bouton « Ainfo » , les informations du pays
seront affichées sur la « TabPage1 » :
Private Sub Ainfo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles Ainfo.Click
If (Result.Items.Count > 0) Then
Npays.Text = Result.SelectedItem.ToString
afficheInfos()
TabPage1.BringToFront()
TabPage2.SendToBack()
End If
End Sub
Une fois que la zone de texte « Npays » est initialisée par le nom du pays sélectionné, la méthode
afficheInfos() est appelée.
18
19. .NET Compact Framework, Tébourbi Riadh, SUP’COM
Notons que pour accéder à l’élément sélectionné de la liste (ListBox) on utilise sa propriété
SelectedItem.
19