[Windows 8] Générateur de politique de confidentialité

4. June 2013 21:37 by Renaud in Windows 8, Windows Azure  //  Tags: , , ,   //   Comments (1)

Vous le savez sans doute, sur Windows 8, l'utilisateur doit toujours garder le contrôle sur son système. Et pour cela, Microsoft n'a pas seulement fait en sorte que le système soit sécurisé, mais a également établi quelques règles pour nous les développeurs. Ces règles visent particulièrement à informer l'utilisateur de l'usage que nous pourrions faire de leurs données.

Ainsi, pour utiliser des fonctionnalités de Windows 8 qui touche au respect de la vie privée (GPS, accès aux librairies personnelles comme les documents, les photos, etc, ...), il est nécessaire de le déclarer explicitement. L'utilisateur verra alors - avant de télécharger l'application - que vous réclamez l'un ou l'autre droit.

En ce qui concerne l'accès à internet, les choses sont également très claires: si votre application fait usage d'internet, vous devez fournir à l'utilisateur une Politique de Confidentialité consultable en ligne!

Alors si vous êtes un peu fainéants ou que vous n'avez aucune idée de comment héberger une page web, voici un petit générateur que j'ai mis en ligne sur mon compte Windows Azure:

http://w8privacy.azurewebsites.net/

Rien de très complexe, mais c'est surtout pratique :) développé en deux temps, trois mouvements avec Foundation. L'intérêt étant que vous aurez une page personnalisée (et multilingue!) pour votre application!

Il vous suffit de suivre les étapes, et c'est parti, vous aurez une URL unique que vous pourrez utiliser dans la page "À propos" de votre application ET dans le formulaire de soumission de votre application sur le Windows Store!

 

Bonus : si cela ne vous suffit pas tout à fait, les sources sont dispos sur GitHub: W8Privacy

[ASP.NET MVC4] Comment implémenter la réinitialisation de mot de passe

26. May 2013 19:04 by Renaud in ASP.NET MVC  //  Tags: , , ,   //   Comments (1)

Le template "Internet Application" de ASP.NET MVC4 est hyper complet en ce qui concerne la gestion des comptes utilisateurs. De base, ils permet de créer une application web avec tout ce qu'il faut pour qu'un utilisateur puisse s'inscrire, se connecter, gérer son profil et modifier son mot de passe. Avec un minimum de configuration, on peut également permettre aux utilisateurs de choisir entre un compte local (nom d'utilisateur + mot de passe) et une identification au travers d'un fournisseur d'identité tel que Facebook, Twitter, Microsoft (Live), Google et Yahoo (ou n'importe quel autre service à condition d'écrire soi-même quelques lignes de code...).

Tout le code nécessaire au bon fonctionnement de ces fonctionnalité est intégré dans le template. Il n'y a donc pour ainsi dire rien à faire! :) Vous avez sans doute déjà jeté un oeil dans le contrôleur AccountController. C'est effectivement là que tout se passe.  

Une autre fonctionnalité disponible dans ASP.NET MVC4 est la récupération de compte. Par récupération de compte, j'entends ici le fait de pouvoir modifier son mot de passe lorsque l'on a perdu son mot de passe actuel, et que l'on ne peut donc plus se connecter.

Mais contrairement à ce qui a été cité ci-dessus, il n'y a pas d'action prévue pour cela dans le template.

La gestion des comptes avec WebSecurity

Il y a eu du changement depuis ASP.NET MVC3. Précédemment, tout ce qui concernait la gestion des compte se faisait à l'aide de la classe Membership. Mais si vous regardez le code de AccountController dans un projet MVC4, vous verrez qu'on utilise désormais deux autres classes : WebSecurity, et OAuthWebSecurity. Ces classes sont une nouvelle couche d'abstraction qui permettent de réaliser les actions courantes de gestion de compte utilisateur comme la création, la modification de mot de passe lorsque l'on est connecté, etc... 

Scénario de récupération

Avant de nous lancer dans l'implémentation de cette procédure, réfléchissons deux secondes à ce dont nous avons besoin...

  • Un moyen d'identifier l'utilisateur: son email ou son mot de passe

En principe l'utilisateur ayant perdu son mot de passe devrait se souvenir de sa propre adresse email. Cela permettra d'identifier le compte que l'on veut récupérer.

  • Un jeton de modification de mot de passe, avec une date d'expiration.

Lorsque l'utilisateur lancera la procédure de récupération, un jeton sera créé et sera valable pour une durée limitée. Sans ce jeton, pas de récupération possible.

  • Un moyen de contacter l'utilisateur pour lui envoyer son jeton.

