Comme le dit le père catuhe dans son billet concernant le Jour 4, nous pouvons considérer que c’est le dernier jour de notre série.
Vous retrouverez le code liée à cette article ici :http://aka.ms/isz0ot
Ainsi que les jours précédent :
Jour 0 (la Consumer Preview)
Jour 1 : (Consumer preview)
Jour 2 : (Release Preview)
Jour 2 Optimisé :(Release preview)
Jour 3
Dans la page d’extension, nous allons pouvoir ajouter une barre d’application contextuelle afin de permettre à l’utilisateur
d’indiquer quelles cartes sont présentes dans sa collection :
Les nouveaux boutons de la barre d’outils sont alors les suivants :
Code Snippet <Page.BottomAppBar> <AppBar x:Name="PageAppBar" Padding="10,0,10,0" IsSticky="{Binding DisplayElement,Converter={StaticResource BooleanToIsOpenConverter}}"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="50*"/> <ColumnDefinition Width="50*"/> </Grid.ColumnDefinitions> <StackPanel x:Name="LeftCommands" Orientation="Horizontal" Grid.Column="0" HorizontalAlignment="Left"> <Button x:Name="AddButton" x:Uid="AddButton" Visibility="{Binding DisplayElement, Converter={StaticResource IntToVisibilityConverter}}" HorizontalAlignment="Left" Style="{StaticResource CheckAppBarButtonStyle}" Click="AddButton_Click"/> <Button x:Name="DelButton" x:Uid="DelButton" Visibility="{Binding DisplayElement, Converter={StaticResource IntToVisibilityConverter}}" HorizontalAlignment="Left" Style="{StaticResource UnCheckAppBarButtonStyle}" Click="DelButton_Click" /> </StackPanel> <StackPanel x:Name="RightCommands" Orientation="Horizontal" Grid.Column="1" HorizontalAlignment="Right"> <Button x:Name="AddAllButton" x:Uid="AddAllButton" HorizontalAlignment="Left" Style="{StaticResource CheckAppBarButtonStyle}" Click="AddAllButton_Click" /> <Button x:Name="DelAllButton" x:Uid="DelAllButton" HorizontalAlignment="Left" Style="{StaticResource UnCheckAppBarButtonStyle}" Click="DelAllButton_Click" /> <Button x:Name="AlbumButton" x:Uid="AlbumButton" HorizontalAlignment="Left" Style="{StaticResource AlbumAppBarButtonStyle}" /> <Button x:Name="PinButton" x:Uid="PinButton" Visibility="{Binding PinUnpinSecondaryTile, Converter={StaticResource BooleanToCollapseConverter}}" HorizontalAlignment="Right" Style="{StaticResource PinAppBarButtonStyle}" Click="Pin_Click" /> <Button x:Name="UnPinButton" x:Uid="UnPinButton" Visibility="{Binding PinUnpinSecondaryTile,Converter={StaticResource BooleanToVisibilityConverter}}" HorizontalAlignment="Right" Style="{StaticResource UnpinAppBarButtonStyle}" Click="UnPin_Click" /> </StackPanel> </Grid> </AppBar> </Page.BottomAppBar>
Les commandes contextuelles AddButton et DelButton se trouvant à gauche les autres à droite.
1ere remarque : Tout d’abord, le style des boutons est défini sur un style particulier par exemple CheckAppBarButtonStyle pour le bouton AddButton.
Ce style est présent dans le fichier StandardStyles.xaml,
Ce qui donne comme résultat
Ce que l’on peut constater c’est que la propriété Content est remplie par le code de caractère 2714, ce qui dans la fonte Segoe UI Symbol donne ✔ et que le texte “Ajouter” est un texte qui provient de la propriété AutomationProperties.Name. Pour que ce texte soit traduit automatiquement en fonction du langage choisi dans les préférences de Windows, il faut encore une fois utiliser la propriété x:Uid du bouton, comme je l’ai indiqué dans le jour 2 de cette série.
Néanmoins, la syntaxe est légérement différente et ne s’invente pas malheureusement. Si vous retournez dans le fichier Resources.resw, il faudra ajouter la syntaxe suivante :
Name = AddButton.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name
Value = Ajouter
Les boutons contextuels sont réglés pour apparaitre en fonction de la selection à l’aide du modèle DisplayElement, qui sera renseigné à l’ouverture de l’AppBar, par le nombre d’éléments sélectionnés.
et du Converter IntToVisibilityConverter attaché à sa propriété Visibility.
Par défaut, la selection multiple du contrôle GridView n’étant pas activée, il ne faut pas oublier de le faire.
Ensuite sur l’évenement click des boutons AddButton/DelButton par exemple , nous allons tout d’abord déclencher la méthode SetUserData, qui aura juste pour rôle d’affecter à la propriété IsChecked d’un objet UrzaCard, si oui ou non elle fait partie de la collection de l’utilisateur.
Code Snippet private async void AddButton_Click(object sender, RoutedEventArgs e) { try { SetUserData(true); await _vueData.SerializeUserDataAsync(); } catch (Exception ex) { Helper.ShowOnError(ex, UrzaResources.AppErrorMessage); } } private void SetUserData(bool adddata) { var SelectedCardsItem = CardsItemsGridView.SelectedItems; foreach (var objCard in SelectedCardsItem) { var card = (URZACard)objCard; card.IsChecked = adddata; } if (adddata == false) { foreach (var objCard in SelectedCardsItem) { CardsItemsGridView.SelectedItems.Remove((URZACard)objCard); } } if (SelectedCardsItem.Count > 0 || adddata == false) _vueData.AppliedFiltersAsync(); }
Puis ensuite nous déclenchons la sauvegarde, ou plutot la sérialisation XML de la collection de l’utilisateur. SerializeUserDataAsync()
Pour la serialisation de la collection de l’utilisateur, j’ai, pour simplifier le processus, crée de nouvelles classes sérialisables qui ne contiendront que le strict minimum
et ceci afin d’éviter de sérialiser la totalité des données contenues dans une carte.
En faite, dans le code livré avec ce billet, c’est un peu plus complexe que cela et je vous laisse le découvrir. Mais le principe est de tester si le fichier existe déjà, si oui de déserialiser les données qu’il contient, afin de les fusionner avec les données qui viennent d’être selectionnées. Cela se complique encore, lorsque le fichier est présent sur SkyDrive (Connexion que nous verrons plus tard), car il faudra tester la version de la collection de l’utilisateur.
Pour identifier qu’une carte est selectionnée, on va utiliser la propriété IsChecked de chaque carte afin de lui affecter un style particulier comme dans l’image suivante :
Pour se faire : on va passer dans mon exemple par un DataTemplateSelector
Dans le fichier Expansion.Xaml, il suffira alors d’y faire reference dans les ressources, puis d’indiquer l’ItemTemplateSelector adéquate pour le GridView.
La collection de l’utilisateur sera à la fois sauvegardée localement, mais également sur son compte SkyDrive.
Tout d’abord, vous devez télécharger et installer le SDK Live. et le référencer dans votre projet :
Le SDK s’installant dans le répertoire : C:\Program Files (x86)\Microsoft SDKs\Live\v5.0
Ensuite il faut inscrire votre application, afin d’obtenir un Package Name, qui permettra d’identifer votre application de façon unique comme illustré sur la figure suivante . Pour cela il suffit de suivre les étapes décrites ici : https://manage.dev.live.com/build?wa=wsignin1.0
Si vous ne suivez pas cette étape, la connexion à SkyDrive ne fonctionnera pas.
Avec ce SDK, il est possible de créer son propre bouton de connexion comme décrit par David Catuhe dans son article, ou alors d’utiliser le contrôle prévu à cette effet, comme je l’ai fait dans la vue Home.XAML
Lors de la 1ere utilisation, la boite de connexion s’affiche.
Une fois connecté j’affiche l’état de la connexion en affichant le nom de la personne connectée.
Pour contrôler ce qui se passe, j’ai abonné le bouton à l’évenement SessionChanged, dans lequel je vais initialiser les options de SkyDrive par l’intermediaire d’une classe Helper SkyDriveHelper
La méthode InitAuthenticationAsync(), va initialiser le champ d’application de l’application. Entre autre la possibilité de mettre à jour SkyDrive, car ensuite nous allons y créer un repertoire, puis y uploader un fichier. Ensuite je crée une connection client avec l’état de session, puis je télécharge le profile de la connection, me permettant d’afficher le nom de l’utilisateur connecté.
La création du repertoire “Urza” sur SkyDrive est assez simple, il suffira de poster les informations nécessaire à sa création. puis de sauvegarder son numéro d’identification dans les paramètres itinérant. Ce numéro d’identification qui est sous la forme “folder.9607f0bf305f86d2.9607F0BF305F86D2!681” nous servira comme chemin pour l’upload du fichier de la collection des cartes. A noter que je retourne true ou false, ce qui permet de determiner dans la propriété IsFirstConnectionToSkyDrive si c’est la 1ere fois que le répertoire a été crée.
L’upload du fichier sur SkyDrive ce fait à chaque fois que l’utilisateur ajoute ou supprime une carte dans sa collection, est également assez simple,
il suffit d’utiliser la méthode BackGroundUploadAsync du SDK Live.
Cette méthode prend comme paramère :
Ensuite, nous sauvegardons la source du fichier dans les paramètres itinérant, qui correspond à une Uri du type :
http://storage.live.com/s1pBoQfS-WhonrKV7bCPsqQdDOLTtuQShJ76mz4EwW9_2OsgyP5M4_aY7BncUOTpfWsdsrHKID31j4F9Huo7h31W9DhUbl9WjFIa0hpeP7WDCJs3W4CEFMfOZyXnofcbCgn/UserData.txt:Binary,Default/UserData.txt
Et ceci car nous la réutiliseront par la suite.
Ensuite tout se passe au chargement de la vue Expansion, ou j’appelle la méthode DeserializeUserDataAsync().
Cette méthode à pour but de déserialiser le flux XML pour en construire une classe URZAUserData, afin de mettre la propriété IsCheck à true, en fonction de la présence
de la carte dans le fichier.
Néanmoins, avant on va la 1ere fois tester si la version locale du fichier est plus récente que la version sur SkyDrive et en fonction récuperer le bon flux de données
Le téléchargement du fichier est assez simple, car il suffit d’utiliser la source (correspondant à l’uri vue plus haut) avec la méthode BackgroundDownloadAsync().
Ainsi avec une API assez réduite (à peine 5 fonctions), vous allez pouvoir vous connecter sur Skydrive et y créer vos fichiers et vos répertoires.
A bientôt
Eric Vernié