Le contrôle WebBrowser pour choisir des fichiers à télécharger sur WP7

Dans le monde Desktop, on trouve pléthore d’applications capables d’ouvrir des fichiers externes, que ce soient des fichiers textes, images, vidéo ou tous autres formats, par le biais d’une boite de dialogues se référant au système de fichier.

Dans nos applications Windows Phone nous ne disposons pas, pour des raisons de sécurité, d’un accès à ces fichiers (sauf les fichiers images avec le fameux PhotoChooserTask).
L’intégration de fichiers externes à l’applications doit donc initialement passer par Internet.
Il existe plusieurs types d’intégration possible par le Web qui vont de la plus simple (une uri du fichier à downloader dans une textbox) à la plus complexe (utiliser le SDK WindowsLive pour intégrer SkyDrive).

Nous allons voir ensemble une autre possibilité, très simple à mettre en place et permettant une grande liberté à l’utilisateur.

Quand le web nous sert de boite de dialogue

L’idée est de se servir d’un control WebBrowser comme d’un système de fichier.
Lorsque l’on est en train de naviguer vers un fichier dont l’extension nous convient, on arrête la naviguation pour le telecharger par nos propres moyens et ainsi pouvoir le récupérer dans notre application.

Un POC !

Afin de vérifier que notre concept fonctionne correctement ajoutons un control WebBrowser dans notre page.

<phone:WebBrowser x:Name="WebBrowser" Source="http://www.google.fr/m?site=images" />

On s’abonne ensuite à l’évènement de début de naviguation :

this.WebBrowser.Navigating += new EventHandler<NavigatingEventArgs>(WebBroser_Navigating);

On peut alors vérifier que l’extension de l’url en cours est bien de l’extension que nous recherchons (ici une image .jpg). Si c’est le cas on annule la navigation et on lance un WebClient contenant l’url en cours !

if (e.Uri.LocalPath.EndsWith(".jpg", StringComparison.InvariantCultureIgnoreCase) == true)
{
    // on annule la navigation
    e.Cancel = true;    

    // on commence le telechargement
    WebClient client = new WebClient();

    client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);

    client.OpenReadAsync(e.Uri);
}

Une fois téléchargé le fichier (qui est ici une image) sera placé dans un BitmapImage afin d’être affiché dans une ListBox d’Image.

void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
    if (e.Error == null && e.Cancelled == false)
    {
        // on crée l'image
        BitmapImage image = new BitmapImage();

        image.SetSource(e.Result);

        // On ajoute l'image dans une collection bindée sur une ListBox
        this.imageSource.Add(image);
    }
}

L’exemple

Afin de vous donner un avant de gout de ce que cela peut donner, voici une petit vidéo explicative.
Elle présente un WebBrowser pointant vers le site google image et capable de recupérer les images téléchargeables coté Silverlight.

Conclusion

Cette méthode est intéressante dans le cas ou les extensions de fichiers sont peu courantes sur le Web. Par exemple pour des images (.jpg, .png) je me suis aperçu que la recherche de google image telechargeais plusieurs fois les même images. Il a fallut donc rajouté un filtre pour vérifier que l’url n’avait pas déjà été téléchargé. Pour des fichiers de type moins courant cela ne devrait en revanche pas poser de problème.

Le projet

Vous pouvez télécharger ici le projet complet de l’application.

Le projet : WebExplorer.rar

D’autre méthodes ?

Et vous ? Avez-vous vos propres façon d’intégrer des fichiers externes ?

Posted in Silverlight WP7 by Samuel Blanchard. No Comments

Un TextBlock sélectionnable pour WP

Après quelques semaines très mouvementées dues à la sortie de BlueTomato (anciennement Sonic’s Jewels) et des sessions TechDays, il est temps de publier un petit article 100% code :)

TextBlock mon ami

Dans nos applications, on se sert habituellement de TextBlock pour rendre du texte.
Celui-ci est très puissant mais malheureusement il lui manque une fonctionnalité parfois bien pratique : Le copier-coller !
Seule les TextBoxs bénéficient de cette fonctionnalité dans Silverlight.
Comment faire alors pour que l’on puisse obtenir un texte sélectionnable et permettre enfin à nos adresses mail, telephone ou toutes autres informations d’être copiées vers un mail, SMS ou d’autres applications sans forcément être modificable.

En utilisant un TextBox bien sûr !

Le TextBox à notre rescousse

Commençons par lancer Blend afin de récupérer son style et plus particulièrement son template.