Évidemment, il est hors de question de donner ce jeton à n'importe quelle personne le demandant. On l'enverra donc à l'adresse email de l'utilisateur qui a fait la requête. Ainsi, à moins qu'une autre personne se soit emparée du compte email, on peut être sûr que la requête émane bien du propriétaire du compte.

Comme je vous le disais, la classe WebSecurity implémente les tâches les plus courantes! :) Et ce mécanisme aussi!

L'implémentation

1/ Obtenir l'adresse email de l'utilisateur

On l'a vu, nous aurons besoin d'une adresse email! Par défaut, le UserProfile (la classe servant à représenter un utilisateur) ne possède pas cet attribut. Mais ce n'est pas un soucis: pour étoffer le profil utilisateur avec ASP.NET MVC4, il suffit d'ajouter des attributs à cette classe.

/Models/AccountModels.cs

[Table("UserProfile")]
public class UserProfile
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }

    public string Email { get; set; }
}

 On va également modifier légèrement la page d'inscription pour demander à l'utilisateur cette information supplémentaire:

/Models/AccountModels.cs

public class RegisterModel
{
    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}

/Views/Account/Register.cshtml

@model RecoverPasswordMVC4.Models.RegisterModel
@{
    ViewBag.Title = "Register";
}

<hgroup class="title">
    <h1>@ViewBag.Title.</h1>
    <h2>Create a new account.</h2>
</hgroup>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()

    <fieldset>
        <legend>Registration Form</legend>
        <ol>
            <li>
                @Html.LabelFor(m => m.UserName)
                @Html.TextBoxFor(m => m.UserName)
            </li>
            <li>
                @Html.LabelFor(m => m.Email)
                @Html.TextBoxFor(m => m.Email)
            </li>
            <li>
                @Html.LabelFor(m => m.Password)
                @Html.PasswordFor(m => m.Password)
            </li>
            <li>
                @Html.LabelFor(m => m.ConfirmPassword)
                @Html.PasswordFor(m => m.ConfirmPassword)
            </li>
        </ol>
        <input type="submit" value="Register" />
    </fieldset>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

À ce stade, si l'on exécute l'application et que l'on essaie de se loguer, on pourra voir le résultat suivant : 

Il reste encore à modifier l'action POST Register pour sauver l'Email. Une fois que le compte est créé à l'aide de WebSecurity, on va récupérer l'enregistrement UserProfile correspondant, et le mettre à jour.

/Controllers/AccountController.cs

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
    if (ModelState.IsValid)
    {
        // Attempt to register the user
        try
        {
            WebSecurity.CreateUserAndAccount(model.UserName, model.Password);

            using (UsersContext context = new UsersContext())
            {
                UserProfile user = context.UserProfiles.FirstOrDefault(u => u.UserName == model.UserName);
                user.Email = model.Email;
                context.SaveChanges();
            }

            WebSecurity.Login(model.UserName, model.Password);

            return RedirectToAction("Index", "Home");
        }
        catch (MembershipCreateUserException e)
        {
            ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
        }
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

2/ Demander à l'utilisateur ses informations de compte

On va créer une nouvelle action RecupAccount, et le formulaire correspondant.

/Controllers/AccountController.cs

[AllowAnonymous]
public ActionResult RecupAccount()
{
    return View(new RecupAccountModel());
}

L'attribut AllowAnonymous indique que les utilisateurs peuvent faire appel à cette action sans être connectés. Il est nécessaire ici de le déclarer explicitement car le AccountController est décoré de l'attribut [Authorized], ce qui fait que toutes ses actions nécessitent par défaut d'être identifié.

La classe RecupAccountModel possède deux propriétés. L'utilisateur devra nous fournir ses données s'il veut qu'on essaie de s'occuper de son problème! :)

/Models/RecupAccountModel.cs

public class RecupAccountModel
{
    [Required]
    public string UserName { get; set; }
    [Required]
    public string Email { get; set; }
}

/Views/Account/RecupAccount.cshtml

@model RecoverPasswordMVC4.Models.RecupAccountModel

@{
    ViewBag.Title = "Récupération de compte";
}

<h2>Mot de passe perdu?</h2>

@using (@Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()
    
    @Html.LabelFor(m => m.UserName)
    @Html.EditorFor(m => m.UserName)
    @Html.ValidationMessageFor(m => m.UserName)

    @Html.LabelFor(m => m.Email)
    @Html.EditorFor(m => m.Email)
    @Html.ValidationMessageFor(m => m.Email)

    <input type="submit" value="Aidez-moi!" />
}

Notre utilisateur malheureux va donc pouvoir nous envoyer ses infos, que nous allons évidemment vérifier lors de l'envoi du formulaire. 

3/ Envoyer le jeton de réinitialisation à l'utilisateur

