Traduction▲
Ce tutoriel est la traduction la plus fidèle possible du tutoriel original de Peter Bull, Windows Phone 7 - Simple Drawing Package with InkPresenter using Silverlight on Windows Phone 7.
Introduction▲
Doodle Pad est un logiciel de dessin simple utilisant le contrôle InkPresenter en Silverlight pour Windows Phone 7. L'application dispose des fonctionnalités pour définir la taille et la couleur, ainsi que la prise en charge des fonctions pour ouvrir/enregistrer en utilisant LINQ to XML.
Logiciel de dessin simple avec InkPresenter en utilisant Silverlight sur Windows Phone 7▲
Étape 1▲
Démarrez Microsoft Visual Web Developer 2010 Express pour Windows Phone, ensuite sélectionnez Fichier, puis Nouveau Projet… Sélectionnez Visual C#, ensuite Silverlight for Windows Phone, puis Application Windows Phone dans les modèles installés, sélectionnez un emplacement si vous le souhaitez, puis entrez un nom pour le projet et appuyez sur OK :
Étape 2▲
Étape 3▲
Sélectionnez Projet, puis Ajouter une référence… La fenêtre Ajouter une référence devrait apparaître, sélectionnez System.Xml.Linq dans la liste .NET :
Étape 4▲
Ajoutez la référence à System.Xml.Linq en cliquant sur OK. Faites un clic droit sur l'entrée App.xaml dans l'Explorateur de solutions et choisissez Afficher le code. Dans la vue de code de App.xaml.cs, au-dessus de la ligne public App(), tapez ceci :
public string Filename { get; set;}
public object Content { get; set;}
Étape 5▲
Faites un clic droit sur le Projet dans l'Explorateur de solutions et choisissez Ajouter, ensuite Nouveau dossier et nommez-le « images » (sans les guillemets) :
Étape 6▲
Téléchargez les images suivantes (delete.png, new.png, open.png et save.png respectivement) en faisant un clic droit sur les images ci-dessous et en choisissant « Enregistrer l'image sous… ». Enregistrez-les dans un dossier sur votre ordinateur :
delete.png
new.png
open.png
save.png
Étape 7▲
Faites un clic droit sur le dossier « images » du Projet dans l'Explorateur de solutions, et choisissez Ajouter, ensuite Élément existant… Puis dans la fenêtre Ajouter un élément existant, sélectionnez le dossier dans lequel vous avez enregistré les images, puis choisissez Ajouter pour ajouter les images delete.png, new.png, open.png et save.png au dossier « images » dans le projet :
Étape 8▲
Toujours dans l'Explorateur de solutions, cliquez sur l'image « delete.png ». Ensuite allez dans la boite Propriétés et modifiez Action de génération à Contenu, faites la même chose pour les images « new.png », « open.png » et « save.png » :