<Style x:Key="TextBoxStyle1" TargetType="TextBox">
	<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilyNormal}"/>
	<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>
	<Setter Property="Background" Value="{StaticResource PhoneTextBoxBrush}"/>
	<Setter Property="Foreground" Value="{StaticResource PhoneTextBoxForegroundBrush}"/>
	<Setter Property="BorderBrush" Value="{StaticResource PhoneTextBoxBrush}"/>
	<Setter Property="SelectionBackground" Value="{StaticResource PhoneAccentBrush}"/>
	<Setter Property="SelectionForeground" Value="{StaticResource PhoneTextBoxSelectionForegroundBrush}"/>
	<Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}"/>
	<Setter Property="Padding" Value="2"/>
	<Setter Property="Template">
		<Setter.Value>
			<ControlTemplate TargetType="TextBox">
				<Grid Background="Transparent">
					<VisualStateManager.VisualStateGroups>
					     <VisualStateGroup x:Name="FocusStates">
					         <VisualState x:Name="Focused">
							<Storyboard>
								<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="EnabledBorder">
									<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxEditBackgroundBrush}"/>
								</ObjectAnimationUsingKeyFrames>
								<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="EnabledBorder">
									<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxEditBorderBrush}"/>
								</ObjectAnimationUsingKeyFrames>
							</Storyboard>
						</VisualState>
					</VisualStateGroup>

						<!-- Autres VisualStates -->
					</VisualStateManager.VisualStateGroups>
					<Border x:Name="EnabledBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="{StaticResource PhoneTouchTargetOverhang}">
							<ContentControl Visibility="Collapsed" x:Name="ContentElement" BorderThickness="0" HorizontalContentAlignment="Stretch" Margin="{StaticResource PhoneTextBoxInnerMargin}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="Stretch"/>
					</Border>
						<!-- Fin du template -->
				</Grid>
			</ControlTemplate>
		</Setter.Value>
	</Setter>
</Style>

Afin de pouvoir rendre semblable notre TextBox à un TextBlock, nous allons modifier quelques une des propriétés de son Style.
Nous passerons tout d’abord le background du control à Transparent par défaut puis son Foreground de la couleur de base des TextBlocks:

          <Setter Property="FontSize" Value="{StaticResource PhoneFontSizeNormal}"/>
	<Setter Property="Background" Value="Transparent"/>
	<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>

Puis on retire l’ensemble du VisualState Focus afin que ni le fond ni les bords ne soit affecté lorsque le control acquière le focus :

<VisualState x:Name="Focused"/>

Pour finir on retire toutes les informations de bord ou de Margin non indispensable à notre nouveau contrôle :

<Border x:Name="EnabledBorder" Background="{TemplateBinding Background}">
      <ContentControl x:Name="ContentElement" BorderThickness="0" HorizontalContentAlignment="Stretch" Padding="{TemplateBinding Padding}" VerticalContentAlignment="Stretch"/>
</Border>

Saisie au clavier

On a maintenant un TextBox qui ressemble à un TextBlock mais qui réagit encore au clavier.
Notre objectif n’est pas de ne plus afficher le clavier puisque c’est celui-ci qui nous permet d’atteindre l’icône copier, mais de le rendre inactif.
Il suffit pour se faire de s’abonner à l’évenement TextChanged et d’annuler toute saisie.

        void textboxSelector_TextChanged(object sender, TextChangedEventArgs e)
        {
            // this.Text est le text initiale de la TextBox
            this.textboxSelector.Text = this.Text;
            this.SelectAll();
        }

TextChanged empêche à la fois la saisie d’une touche et le « Coller » d’éléments mais afin d’être plus réactif on peut ajouter l’évenement KeyDown en lui demandant de ne pas transmettre la touche actuellement frappée.

private void TextBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
	// on annule toutes touches
	e.Handled = true;
}

On peut noter que l’utilisation de e.Handled n’empêche pas pour autant la possibilité de coller du texte !

Et pourquoi pas un ReadOnly ?

Dans mon projet, je voulais pouvoir utiliser la sélection à l’aide éventuellement d’un scroll ce que ne permet pas le IsReadOnly. Rudy a développer un control basé sur ce principe. Je vous encourage à aller voir sur son blog une implémentation possible : http://www.rudyhuyn.com/blog/​2012/02/15/​un-textblock-selectionnable-pou​r-wp-alternative/

Sélection automatique

Afin d’être plus efficace, le controle pourrait se sélectionner automatiquement lorsqu’il récupère le focus.

private void TextBox_GotFocus(object sender, System.Windows.RoutedEventArgs e)
{
   TextBox t = sender as TextBox;
   t.SelectAll();
}

Et pourquoi pas utiliser le Clipboard ?

Apparut dans Mango, le clipboard permet la mise en clipboard du texte de son choix. En revanche la sélection serait moins fine sur un grand texte (à moins de gerer soi-même la sélection du texte) et comme le clavier n’apparait pas, il faudrait rajouter également un petit control permettant la copie.
Cela reste une alternative très intéressante néanmoins (merci à Rudy pour m’avoir rafraichit la mémoire à ce sujet).