On va donc vérifier les données, et si elles sont correctes, générer un jeton de réinitialisation de mot de passe grâce à la classe WebSecurity. Pour cela, on fait appel à la méthode GeneratePasswordResetToken qui prend en paramètre le nom d'utilisateur et le temps avant expiration (facultatif). Par défaut, le token expire après 1440 minutes (24 heures), mais comme je suis un peu vache j'ai décidé de ne laisser que 5 minutes à l'utilisateur pour faire la manip'! :)

/Controllers/AccountController.cs

[HttpPost]
[AllowAnonymous]
public ActionResult RecupAccount(RecupAccountModel model)
{
    // On vérifie que les deux champs sont remplis
    if (ModelState.IsValid)
    {
        using (UsersContext context = new UsersContext())
        {
            // Si on trouve un compte qui match avec les infos entrées par l'utilisateur...
            if (context.UserProfiles.Any(
                    u => u.UserName.Equals(model.UserName, StringComparison.OrdinalIgnoreCase) &&
                            u.Email.Equals(model.Email, StringComparison.OrdinalIgnoreCase)))
            {
                // On crée un token permettant de réinitialiser le mot de passe ...
                string token = WebSecurity.GeneratePasswordResetToken(model.UserName, 5);

                // ... et on l'envoit à l'utilisateur par email
                MailingService mailingService = new MailingService();
                mailingService.SendTokenByEmail(token, model.Email, model.UserName);

                return View("RecupAccountConfirmed");
            }
            else
            {
                ModelState.AddModelError("", "Le nom d'utilisateur ou l'email est incorrect.");
            }
        }
    }
    return View(model);
}

Ensuite on va envoyer ce token par email. En fait, on va envoyer à l'utilisateur un lien sur lequel il n'aura qu'à cliquer pour consommer ce token et réinitialiser son mot de passe:

var url = String.Format("{0}/account/resetpassword/?token={1}", SitewebUrl, token);

Si vous ne savez pas comment envoyer de mail en ASP.NET MVC, vous trouverez l'implémentation de la classe MailingService dans le projet d'exemple téléchargeable à la fin de l'article.

 

A ce stade, soit l'utilisateur nous a donné des informations correctes et il reçoit un email, soit les informations sont bidons et il revient sur le formulaire avec un message d'erreur.

4/ Vérifier le jeton

Lorsque l'utilisateur aura reçu son email, il naviguera vers un lien du genre: http://monsupersite.be/account/resetpassword/?token=Ddsn32jd3jLJsnd3

On va donc créer cette action, chargée de vérifier le jeton de l'utilisateur. Encore une fois nous allons faire appel à la classe WebSecurity. La méthode GetUserIdFromPasswordResetToken permet de récupérer l'Id de l'utilisateur lié au jeton. Si ce dernier a expiré ou ne correspond à aucun jeton existant, l'Id retourné sera -1.

/Controllers/AccountController.cs

[AllowAnonymous]
public ActionResult ResetPassword(string token)
{
    var userId = WebSecurity.GetUserIdFromPasswordResetToken(token);

    using (UsersContext context = new UsersContext())
    {
        UserProfile user = context.UserProfiles.Find(userId);
        if (user == null)
            return View("Error");

        var model = new ResetPasswordModel()
            {
                Token = token,
                UserName = user.UserName
            };

        return View(model);
    }
}

Si l'Id ne correspond à rien, on peut rediriger l'utilisateur vers une page d'erreur, ou plutôt lui proposer de refaire une demande de jeton. Le sien ayant peut-être tout simplement expiré.

5/ Modifier le mot de passe

Quoiqu'il en soit, si tout se passe bien, l'utilisateur sera amené sur la page de réinitialisation de son mot de passe. La classe ResetPasswordModel est définie comme ceci. On va avoir besoin de toutes ces valeurs par la suite. On connait déjà le Token et le UserName, et l'utilisateur va nous donner le nouveau mot de passe.

/Models/Account/ResetPasswordModel.cs

public class ResetPasswordModel
{
    [Required]
    public string Token { get; set; }
    [Required]
    public string UserName { get; set; }
    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Nouveau mot de passe")]
    public string NewPassword { get; set; }
    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Confirmation mot de passe")]
    public string ConfirmNewPassword { get; set; }
}

 /Views/Account/ResetPassword.cshtml

 

@model RecoverPasswordMVC4.Models.ResetPasswordModel

@{
    ViewBag.Title = "Réinitialisation du mot de passe";
}

<h2>Réinitialisation du mot de passe</h2>