Étape 9▲
Dans l'Explorateur de solutions, sélectionnez l'entrée Doodle Pad dans la liste, en dessous de l'entrée Solution. Ensuite sélectionnez Projet, puis Ajouter un nouvel élément… et sélectionnez le modèle Page en mode portrait Windows Phone, ensuite modifiez le Nom en OpenPage.xaml :
Étape 10▲
Cliquez sur Ajouter pour ajouter une nouvelle Page en mode portrait Windows Phone au Projet. Ensuite, dans le volet XAML de OpenPage.xaml, au-dessus de la balise <Grid x:Name="LayoutRoot" Background="Transparent">, tapez le code ApplicationBar XAML suivant :
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" IsMenuEnabled="False">
<shell:ApplicationBar.Buttons>
<shell:ApplicationBarIconButton Text="open" IconUri="/images/open.png" Click="Open_Click"/>
<shell:ApplicationBarIconButton Text="delete" IconUri="/images/delete.png" Click="Delete_Click"/>
</shell:ApplicationBar.Buttons>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>Étape 11▲
Toujours dans le volet XAML, entre les lignes <Grid x:Name="ContentGrid" Grid.Row="1"> et </Grid>, tapez le code XAML suivant :
<ListBox Margin="10" FontSize="{StaticResource PhoneFontSizeExtraLarge}" Name="Files"/>XAML :
Design :
Étape 12▲
Faites un clic droit sur la page ou sur l'entrée de OpenPage.xaml dans l'Explorateur de solutions et choisissez l'option Afficher le code. Dans la vue de code, au-dessus de namespace DoodlePad, tapez ceci :
using System.IO.IsolatedStorage;
using System.Xml.Linq;
using System.Windows.Ink;Également dans la vue de code, au-dessus de public OpenPage(), tapez la déclaration Application suivante :
public App app = (App)Application.Current;Étape 13▲
Puisque nous en sommes à la vue de code de OpenPage.xaml.cs, dans le constructeur public OpenPage() en dessous de InitializeComponent();, tapez ceci :
ApplicationTitle.Text = "DOODLE PAD";
PageTitle.Text = "open";
Loaded += (object sender, RoutedEventArgs e) =>
{
using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
{
foreach (string filename in storage.GetFileNames("*.ipr"))
{
Files.Items.Add(filename.ToLower());
}
}
};Étape 14▲
Toujours dans la vue de code de OpenPage.xaml.cs, en dessous du « } » de la méthode public OpenPage(), tapez les gestionnaires d'événements suivants :
private void Open_Click(object sender, EventArgs e)
{
if (Files.SelectedItem != null)
{
app.Filename = (string)Files.SelectedItem;
using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
{
XElement _xml;
Stroke _stroke = new Stroke();
StrokeCollection _strokes = new StrokeCollection();
DrawingAttributes _drawAttr = new DrawingAttributes();
IsolatedStorageFileStream location = new IsolatedStorageFileStream(app.Filename,
System.IO.FileMode.Open, storage);
System.IO.StreamReader file = new System.IO.StreamReader(location);
_xml = XElement.Parse(file.ReadToEnd());
foreach (XElement element in _xml.Elements("Stroke"))
{
foreach (XElement item in element.Elements("Stroke.DrawingAttributes")
.Elements("DrawingAttributes"))
{
_drawAttr = new DrawingAttributes
{
Color = Color.FromArgb(
byte.Parse(item.Attribute("Color").Value.Substring(1, 2),
System.Globalization.NumberStyles.HexNumber),
byte.Parse(item.Attribute("Color").Value.Substring(3, 2),
System.Globalization.NumberStyles.HexNumber),
byte.Parse(item.Attribute("Color").Value.Substring(5, 2),
System.Globalization.NumberStyles.HexNumber),
byte.Parse(item.Attribute("Color").Value.Substring(7, 2),
System.Globalization.NumberStyles.HexNumber)),
Width = double.Parse(item.Attribute("Width").Value),
Height = double.Parse(item.Attribute("Height").Value)
};
}
foreach (XElement item in element.Elements("Stroke.StylusPoints"))
{
_stroke = new Stroke();
_stroke.DrawingAttributes = _drawAttr;
foreach (XElement point in item.Elements("StylusPoint"))
{
_stroke.StylusPoints.Add(new StylusPoint
{
X = double.Parse(point.Attribute("X").Value),
Y = double.Parse(point.Attribute("Y").Value)
});
}
_strokes.Add(_stroke);
}
}
app.Content = _strokes;
file.Dispose();
location.Dispose();
}
NavigationService.GoBack();
}
}
private void Delete_Click(object sender, EventArgs e)
{
if (Files.SelectedItem != null)
{
string _selected = (string)Files.SelectedItem;
if (MessageBox.Show("Delete selected Item " + _selected + "?", "Doodle Pad",
MessageBoxButton.OKCancel) == MessageBoxResult.OK)
{
using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
{
if (storage.FileExists(_selected))
{
storage.DeleteFile(_selected);
}
}
NavigationService.GoBack();
}
}
}Étape 15▲
Sélectionnez Projet, puis Ajouter un nouvel élément… et sélectionnez le modèle Page en mode portrait Windows Phone, ensuite modifiez le Nom en SavePage.xaml :
Étape 16▲
Cliquez sur Ajouter pour ajouter une nouvelle Page en mode portrait Windows Phone au Projet. Ensuite dans le concepteur de vues pour SavePage.xaml, dans le volet XAML entre les lignes <Grid x:Name="ContentGrid" Grid.Row="1"> et </Grid>, tapez le code XAML suivant :
<StackPanel>
<TextBlock Text="Filename"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Name="Filename">
<TextBox.InputScope>
<InputScope>
<InputScopeName NameValue="FileName"/>
</InputScope>
</TextBox.InputScope>
</TextBox>
<Button Grid.Column="1" Content="save" Click="Save_Click"/>
</Grid>
</StackPanel>XAML :
Design :
Étape 17▲
Faites un clic droit sur la page ou sur l'entrée de SavePage.xaml dans l'Explorateur de solutions et choisissez l'option Afficher le code. Dans la vue de code, au-dessus de namespace DoodlePad, tapez ceci :
using System.IO.IsolatedStorage;
using System.Xml.Linq;
using System.Windows.Ink;Également dans la vue de code, au-dessus de public SavePage(), tapez la déclaration Application suivante :
public App app = (App)Application.Current;Étape 18▲
Puisque nous en sommes à la vue de code de SavePage.xaml.cs, dans le constructeur public SavePage() en dessous de InitializeComponent();, tapez ceci :
ApplicationTitle.Text = "DOODLE PAD";
PageTitle.Text = "save";
Loaded += (object sender, RoutedEventArgs e) =>
{
if (app.Filename == null || app.Filename == "")
{
Filename.Text = "untitled.ipr";
}
else
{
Filename.Text = app.Filename;
}
};
Étape 19▲
Toujours dans la vue de code de SavePage.xaml.cs, en dessous du « } » de la méthode public SavePage(), tapez les gestionnaires d'événements suivants :
private void Save_Click(object sender, RoutedEventArgs e)
{
if (Filename.Text != "")
{
try
{
app.Filename = Filename.Text.Trim().ToLower();
using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
{
XDocument _doc = new XDocument();
StrokeCollection _strokes = new StrokeCollection();
_strokes = (StrokeCollection)app.Content;
XElement _strokecollection = new XElement("StrokeCollection");
foreach (Stroke item in _strokes)
{
XElement _stroke = new XElement("Stroke");
XElement _strokeAttr = new XElement("Stroke.DrawingAttributes");
XElement _attributes = new XElement("DrawingAttributes");
XAttribute _color = new XAttribute("Color", item.DrawingAttributes.Color);
XAttribute _width = new XAttribute("Width", item.DrawingAttributes.Width);
XAttribute _height = new XAttribute("Height", item.DrawingAttributes.Height);
_attributes.Add(_color, _width, _height);
_strokeAttr.Add(_attributes);
XElement _points = new XElement("Stroke.StylusPoints");
foreach (StylusPoint point in item.StylusPoints)
{
XElement _point = new XElement("StylusPoint");
XAttribute _x = new XAttribute("X", point.X);
XAttribute _y = new XAttribute("Y", point.Y);
_point.Add(_x, _y);
_points.Add(_point);
}
_stroke.Add(_strokeAttr, _points);
_strokecollection.Add(_stroke);
}
_doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), _strokecollection);
IsolatedStorageFileStream location = new IsolatedStorageFileStream(app.Filename,
System.IO.FileMode.Create, storage);
System.IO.StreamWriter file = new System.IO.StreamWriter(location);
_doc.Save(file);
app.Content = null;
file.Dispose();
location.Dispose();
}
NavigationService.GoBack();
}
catch
{
// Ignore Errors
}
}
}Étape 20▲
Sélectionnez l'onglet MainPage.xaml, ensuite dans le volet XAML de MainPage.xaml, au-dessus de la balise <Grid x:Name="LayoutRoot" Background="Transparent">, tapez le code ApplicationBar XAML suivant :
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" IsMenuEnabled="False">
<shell:ApplicationBar.Buttons>
<shell:ApplicationBarIconButton Text="new" IconUri="/images/new.png" Click="New_Click"/>
<shell:ApplicationBarIconButton Text="open" IconUri="/images/open.png" Click="Open_Click"/>
<shell:ApplicationBarIconButton Text="save" IconUri="/images/save.png" Click="Save_Click"/>
</shell:ApplicationBar.Buttons>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>Étape 21▲
Ensuite dans le volet XAML, entre les lignes <Grid x:Name="ContentGrid" Grid.Row="1"> et </Grid>, tapez le code XAML suivant :
<Grid x:Name="ContentMain">
<Grid.RowDefinitions>
<RowDefinition Height="90"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="Toolbar" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- Toolbar -->
</Grid>
<!-- Content -->
</Grid>XAML :