http://msdn.microsoft.com/en-us/library/system.windows.clipboard(v=vs.96).aspx

Transformation en control

Pour que notre contrôle soit facilement portable sur différentes applications on va créer un control que l’on nommera TextSelector.
Premièrement un fichier Generic.xaml, qu’il suffira de deposer dans un dossier Theme de notre application si il n’existe pas, permettra de stocker le style du control.
Puis un fichier TextSelector.cs qui contiendra tout le coté programmatique et pourra être positionner n’importe ou à condition qu’il reste dans le même projet que Generic.xaml.

Le control en lui même sera appelé de la manière suivante à partit du namespace xmlns:my= »clr-namespace:SamSoft.Controls » :

<my:TextSelector Text="Ceci est un TextSelector !" AutoSelectAll="True"/>

Les deux fichiers peuvent être téléchargés ici : TextSelector.cs, Generic.xaml

Le résultat !

Une petite vidéo pour constater le résultat :





WPF + Kinect + Office 365 = OBox365 !

La session sur Kinect & Office 365 à laquelle j’ai participé avec mes co-speakers Julien LO PRESTI et Fabrice BARBIN vient de se terminer.

T’as fait quoi ?

Dans cette session je me suis plus particulièrement occupé de l’architecture générale de l’application et de l’implémentation du Framework et des Apps Documents Entreprise et News. Julien a géré toute la partie Lync et Authentification et accès au liste O365 ainsi que l’App Contact tandis que Fabrice c’est occupé de la gestion de Sharepoint et coordonné l’ensemble de la session.
Une équipe equilibrée et motivée pour une démo finale qui, j’éspère, n’a pas laissée le public insensible.

Bilan très positif puisqu’il a fallu refuser du monde :)

On peut voir ?

Quelques screenshots et video pour vous faire une idée :






Posted in Silverlight by Samuel Blanchard. No Comments

Sonic’s Jewels

Un nouvel emulateur devrait sortir très prochainement sur Windows Phone. Il s’agit de Sonic’s Jewels un emulateur Sega Master System et GameGear basé sur CogWheel que je viens de porter. Et oui on ne peut pas toujours créer son propre emulateur ^^
Cogwheel est réputé pour sa fiabilité bien que quelques jeux ne fontionnent pas (en général ceux réputé pour leur taille comme AfterBurner par exemple).

Le marketplace accessible !

Cette version sera poussée sur le marketplace dès que les derniers éléments seront en place (d’ici quelques jours).

Au contraire de Wario’Jewels, Sonic’s Jewels utilise toutes les fonctionnalités de Mango et n’a pas besoin d’un tricks non autorisé sur le marketplace.
J’éspère que Microsoft me permettra, comme le fameux emulateur NES, VNesLight de Nudua, d’intégrer le marketplace sans trop d’embuches.

Deux versions

Il y aura deux versions pour l’appli.
Une gratuite qui ne possédera pas toutes les options mais fonctionnelle et une payante plus complète.

La version payante permettra :

  • Le téléchargement de rom par le biais d’un explorateur skydrive au lieu d’une url pour la version gratuite.
  • L’affichage d’un mode Paysage de l’émulateur en plus de la version portrait
  • Le changement de 30 à 60 images par secondes (1 frame en moins en 30fps) pour les devices de nouvelles générations !
  • La gestion de 3 slots de sauvegarde (destruction et copie)
  • Le partage via Facebook et l’enregistrement de screenshot dans l’album Photo
  • La possibilitée d’accrocher ses jeux directment sur la page d’accueil avec photo du screenshot et information en face arrière du tile

La version gratuite aura une publicité en haut des menus de sélection (mais pas durant les phases de jeu).
L’application sera disponible au prix de 1,29€.

Le son

Il n’y aura pas de son dans cette première version bien que j’étudie la manière de l’ajouter.

Screenshots

Le paddle n’est pas encore complétement terminé. Il sera réalisé comme pour WJ7 par Damien Bigot !












Se tenir au courant !

Vous pouvez vous tenir au courant des dernière nouveauté sur la page facebook de Wario’s Jewels



Tags: , , ,
Posted in Emulator Silverlight WP7 by Samuel Blanchard. 5 Comments

BUGTRACK de Programmez! n°148

Peut-être vous souvenez vous du bug étrange rencontré sur Windows Phone et que je vous avais décrit en détail dans le truc #4 sur le photoChooserTask ?

Celui-ci se retrouve à la une de la nouvelle formule du magazine Programmez! (avec mon copain américain Julien Dollon en couverture) dans une nouvelle rubrique décryptant un bug inédit et la façon dont il est traqué.







D’autres articles devraient suivre rapidemment notamment sur le projet Hawaii…

Meilleurs voeux 2012 à tous ^^



Posted in Silverlight by Samuel Blanchard. No Comments