@using (@Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()
    
    @Html.HiddenFor(m => m.Token)
    @Html.HiddenFor(m => m.UserName)
    
    @Html.LabelFor(m => m.NewPassword)
    @Html.PasswordFor(m => m.NewPassword)
    @Html.ValidationMessageFor(m => m.NewPassword)

    @Html.LabelFor(m => m.ConfirmNewPassword)
    @Html.PasswordFor(m => m.ConfirmNewPassword)
    @Html.ValidationMessageFor(m => m.ConfirmNewPassword)

    <input type="submit" value="Changer mot de passe" />
}

Dans cette vue, les champs Token et UserName seront invisibles à l'utilisateur, mais ils seront envoyés avec les autres informations du formulaire.

Et pour finir, on va vérifier que l'utilisateur a bien entré deux fois le même mot de passe, et on va faire une dernière fois appel à la classe WebSecurity. La méthode ResetPassword va mettre à jour le mot de passe en consommant le jeton, et la méthode Login va connecter l'utilisateur à l'aide de son nom et de son nouveau mot de passe.

/Controllers/AccountController.cs

[HttpPost]
[AllowAnonymous]
public ActionResult ResetPassword(ResetPasswordModel model)
{
    if (ModelState.IsValid)
    {
        if (!model.NewPassword.Equals(model.ConfirmNewPassword))
        {
            ModelState.AddModelError("", "Les mots de passe ne correspondent pas.");
            return View(model);
        }
        WebSecurity.ResetPassword(model.Token, model.NewPassword);
        WebSecurity.Login(model.UserName, model.NewPassword);
        return RedirectToAction("Index", "Home");
    }
    return View(model);
}

 

Et voilà, l'utilisateur pourra à nouveau se connecter. Il ne reste plus qu'à ajouter un petit lien "Mot de passe oublié?" sur la page de login :

@Html.ActionLink("Mot de passe oublié ?", "RecupAccount", "Account")

 

Pour résumer, les différentes étapes de la procédure sont :

1/ Avoir un moyen de contacter l'utilisateur (email).

2/ Mettre en place une page "Mot de passe oublié?"

3/ Générer un jeton de réinitialisation et l'envoyer à l'utilisateur à l'aide de WebSecurity.

4/ Vérifier que le jeton est correct avec WebSecurity et montrer une page demandant un nouveau mot de passe.

5/ Réinitialiser le mot de passe avec WebSecurity en consommant le jeton

 

Ressources

Vous pouvez télécharger la solution d'exemple ici: 

RecoverPasswordMVC4.zip

La Kinect nouvelle génération bientôt disponible sur PC

22. May 2013 06:54 by Renaud in Kinect  //  Tags: , ,   //   Comments (0)

Microsoft vient tout juste d'annoncer sa nouvelle console, la Xbox One (pré-commandable sur Amazon). En gros: un nouveau look, plus de puissance, et une box all-in-one. En effet, elle ne viendra pas seule puisqu'elle sera accompagnée de la Kinect nouvelle génération!

La super bonne nouvelle, même si cela semblait évident, c'est la confirmation que cette nouvelle Kinect arrivera sur PC prochainement. C'est ce que rapporte le site Shacknews:

According to Kinect program manager Scott Evans, Microsoft plans on bringing the new Kinect to PC. "We will bring this to PC," he told us. "We will have more information soon."

On ne sait donc pas encore quand, mais on ne peut qu'être impatient aux vues des nouvelles possibilités!

La nouvelle Kinect est de faite plus précise. Elle permet de détecter et suivre les mouvements du corps quasiment sans aucune latence. Elle peut suivre entièrement jusqu'à 6 personnes simultanément, là où la version précédente se limitait à 2 personnes. La Kinect pouvait déjà suivre les mouvements du corps, mais désormais elle peut le faire avec plus de détails. On peut ainsi suivre plus d'articulations, connaître l'orientation des épaules et la position même des pouces des mains. La Kinect regardera également votre visage, pouvant ainsi dire si vous souriez, si vous regardez ou non vers l'écran, si vous portez des lunettes, etc... Et plus impressionnant encore, la Kinect peut monitorer votre rythme cardiaque!

Pour voir le tout en vidéo, voici le test de The Verge: Kinect Xbox One / Hands on.

Quand on voit déjà ce que permettait la dernière version du SDK, avec le tracking des mains, la reconnaissance faciale, la modélisation 3D... Cela ne fait nul doute que beaucoup de développeurs à travers le monde doivent être impatients de voir arriver la version PC et le nouveau SDK qui l'accompagnera! Smile

[Windows 8] Développez en HTML 5 pour Windows 8

29. April 2013 14:53 by Renaud in Windows 8  //  Tags: , , ,   //   Comments (0)

* Petite pub perso Tongue Out *


Ces derniers moi j'ai écrit un bouquin traitant de Windows 8 avec Loïc Bar et Simon Boigelot. Ce livre parle du développement d'applications pour le store Windows 8 à base de HTML 5 et de JavaScript !