Design :
Étape 22▲
Toujours dans le volet XAML au sein du Grid ContentMain, en dessous de <!--Toolbar-->, tapez le code ListBox XAML suivant :
<ListBox Grid.Column="0" Name="Size"
SelectionChanged="Size_SelectionChanged">
<ListBoxItem Tag="1">
<Rectangle Margin="10" Width="340" Height="1" Fill="{StaticResource PhoneAccentBrush}"/>
</ListBoxItem>
<ListBoxItem Tag="2">
<Rectangle Margin="10" Width="340" Height="2" Fill="{StaticResource PhoneAccentBrush}"/>
</ListBoxItem>
<ListBoxItem Tag="5" IsSelected="True">
<Rectangle Margin="10" Width="340" Height="5" Fill="{StaticResource PhoneAccentBrush}"/>
</ListBoxItem>
<ListBoxItem Tag="10">
<Rectangle Margin="10" Width="340" Height="10" Fill="{StaticResource PhoneAccentBrush}"/>
</ListBoxItem>
<ListBoxItem Tag="15">
<Rectangle Margin="10" Width="340" Height="15" Fill="{StaticResource PhoneAccentBrush}"/>
</ListBoxItem>
<ListBoxItem Tag="20">
<Rectangle Margin="10" Width="340" Height="20" Fill="{StaticResource PhoneAccentBrush}"/>
</ListBoxItem>
<ListBoxItem Tag="25">
<Rectangle Margin="10" Width="340" Height="25" Fill="{StaticResource PhoneAccentBrush}"/>
</ListBoxItem>
<ListBoxItem Tag="30">
<Rectangle Margin="10" Width="340" Height="30" Fill="{StaticResource PhoneAccentBrush}"/>
</ListBoxItem>
<ListBoxItem Tag="40">
<Rectangle Margin="10" Width="340" Height="40" Fill="{StaticResource PhoneAccentBrush}"/>
</ListBoxItem>
<ListBoxItem Tag="50">
<Rectangle Margin="10" Width="340" Height="50" Fill="{StaticResource PhoneAccentBrush}"/>
</ListBoxItem>
</ListBox>
<ListBox Grid.Column="1" Width="120" Name="Colour"
SelectionChanged="Colour_SelectionChanged">
<ListBoxItem Tag="FF000000" IsSelected="True">
<Rectangle Margin="5" Width="120" Height="20" Fill="Black"/>
</ListBoxItem>
<ListBoxItem Tag="FF808080">
<Rectangle Margin="5" Width="120" Height="20" Fill="Gray"/>
</ListBoxItem>
<ListBoxItem Tag="FFFF0000">
<Rectangle Margin="5" Width="120" Height="20" Fill="Red"/>
</ListBoxItem>
<ListBoxItem Tag="FFFFA500">
<Rectangle Margin="5" Width="120" Height="20" Fill="Orange"/>
</ListBoxItem>
<ListBoxItem Tag="FFFFFF00">
<Rectangle Margin="5" Width="120" Height="20" Fill="Yellow"/>
</ListBoxItem>
<ListBoxItem Tag="FF008000">
<Rectangle Margin="5" Width="120" Height="20" Fill="Green"/>
</ListBoxItem>
<ListBoxItem Tag="FF00FFFF">
<Rectangle Margin="5" Width="120" Height="20" Fill="Cyan"/>
</ListBoxItem>
<ListBoxItem Tag="FF0000FF">
<Rectangle Margin="5" Width="120" Height="20" Fill="Blue"/>
</ListBoxItem>
<ListBoxItem Tag="FFFF00FF">
<Rectangle Margin="5" Width="120" Height="20" Fill="Magenta"/>
</ListBoxItem>
<ListBoxItem Tag="FF800080">
<Rectangle Margin="5" Width="120" Height="20" Fill="Purple"/>
</ListBoxItem>
</ListBox>XAML :
Design :
Étape 23▲
En étant toujours dans le volet XAML de MainPage.xaml, en dessous de la ligne <!-- Content -->, tapez le code InkPresenter XAML suivant :
<InkPresenter Grid.Row="1" Background="White" Name="Surface"
MouseLeftButtonDown="Surface_MouseLeftButtonDown"
MouseLeftButtonUp="Surface_MouseLeftButtonUp"
MouseMove="Surface_MouseMove" />XAML :