Ce livre s'adresse aux débutants, aux personnes n'ayant pas nécessairement d'expérience avec les technologies du monde Microsoft. Vous n'avez jamais fait de .NET? Mais vous avez déjà bidouillé avec du HTML?

Si vous voulez passer à la vitesse supérieure, tirer profit du nouvel OS de Microsoft et pourquoi pas commencer à gagner un peu d'argent en vendant vos applications, ce livre est pour vous ! :)

Développez en HTML 5 pour Windows 8

[Windows 8] Créer un timer rond en XAML

15. April 2013 21:27 by Renaud in Expression Blend, Windows 8, XAML  //  Tags: , , , ,   //   Comments (0)

Pour le développement du jeu WordDefy pour Windows 8, Matthieu (@MatthieuVdh) et moi avons demandé l'aide d'une amie graphiste. Et comme elle nous a rapidement pondu un super truc, la moindre des choses c'était de tenter de le reproduire à l'identique ! Il y a plusieurs bons côtés à cela : premièrement on a une app avec un look plutôt sympa, et deuxièmement j'ai pu jouer avec Blend et m'amuser avec le XAML, ce qui fait que j'ai appris pas mal de choses!

Une des parties consistait à reproduire un Timer en forme de cercle. Pour que vous y voyez plus clair, voici le compteur original tel que designé et le résultat final (qui est assez ressemblant :)) en XAML :

Design original
Design original

Résultat en XAML
XAML

Conception d'un RoundedTimer

Il existe plein d'exemples de timer sur le web, mais aucun fonctionnant sous WinRT. Et évidemment, le XAML sur Windows 8 a quelques particularités qui font que l'exemple ne sont pas toujours utilisables. J'en ai donc recréé un avec Blend !

Générer un Path

La première étape consiste à créer le cercle du compteur. Ce cercle doit être transparent au milieu. Pour faire cela, on va utiliser deux Ellipses et les combiner (ou plus précisément les soustraire). Placez donc deux Ellipses de manière à ce qu'elles soient centrées sur le même point, et avec l'une d'elle légèrement plus petite que l'autre.

Le code jusqu'à présent:

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    	<Ellipse Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="200" Margin="160,240,0,0" Stroke="Black" VerticalAlignment="Top" Width="200"/>
    	<Ellipse Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="140" Margin="190,270,0,0" Stroke="Black" VerticalAlignment="Top" Width="140"/>
    </Grid>

Pour obtenir le résultat voulu, on peut donc soustraire la deuxième Ellipse à la première ou exclure les zones de chevauchement (lisez aussi Combiner des formes et des tracés (Blend pour Visual Studio)). Faites un clique droit sur l'arbre visuel et les Ellipses sélectionnées et choisissez l'opération qui vous convient dans le menu Combiner

Le résultat de cette opération est un Path généré en remplacement des deux Ellipses précédemment créées. Le résultat devrait ressembler à ceci:

Et le code correspondant : 

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    	<Path Data="M100,30.5 C61.6162,30.5 30.5,61.6162 30.5,100 C30.5,138.384 61.6162,169.5 100,169.5 C138.384,169.5 169.5,138.384 169.5,100 C169.5,61.6162 138.384,30.5 100,30.5 z M100,0.5 C154.952,0.5 199.5,45.0477 199.5,100 C199.5,154.952 154.952,199.5 100,199.5 C45.0477,199.5 0.5,154.952 0.5,100 C0.5,45.0477 45.0477,0.5 100,0.5 z" Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="200" Margin="160,240,0,0" Stretch="Fill" Stroke="Black" UseLayoutRounding="False" VerticalAlignment="Top" Width="200"/>
    </Grid>

Ce cercle est la base de notre RoundedTimer... Passons à l'étape suivante: le clipping ! :)

Clipping Path

Le principe du clipping path est d'utiliser un élément pour délimiter la zone visible d'un autre élément. Malheureusement dans les apps Windows Store on ne peut pas utiliser un Path pour "masquer" un autre élément. Par contre on peut utiliser des Ellipse et des Rectangle pour délimiter une zone. 

Ajoutons par exemple un Rectangle dans sur un coin de notre cercle : 

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <Rectangle Margin="160,240,1106,428" Width="100" Height="100"/>
    <Path Data="M100,30.5 C61.6162,30.5 30.5,61.6162 30.5,100 C30.5,138.384 61.6162,169.5 100,169.5 C138.384,169.5 169.5,138.384 169.5,100 C169.5,61.6162 138.384,30.5 100,30.5 z M100,0.5 C154.952,0.5 199.5,45.0477 199.5,100 C199.5,154.952 154.952,199.5 100,199.5 C45.0477,199.5 0.5,154.952 0.5,100 C0.5,45.0477 45.0477,0.5 100,0.5 z" Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="200" Margin="160,240,0,0" Stretch="Fill" Stroke="Black" UseLayoutRounding="False" VerticalAlignment="Top" Width="200"/>
</Grid>

 

Le résultat obtenu est le suivant : 

On se retrouve avec un quart de cercle, ce qui va en fait représenter un quart de notre RoundedTimer ! Ce qu'il reste à faire est d'animer ce quart de Timer pour représenter le temps qui s'écoule.

Animer le Timer

Pour cela on va utiliser une Transformation sur l'élément RectangleGeometry. A vrai dire il y a sans doute plusieurs façon d'arriver au même résultat ! Pour ma part j'y suis arrivé en utilisant un SkewTransform.

Si l'on reprend le quart de cercle précédent, on peut l'animer en utilisant la transformation correcte : 

<Path Data="M100,30.5 C61.6162,30.5 30.5,61.6162 30.5,100 C30.5,138.384 61.6162,169.5 100,169.5 C138.384,169.5 169.5,138.384 169.5,100 C169.5,61.6162 138.384,30.5 100,30.5 z M100,0.5 C154.952,0.5 199.5,45.0477 199.5,100 C199.5,154.952 154.952,199.5 100,199.5 C45.0477,199.5 0.5,154.952 0.5,100 C0.5,45.0477 45.0477,0.5 100,0.5 z" Fill="White" HorizontalAlignment="Left" Height="200" Margin="160,240,0,0" Stretch="Fill" Stroke="Black" UseLayoutRounding="False" VerticalAlignment="Top" Width="200">
	<Path.Clip>
		<RectangleGeometry Rect="0,0,100,100">
			<RectangleGeometry.Transform>
                <!-- AngleY : De 0 à 90 -->
                <SkewTransform CenterX="100" CenterY="100" AngleY="0"/>
            </RectangleGeometry.Transform>
		</RectangleGeometry>
	</Path.Clip>
</Path>

En modifiant la valeur de la propriété AngleY, on peut animer joliment le timer ! Ainsi, avec un angle de 40°, on retrouve la forme suivante :

Il ne reste donc plus qu'à créer trois autres quarts du timer, et à les animer en changeant la valeur d'un des angles toutes les secondes grâce à un DispatcherTimer. L'important étant de voir comment appliquer la SkewTransformation, en jouant sur les propriétés Center et Angle !

Téléchargement / Sources

Vous pouvez télécharger le résultat final sous la forme d'une contrôle sur GitHub ! À vous de le customiser ! :)

Pour l'intégrer dans votre app, rien de plus simple :

<Page
    x:Class="TestApp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:roundedTimer="using:RoundedTimer"
    mc:Ignorable="d">
    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <roundedTimer:RoundedTimer x:Name="MyTimer" Width="200" Height="200" Duration="00:01:00" />
    </Grid>
</Page>

On instancie le timer dans le XAML, et on démarre le décompte avec un appel à la méthode Start() dans le code-behind :

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            MyTimer.Start();
        }

 

Spotlight : La coupe de Belgique de robotique 2013 à l'UMONS

13. April 2013 16:36 by Renaud in Robotic  //  Tags: , , ,   //   Comments (0)

Ce weekend, j'ai eu la chance d'être invité par les organisateurs de la Coupe de Belgique de Robotique 2013 pour participer à une mini-conférence ! C'était une première pour moi... j'avoue n'avoir jamais participé à ce genre d'événement auparavant. Mais je dois dire que l'ambiance y est plutôt sympathique. Globalement, on y retrouve la même faune que lors d'un hackathon, mais avec des super-pouvoirs un peu différents puisque les gens là-bas ne font pas qu'écrire du code mais manient également le tournevis ou le fer à souder!

Bref, ça se passait donc ce weekend à l'UMONS, (établissement où j'ai fait un arrêt durant mon cursus scolaire), et j'ai pu y parler de Nao (allez voir le Developer's program) et de la Kinect pour PC

Je me suis donc retrouvé de l'autre côté de l'auditoire dans lequel j'ai suivi de nombreux cours d'algèbre et d'analyse ! :)

L'amphi avant l'arrivée des gens!

Crédits : Tomas Gosselin

Donc en deux mots, après une légère introduction à la Kinect suivie d'une présentation de Nao, j'ai montré comment on peut fusionner les deux mondes pour faire un truc super cool : contrôler Nao en faisant le singe devant la Kinect !

Crédits : Tomas Gosselin