Design :
Étape 24▲
Sélectionnez l'onglet MainPage.xaml, ensuite faites un clic droit sur la page ou sur l'entrée de MainPage.xaml dans l'Explorateur de solutions et choisissez l'option Afficher le code. Dans la vue de code, au-dessus de namespace DoodlePad, tapez ceci :
using System.Xml.Linq;
using System.Windows.Ink;Également dans la vue de code, au-dessus de public MainPage(), tapez les déclarations suivantes :
public App app = (App)Application.Current;
public Stroke drawStroke;
public Color drawColour = Colors.Black;
public Size drawSize = new Size { Height = 5, Width = 5 };Étape 25▲
Puisque nous en sommes à la vue de code de MainPage.xaml.cs, dans le constructeur public MainPage() en dessous de InitializeComponent();, tapez ceci :
ApplicationTitle.Text = "DOODLE PAD";
PageTitle.Text = "untitled.ipr";
Loaded += (object sender, RoutedEventArgs e) =>
{
if (app.Content != null)
{
Surface.Strokes.Clear();
Surface.Strokes = (StrokeCollection)app.Content;
}
if (app.Filename == null || app.Filename == "")
{
PageTitle.Text = "untitled.ipr";
}
else
{
PageTitle.Text = app.Filename;
}
};Étape 26▲
En étant toujours dans la vue de code de MainPage.xaml.cs, en dessous du « } » de la méthode public MainPage(), tapez les gestionnaires d'événements suivants :
private void New_Click(object sender, EventArgs e)
{
if (MessageBox.Show("Start a new Doodle?", "Doodle Pad",
MessageBoxButton.OKCancel) == MessageBoxResult.OK)
{
PageTitle.Text = "untitled.ipr";
Surface.Strokes.Clear();
app.Filename = PageTitle.Text;
app.Content = Surface.Strokes;
}
}
private void Open_Click(object sender, EventArgs e)
{
app.Content = Surface.Strokes;
NavigationService.Navigate(new Uri("/OpenPage.xaml", UriKind.Relative));
}
private void Save_Click(object sender, EventArgs e)
{
app.Content = Surface.Strokes;
NavigationService.Navigate(new Uri("/SavePage.xaml", UriKind.Relative));
}
private void Surface_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
drawStroke = new Stroke();
drawStroke.DrawingAttributes.Color = drawColour;
drawStroke.DrawingAttributes.Width = drawSize.Width;
drawStroke.DrawingAttributes.Height = drawSize.Height;
drawStroke.StylusPoints.Add(new StylusPoint
{
X = e.GetPosition(Surface).X,
Y= e.GetPosition(Surface).Y
});
Surface.Strokes.Add(drawStroke);
}
private void Surface_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
drawStroke = null;
}
private void Surface_MouseMove(object sender, MouseEventArgs e)
{
if (drawStroke != null)
{
drawStroke.StylusPoints.Add(new StylusPoint
{
X = e.GetPosition(Surface).X,
Y = e.GetPosition(Surface).Y
});
}
}
private void Size_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (Size != null)
{
double _drawWidth = double.Parse(((ListBoxItem)Size.SelectedItem).Tag.ToString());
drawSize = new Size { Height = _drawWidth, Width = _drawWidth };
}
}
private void Colour_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (Colour != null)
{
string _colour = (string)((ListBoxItem)Colour.SelectedItem).Tag;
drawColour = Color.FromArgb(
byte.Parse(_colour.Substring(0, 2),
System.Globalization.NumberStyles.HexNumber),
byte.Parse(_colour.Substring(2, 2),
System.Globalization.NumberStyles.HexNumber),
byte.Parse(_colour.Substring(4, 2),
System.Globalization.NumberStyles.HexNumber),
byte.Parse(_colour.Substring(6, 2),
System.Globalization.NumberStyles.HexNumber));
}
}Étape 27▲
Enregistrez le Projet maintenant que vous avez terminé l'application Windows Phone Silverlight. Sélectionnez l'option Windows Phone Emulator, ensuite sélectionnez Debug puis Démarrer le débogage ou cliquez sur Démarrer le débogage :
Dès que vous l'aurez fait, ce qui suit apparaîtra dans l'émulateur Windows Phone une fois chargé :
Étape 28▲
Faites défiler la ListBox Colour puis appuyez sur une couleur, par exemple bleu pour sélectionner une couleur. Sélectionnez une taille de la même manière, puis appuyez et maintenez afin de dessiner quelque chose qui pourra ensuite être sauvegardé :
Étape 29▲
Vous pouvez ensuite Arrêter l'application en sélectionnant la fenêtre d'application Visual Studio 2010 et en cliquant sur le bouton Arrêter le débogage :

Conclusion▲
Ceci est un exemple simple d'application de dessin, utilisant InkPresenter et LINQ to XML pour enregistrer et ouvrir les « traits » utilisés pour dessiner. Essayez d'ajouter davantage de fonctionnalités telles que des tailles et des couleurs additionnelles - personnalisez-la !
Liens▲
Remerciements▲
Je tiens ici à remercier Peter Bull de m'avoir autorisé à traduire son tutoriel.
Je remercie tomlev pour sa relecture technique et ses propositions.
Je remercie également Gurdil_le_nain pour sa relecture orthographique et ses propositions.




