L'exemple en soit est un peu simpliste. Je commence par calibrer l'application pour définir une zone dans laquelle je peux commander Nao à distance. Ensuite j'active le contrôle, et Nao commence à reproduire les mouvements de mes bras. Grâce au dernier SDK Kinect pour Windows et à la nouvelle Interaction API, je peux également contrôler l'ouverture des mains de Nao très facilement! Et pour finir, je peux me déplacer en dehors de ma zone de contrôle pour que Nao se déplace également pas à pas.

Les slides sont dispos sur Slideshare :  

 
Quel est l'intérêt de cette démo ? Montrer que l'association des deux technologies pourraient être très intéressante. On pourrait imaginer envoyer des robots dans des zones qui ne soient pas accessibles à des humains, et contrôler ces robots à distance de manière simple et précise. Évidemment, ce n'est pas encore aujourd'hui que Nao remplacera des pompiers pour sauver une victime prisonnière d'un bâtiment en flammes, mais ce n'est peut-être pas aussi improbable que ça en a l'air!

A suivre

Vous connaissez peut-être déjà les Developer's First Monday, ces afterworks organisés tous les premiers lundis du mois. Sachez qu'une des prochaines sessions sera sur le thème de la robotique. Si cela vous intéresse, faites-le savoir sur notre uservoice : https://micbelgique.uservoice.com/forums/191395-general/suggestions/3688770-session-gadgeteer

Developer's First Monday 01x03

10. April 2013 14:31 by Renaud in Agile, Events  //  Tags: , , , , ,   //   Comments (0)

Le 08 avril dernier, nous avons accueilli la deuxième édition des Developer's First Monday (en photo). Pour cet évènement, nous avions souhaité (enfin, via notre Uservoice, vous aviez souhaité) parler un peu d'Infrastructure et pas toujours de Dev ! Nous nous sommes donc retrouvés à une petite vingtaine pour écouter Gokan Ozcifci nous parler de Sharepoint 2013, de ses nouveautés et des best-practices. Nous avons également eu droit à l'intervention d'Arnaud Jund, fondateur de la communauté myTIC Pour ce troisième épisode,  c'est encore vous qui décidez ! Et nous aurons le plaisir de recevoir Pierre-Emmanuel (MEET member) et Norman Deschauwer de DotNetHub)

Pour ceux qui n'ont pas suivi, de quoi s’agit-il ?

Si vous avez manqué la première et la deuxième soirée et que vous ne savez toujours ce qu'est le Developer's First Monday, voici un rappel : L’idée est de créer un rendez-vous récurrent pour les développeurs et autres professionnels de l’IT! Ce sera l’occasion de faire connaissance, mais aussi de partager notre noble savoir lors de courtes présentations. La soirée pourra évidemment se prolonger autour d’un verre pour les plus motivés ! Pour rendre la soirée encore plus intéressante, vous êtes invités à dire de quoi vous aimeriez parler ! Quels sont les sujets qui vous passionnent ? Dites-le nous, le UserVoice est là pour ça ! :)

Détails

Cette soirée se tiendra le 06 mai au MIC de Mons !

Lors de formations Agile, on se pose souvent la question des outils : quels outils pouvons-nous utiliser pour faire de l'agile ? Et si les agilistes promeuvent souvent des "outils" manuels (post-it, tableaux blanc, ...), il est parfois nécessaire de les accompagner d'outils informatiques. Depuis quelques années, Microsoft propose son outil TFS (Team Foundation Server) comme étant sa solution ALM (Application Lifecycle Management). Si les versions précédentes proposaient déjà des modules "agiles", ils proposent avec leur version TFS 2012, une solution complète pour la gestion de projet Agile, et intégrant les chefs de projet, les product owners, les développeurs, les testeurs, ... Cette session a pour but de démontrer les capacités de cet outil, et ce qu'il apporte dans le monde agile. Nous verrons entre autres :

  • l'analyse et le prototyping / storyboarding / sketching d'application
  • la définition et la priorisation du backlog
  • la planification des itérations et leur suivi (kanban, burndown chart)
  • le développement, et la traçabilité des exigences
  • le testing (TDD développement piloté par les tests, tests unitaires, tests d'acceptance)
  • l'intégration continue
  • le feedback client Toutes les démo se feront via les plate-formes Visual Studio 2012 et Team Foundation Server 2012.

Les exemple de code seront en C#.

Speaker

Pierre-Emmanuel Dautreppe, MEET Member et membre fondateur de DotNetHub !

Pierre-Emmanuel est un spécialiste .NET depuis 2002 et travaille actuellement comme expert technique et architecte agile dans des projets .NET. Il est passé dans le monde de l’agilité en 2005, et depuis ce jour, il partage ses expérience, recettes et déconevnues. Il essaye de partager les valeurs et la culture agile. Il donne des conférences et des formations en .NET (C#, testing, intégration continue, application lifecycle management, …) et en agile. En 2009, il a fondé le user group DotNetHub (www.dotnethub.be) pour promouvoir .NET et les méthodologies Agile au Bénélux et en France. Chaque année, il organisé la Journée Agile (Agile Tour francophone) en Belgique (www.journeeagile.be).

Inscriptions

En suivant ce lien : http://events.mic-belgique.be/event/developer-s-first-monday-3.

Ou directement sur cette page :

DevFM 01x02 : Sharepoint 2013

26. March 2013 15:10 by Renaud in Events, Sharepoint  //  Tags: , ,   //   Comments (0)

Pour le deuxième épisode des Developer's First Monday, deux particularités : 

- On fera une session IT Pro sur les nouveautés de Sharepoint 2013

- L'afterwork est exceptionnellement prévu pour le 2ème lundi du mois (le premier étant le lundi de pâques :))

Rendez-vous donc le 08/04 au MIC Belgique à partir de 18h pour une session donnée par Gokan Ozcifci, très actif dans la communauté Sharepoint et récemment nommé Microsoft Community Contributor !

Pour plus d'infos ou vous inscrire, rendez-vous là : http://events.mic-belgique.be/event/developer-s-first-monday-2-meets-the-it-crowd-sharepoint-2013

Et si vous n'avez pas envie de lire et que vous voulez juste venir, vous pouvez-le faire directement ici :

[MOOC] Windows 8 - 2/ Cycle de vie des apps Windows Store

25. March 2013 13:14 by Renaud in MOOC, Windows 8  //  Tags: , , , ,   //   Comments (0)

 

Dans cette deuxième vidéo (la première étant ici : [MOOC] Windows 8 - 1/ Les contrats en C#) , on aborde le cycle de vie des applications Windows Store. Qu'est-ce qui change par rapport aux applications classiques? Pourquoi ces modifications? Et comment gérer tout ça? C'est ce que je vous explique ici !

La gestion du cycle de vie des applications Windows Store

Les applications Windows Store passent par différents états au cours de leur vie. Elles peuvent successivement être actives, suspendues, ou terminées.

Au sommaire :

- Qu'est-ce qui a changé ?

- Gérer le passage entre les différents états

- Sauvegarder la session des utilisateurs avec le SuspensionManager

- Le SplashScreen étendu

- Les BackgroundTask

- Mettre à jour les LiveTile depuis le background

 

  

Après avoir suivi cette vidéo :

Vous saurez comment sauvegarder une session utilisateur, effectuer des tâches en arrière plan et mettre à jour une vignette dynamique depuis votre application !

La suite

Dans la prochaine vidéo, on verra quelques Tips & Tricks sur le XAML, Visual Studio et Blend

Relive TechDays Belgium 2013 online: videos and slides available!

22. March 2013 10:03 by Renaud in Events, Windows 8, Windows Phone  //  Tags: , ,   //   Comments (0)

TechDays

2 weeks ago we closed the Microsoft TechDays 2013 in Antwerp. Close to 2900 IT Professionals, Developers and Students enjoyed 90 sessions with top content led by a broad selection of international and local top speakers. A special THANK YOU goes to our partners, our MVP’s and MEET (Microsoft Extended Experts Team) members and of course, all our enthusiastic attendees! What’s next? The session videos and slides are now available on www.techdays.be! (Re)live the sessions and take the next steps to truly master the technologies. Warm up with a selection from our Technical Evanglists Arlindo Alves and Katrien De Graeve:

Arlindo’s Top Selection Katrien’s Top Selection
Hackers (Not) Halted with Paula Januszkiewicz Become a Windows 8 and Windows Phone App Developer at TechDays with Ben Riga
Moving from Device Centric to a User Centric Management with Corey Hynes Bigger, Faster, Stronger: Optimizing ASP.NET 4 and 4.5 Applications with Mads Kristensen
Windows 8 Client: Part 1 "The OS internals for IT-Pro's" and Part 2 "The Application internals for IT-Pro's" with Tom Decaluwé Behind the scenes of (as many) C# language features with Bart De Smet

Enjoy! The TechDays Team Questions? Connect with us on Twitter, Facebook or simply via e-mail.

TextBox

About the author

I'm a developer, blog writer, and author, mainly focused on Microsoft technologies (but not only Smile). I'm Microsoft MVP Client Development since July 2013.

Microsoft Certified Professional

I'm currently working as an IT Evangelist with an awesome team at the Microsoft Innovation Center Belgique, where I spend time and energy helping people to develop their projects. I also give training to enthusiastic developers and organize afterworks with the help of the Belgian community.

MIC Belgique

Take a look at my first book (french only): Développez en HTML 5 pour Windows 8

Développez en HTML5 pour Windows 8

Membre de l'association Fier d'être développeur

TextBox

Month List