Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Thomas Lebrun

Tout sur WPF, LINQ, C# et .NET en général !

[Personnel] MVP++ :)

Et oui, quoi de plus clair comme titre ! Je viens de recevoir l’email, de la part de Microsoft, me confirmant mon renouvellement MVP dans la catégorie Client Application Development.

Merci à tous ceux, de Microsoft ou non, qui me suivent (et m’encouragent) de prêt ou de loin !

 

A+

[WPF] Comment savoir si le rendu est effectué par la carte graphique ou le processeur ?

WPF a la particularité de faire en sorte que tous les calculs nécessaires à l’affichage soit effectués par la carte graphique (GPU), si celle-ci le permet. Mais comment savoir, par programmation, si la carte graphique sera en mesure d’effectuer les calculs ?

Il existe une propriété, nommée RenderCapability.Tier, qui permet justement de renvoyer cette information:

int renderingTier = (RenderCapability.Tier >> 16);

En fonction de la valeur retournée, vous pouvez connaitre les capacités de votre carte graphique:

  • 0: Aucune accélération matérielle n’est disponible pour le périphérique
  • 1: La carte graphique supporte une accélération matérielle partielle. Cela correspond à une version de DirectX comprise entre 7 et 9.
  • 2: Toutes les fonctionnalités d’accélération matérielle sont disponibles. Cela correspond à une version de DirectX supérieure (ou égale) à la version 9.

Pour plus d’infos, c’est par ici: http://msdn.microsoft.com/en-us/library/system.windows.media.rendercapability.tier.aspx

 

A+

[Silverlight] Une implémentation de la DataTable en Silverlight

Récemment, j’ai eu besoin d’utiliser une structure de données qui se rapprochait beaucoup, en termes de fonctionnalités, de ce que l’on peut retrouver dans les Dataset/DataTables du Framework .NET.

Je suis alors tombé sur ce petit projet qui, bien que tout simple, à l’avantage de fonctionner parfaitement bien: il est même possible de lier directement une DataTable à une DataGrid Silverlight (2 ou 3) !

Bref, comme quoi, lorsque l’on cherche, on finit par trouver, ce qui évite de devoir réinventer la roue Wink

 

A+

[WCF] Appeler un service WCF depuis un client Java

Pour un projet récent, j’ai eu besoin de développer un service WCF qui utilise le Membership Provider d’ASP.NET. Pour cela, il est nécessaire d’utiliser le binding de type wsHttpBinding.

Tout ce passait très bien jusqu’à ce qu’on me prévienne que mon service n’était pas accessible depuis un client Java. Après avoir effectué quelques tests et recherché sur Internet, j’ai découvert que le problème semblait venir de la version de SOAP utilisée.

En effet, le binding de type wsHttpBinding utilise la version 1.2 de SOAP. Cependant, Java n’est pas en mesure (d’après mes recherches donc libre à vous de me corriger si je dit une bétise Smile) de gérer les versions de SOAP supérieures à la version 1.1: il y a donc une incompatibilité entre Java et le binding wsHttpBinding.

Pour pallier à ce problème, vous avez plusieurs possibilités:

  • Créer un service “proxy”, utilisant le binding de type basicHttpBinding, qui va appeler votre service
  • Intercepter les Headers SOAP et y insérer des informations de logins/mots de passe, qui seront ensuite réutilisées coté service pour authentifier l’utilisateur
  • Etc.

Pour mon cas, j’ai opté pour la deuxième solution mais libre à vous de choisir celle qui vous intéresse/convient le mieux Smile

 

A+

[Visual Studio 2010] Où est passé mon espace disque ?

Depuis la sortie de Visual Studio 2010 Beta 1, je l’utilise comme environnement de développement sur la plupart des applications personnelles que je développe sur mon temps libre.

J’ai cependant remarqué un comportement particulier: mon espace disque diminuait jusqu’à ce qu’il soit complètement saturé:

image

J’ai alors utilisé WinDirStats pour inspecter la taille des différents répertoires de mon système et je me suis rendu compte que le répertoire C:\ProgramData\Microsoft Visual Studio\10.0\TraceDebugging contenait énormément de fichiers, chacun pesant entre 20 et 25 Mo:

image

En cherchant sur Internet, j’ai découvert que ces fichiers étant en fait utilisés par l’Historical Debugger. Il s’agit d’une nouvelle fonctionnalité de Visual Studio 2010 qui permet d’améliorer l’expérience de débugging de vos applications.

Grâce à la procédure indiquée ici, j’ai désactivé cette fonctionnalité:

image

Ensuite, j’ai supprimé les fichiers du répertoire et tout est revenu à la normal:

image

Et le tour est joué Smile

 

A+

[Vista / Seven] Comment développer sa propre barre d’outils ?

La création de barre d’outils personnalisées, pour Windows, requiert d’utiliser certaines méthodes/interfaces natives comme par exemple IDeskBand, IObjectWithSite, etc.

Lorsque l’on est développeur .NET, on se retrouve donc obligé de faire de l’interop afin de pouvoir disposer de sa propre barre d’outils. Fort heureusement, Pavel Zolnikov a écrit, sur CodeProject, un article dans lequel il met à disposition un objet managé (BandObject), prêt à l’emploi, permettant la création de barre d’outils personnalisée:

http://www.codeproject.com/KB/shell/dotnetbandobjects.aspx

Le résultat est vraiment bluffant et tout cela, en seulement quelques minutes de développement:

image

A noter que pour, pour Windows Vista et Windows Seven, vous pouvez également implémenter IDeskBand2, qui permet de gérer la transparence au niveau de la barre d’outils.

 

A+

[WPF] Comment masquer un contrôle si la commande liée est désactivée ?

Allez, un petit post rapide pour vous montrer un simple astuce que l’on retrouve assez souvant comme question: Comment faire pour masquer un contrôle, plutôt que de le désactiver, si la commande qui lui est liée est désactivée ?

Pour cela, on va commencer par déclarer un petit converter, BooleanToVisibilityConverter. Attention, pas besoin de le redéfinir soi-même: celui-ci est disponible de base dans WPF Smile

<BooleanToVisibilityConverter x:Key="convVisibility" />

Ensuite, il ne reste plus qu’à faire un peu de binding sur la propriété Visibility du contrôle, par rapport à SA propriété IsEnabled:

<Button Content="Supprimer" Command="ApplicationCommands.Delete" Visibility="{Binding IsEnabled, RelativeSource={x:Static RelativeSource.Self}, Converter={StaticResource convVisibility}}"/>

Simple mais terriblement efficace !

 

A+

[Seven / Vista] La classe TaskDialog et l’erreur “Unable to find an entry point named 'TaskDialogIndirect' in DLL 'comctl32.dll'”

Suite à la demande de tomlev, j’ai cherché à utilisé la classe TaskDialog du Windows® API Code Pack for Microsoft® .NET Framework (v0.85) et effectivement, ce n’est pas aussi simple car l’utilisation du code provoque l’erreur suivante:

Unable to find an entry point named 'TaskDialogIndirect' in DLL 'comctl32.dll'.

image

Après avoir cherché sur Internet, j’ai confirmé ce que tomlev avait dit à savoir que que l’erreur provient d’un fichier manifest qui doit être présent et dans lequel on force l’utilisation comctl.dll en version 6 (afin de forcer vos contrôles à avoir le “look & feel” de Windows Vista ou Windows Seven). J’ai trouvé la solution à ce problème grâce à ce lien et je vous le fais partager. Faîtes un clic droit sur votre projet => Propriétés => Security. Là, cocher la case “Enable ClickOnce Security Settings”:

image

Puis compiler votre projet. Là, un fichier app.manifest va apparaitre dans le répertoire Properties de votre projet:

image

Double-cliquez sur ce fichier et sous la ligne:

</trustInfo>

Rajoutez ceci:

<dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" />
    </dependentAssembly>
  </dependency>

Ensuite, recompiler votre projet. Vous devriez alors avoir une erreur de compilation:

image

Pour la faire disparaitre, décochez simplement la case “Enable ClickOnce Security Settings” qui est dans l’onglet Security des propriétés de votre projet. Recompilez votre projet, exécuter-le à nouveau et vous devriez constater que l’application (et la TaskDialog) se lance parfaitement Smile

image

 

A+

[WPF] L’intellisense XAML dans Visual Studio 2010

La Beta 1 de Visual Studio 2010, disponible depuis hier pour les abonnées MSDN, apportent un grand nombre de nouveautés liés à WPF. Je tâcherais de faire des posts (peut-être même un article ?) sur ces nouveautés mais je voulais commencer par vous montrer 2 nouvelles fonctionnalités propres à l’IDE.

La première concerne la mise à disposition, dans Visual Studio, d’un mini-éditeur de binding:

image

Ainsi, plus besoin de passer par Blend pour faire son binding, on peut le faire directement (et simplement) depuis VS. Pour les personnes qui, comme moi, préfèrent écrire leur XAML à la main, et c’est la deuxième chose dont je voulais vous parler, on dispose à présent, dans le code XAML, de l’intellisense sur les MarkupExtensions !

image

Grâce à cela, dès que vous ouvrirez une accolade, Visual Studio vous propose de choisir entre Binding, StaticResource, DynamicResource, etc. De plus, si vous choisissez Binding, vous pourrez constater que, là encore, vous disposez de l’intellisense au niveau de propriétés utilisables:

image

Certes, cela ne représente peut-être rien pour certains mais il s’agissait là d’un des points faibles que beaucoup de monde reprochait à WPF: c’est maintenant un véritable plus qui va permettre d’aller toujours un peu plus vite !

Allez, juste pour la route, une capture d’écran du nouvel outil “natif” dans Visual Studio 2010 pour gérer/assigner des couleurs aux contrôles Smile

image

 

A bientôt pour la suite Smile

 

A+

[Seven] Utiliser les icônes système standard de Windows Seven !

Voici une autre fonctionnalité offerte par la bibliothèque Windows® API Code Pack for Microsoft® .NET Framework (v0.85): la possibilité de récupérér et d’utiliser la liste des icônes système standard disponible sur Windows 7.

Pour cela, vous allez devoir utiliser la classe StockIcons.

stockIcons = new StockIcons();

Une fois l’objet instancié, vous pouvez utiliser plusieurs propriétés qui servent à représenter les différentes icones systèmes:

image

Ensuite, chaque icône dispose de plusieurs propriétés que vous pouvez manipuler:

  • CurrentSize, qui représente la taille courante de l’icône (vous avez le choix entre Large, ShellSize et Small)
  • LinkOverlay, qui permet d’indiquer si vous souhaiter faire afficher la flêche servant à représenter l’icone comme raccourci
  • Selected, qui affiche l’icône comme étant sélectionnée.

Voici un exemple résultant de l’affichage de toutes les icônes “système”:

image

Là encore, cela n’a rien d’extraordinaire mais cela permet d’avoir accès, rapidement et simplement, à l’icône correcte qui vous intéresse Smile

 

A+

[Seven] Travailler avec les KnownFolders, ShellObjets et ShellLibraries de Windows Seven !

La bibliothèque Windows® API Code Pack for Microsoft® .NET Framework (v0.85)  permet de travailler facilement avec les KnowFolders de Windows Seven.

Pour cela, il est nécessaire d’utiliser la classe (statique) nommée KnownFolders. Celle-ci définie un ensemble de propriétés désignant les différents répertoires connus sur le système d’exploitation:

/// <summary>

/// Gets the computer folder.

/// </summary>

/// <value>A <see cref="IKnownFolder"/> object.</value>

public static IKnownFolder Computer

{

    get

    {

        return GetKnownFolder(

            FolderIdentifiers.Computer);

    }

}

 

/// <summary>

/// Gets the Windows Vista Synchronization Manager folder.

/// </summary>

/// <value>A <see cref="IKnownFolder"/> object.</value>

public static IKnownFolder Conflict

{

        get

        {

            return GetKnownFolder(

                FolderIdentifiers.Conflict);

        }

}

 

/// <summary>

/// Gets the control panel.

/// </summary>

/// <value>A <see cref="IKnownFolder"/> object.</value>

public static IKnownFolder ControlPanel

{

    get

    {

        return GetKnownFolder(

            FolderIdentifiers.ControlPanel);

    }

}

Chaque répertoire, de type IKnownFolder, contient un ensemble d’objets de type ShellObject définissant un grand nombre de propriétés:

 private ShellThumbnail thumbnail;

/// <summary>

/// Gets the thumbnail of the ShellObject.

/// </summary>

public ShellThumbnail Thumbnail

{

    get

    {

        if (thumbnail == null)

             thumbnail = new ShellThumbnail(this);

 

        return thumbnail;

    }

}

 

private ShellObject parentShellObject = null;

/// <summary>

/// Gets the parent ShellObject

/// </summary>

public ShellObject Parent

{

    get

    {

        if (parentShellObject == null && nativeShellItem != null)

        {

            IShellItem parentShellItem = null;

 

            HRESULT hr = nativeShellItem.GetParent(out parentShellItem);

 

            if (hr == HRESULT.S_OK && parentShellItem != null)

                parentShellObject = ShellObjectFactory.Create(parentShellItem);

            else

                throw Marshal.GetExceptionForHR((int)hr);

        }

 

        return parentShellObject;

    }

}

Ainsi, il est possible de tout savoir sur un objet spécifique:

internal static void ShowObjectData(Window1 wnd, ShellObject shellObj)

{

    wnd.PropertiesTextBox.Text =

        String.Format(

            "Name = {0}{1}Path/ParsingName = {2}{1}Type = {3}{4} ({5}File System)",

             shellObj.Name,

             Environment.NewLine,

             shellObj.ParsingName,

             shellObj.GetType().Name,

             shellObj.IsLink ? " (Shortcut)" : "",

             shellObj.IsFileSystemObject ? "" : "Non ");

}

Si l’objet en question est de type IKnownFolder alors il est possible d’afficher les propriétés de ce répertoire:

internal static void ShowKnownFolderProperties(Window1 wnd, IKnownFolder kf)

{

    wnd.FolderPropsListBox.Visibility = Visibility.Visible;

    wnd.PropertiesGrid.RowDefinitions[1].Height = new GridLength(150);

 

    Collection<KnownFolderProperty> properties = new Collection<KnownFolderProperty>();

 

    properties.Add(new KnownFolderProperty { Property = "Canonical Name", Value = kf.CanonicalName });

    properties.Add(new KnownFolderProperty { Property = "Category", Value = kf.Category });

    properties.Add(new KnownFolderProperty { Property = "Definition Options", Value = kf.DefinitionOptions });

    properties.Add(new KnownFolderProperty { Property = "Description", Value = kf.Description });

    properties.Add(new KnownFolderProperty { Property = "File Attributes", Value = kf.FileAttributes });

    properties.Add(new KnownFolderProperty { Property = "Folder Id", Value = kf.FolderId });

    properties.Add(new KnownFolderProperty { Property = "Folder Type", Value = kf.FolderType });

    properties.Add(new KnownFolderProperty { Property = "Folder Type Id", Value = kf.FolderTypeId });

    properties.Add(new KnownFolderProperty { Property = "Path", Value = kf.Path });

    properties.Add(new KnownFolderProperty { Property = "Relative Path", Value = kf.RelativePath });

    properties.Add(new KnownFolderProperty { Property = "Security", Value = kf.Security });

    properties.Add(new KnownFolderProperty { Property = "Tooltip", Value = kf.Tooltip });

 

    wnd.FolderPropsListBox.ItemsSource = properties;

}

Dans le cas d’un objet de type ShellLibrary, on va travailler avec une Library, nouveautés de Windows 7 qui permettent de regrouper, dans un même dossier, des fichiers provenant de répertoires différents. Dans ce cas, on va disposer de propriétés différentes à afficher/manipuler:

internal static void ShowLibraryProperties(Window1 wnd, ShellLibrary lib)

{

    wnd.FolderPropsListBox.Visibility = Visibility.Visible;

    wnd.PropertiesGrid.RowDefinitions[1].Height = new GridLength(150);

 

    Collection<KnownFolderProperty> properties = new Collection<KnownFolderProperty>();

 

    properties.Add(new KnownFolderProperty { Property = "Name", Value = lib.Name});

    object value = null;

 

    try

    {

        value = lib.LibraryType;

    }

    catch 

    {}

    properties.Add(new KnownFolderProperty { Property = "Library Type", Value = value });

 

 

    try

    {

        value = lib.LibraryTypeId;

    }

    catch

    { }

    properties.Add(new KnownFolderProperty { Property = "Library Type Id", Value = value });

 

    properties.Add(new KnownFolderProperty { Property = "Path", Value = lib.ParsingName});

    properties.Add(new KnownFolderProperty { Property = "Is Pinned To NavigationPane", Value = lib.IsPinnedToNavigationPane });

 

    wnd.FolderPropsListBox.ItemsSource = properties;

}

Enfin, chaque ShellObject possède une propriété nommée Thumbnail qui permet de récupérer la vignette, sous différents formats/tailles, associée à l’objet en question:

internal static void ShowThumbnail(Window1 wnd, ShellObject shellObj)

{

    try

    {

        wnd.ThumbnailPreview.Source = shellObj.Thumbnail.LargeBitmapSource;

    }

    catch

    {

        wnd.ThumbnailPreview.Source = null;

    }

}

Voici un exemple lorsque l’on sélectionne la corbeille, qui est un KnowFolder:

image

On constate donc qu’il est très aisé de travailler avec les KnowFolders, ShellObjets et ShellLibraries de Windows 7, grâce à cette bibliothèque d’APIs qui facilite grandement les développements !

 

A+

[Seven] Utiliser l’explorateur de fichiers dans vos applications !

La bibliothèque Windows® API Code Pack for Microsoft® .NET Framework (v0.85)  mise à disposition par Microsoft permet aux développeurs d’utiliser un contrôle nommé ExplorerBrowser.

Celui-ci permet d’insérer l’explorateur de fichier directement au sein de vos applications (WindowsForms ou WPF):

image

Pour l’utiliser, c’est extrèmement simple car toutes les fonctionnalités de l’explorateur sont exposées sous forme de DependencyProperties (il est donc possible d’utiliser le DataBinding !).

Voici un exemple d’utilisation de ce contrôle:

<!-- The Explorer Browser -->                   
<WindowsAPICodePackPresentation:ExplorerBrowser

         x:Name="eb"

         Margin="5"

         AlignLeft="{Binding IsSelected, ElementName=lbiAlignLeft, Mode=TwoWay}"

         AutoArrange="{Binding IsSelected, ElementName=lbiAutoArrange, Mode=TwoWay}"

         CheckSelect="{Binding IsSelected, ElementName=lbiCheckSelect, Mode=TwoWay}"

         ExtendedTiles="{Binding IsSelected, ElementName=lbiExtendedTiles, Mode=TwoWay}"

         FullRowSelect="{Binding IsSelected, ElementName=lbiFullRowSelect, Mode=TwoWay}"

         HideFileNames="{Binding IsSelected, ElementName=lbiHideFileNames, Mode=TwoWay}"

         NoBrowserViewState="{Binding IsSelected, ElementName=lbiNoBrowserViewState, Mode=TwoWay}"

         NoColumnHeader="{Binding IsSelected, ElementName=lbiNoColumnHeader, Mode=TwoWay}"

         NoHeaderInAllViews="{Binding IsSelected, ElementName=lbiNoHeaderInAllViews, Mode=TwoWay}"

         NoIcons="{Binding IsSelected, ElementName=lbiNoIcons, Mode=TwoWay}"

         NoSubFolders="{Binding IsSelected, ElementName=lbiNoSubFolders, Mode=TwoWay}"

         SingleClickActivate="{Binding IsSelected, ElementName=lbiSingleClickActivate, Mode=TwoWay}"

         SingleSelection="{Binding IsSelected, ElementName=lbiSingleSelection, Mode=TwoWay}"

         AlwaysNavigate="{Binding IsSelected, ElementName=lbiAlwaysNavigate, Mode=TwoWay}"

         NavigateOnce="{Binding IsSelected, ElementName=lbiNavigateOnce, Mode=TwoWay}"

         ViewMode="{Binding SelectedValue, ElementName=ViewModeCombo, Mode=TwoWay}"

         ThumbnailSize="{Binding Value, ElementName=thumbnailSizeSlider, Mode=TwoWay}"

         AdvancedQueryPane="{Binding IsChecked, ElementName=lbiAdvancedQueryPane, Mode=TwoWay, Converter={StaticResource tristateConverter} }"

         CommandsPane="{Binding IsChecked, ElementName=lbiCommandsPane, Mode=TwoWay, Converter={StaticResource tristateConverter} }"

         CommandsOrganizePane="{Binding IsChecked, ElementName=lbiCommandsOrganizePane, Mode=TwoWay, Converter={StaticResource tristateConverter} }"

         CommandsViewPane="{Binding IsChecked, ElementName=lbiCommandsViewPane, Mode=TwoWay, Converter={StaticResource tristateConverter} }"

         DetailsPane="{Binding IsChecked, ElementName=lbiDetailsPane, Mode=TwoWay, Converter={StaticResource tristateConverter} }"

         NavigationPane="{Binding IsChecked, ElementName=lbiNavigationPane, Mode=TwoWay, Converter={StaticResource tristateConverter} }"

         PreviewPane="{Binding IsChecked, ElementName=lbiPreviewPane, Mode=TwoWay, Converter={StaticResource tristateConverter} }"

         QueryPane="{Binding IsChecked, ElementName=lbiQueryPane, Mode=TwoWay, Converter={StaticResource tristateConverter} }"

         NavigationTarget="{Binding SelectedItem, ElementName=KnownFoldersList, Mode=OneWay}" />

Comme vous pouvez le constater, un grand nombre de propriétés sont disponibles, permettant une manipulation fine et précise de ce contrôle Smile

 

A+

[Seven] De nouvelles APIs pour travailler avec les nouvelles fonctionnalités de Windows 7

Dans la lignée de la sortie de Windows 7 en version RC (Release Candidate), Microsoft vient de mettre en ligne une nouvelle bibliothèque contenant un ensemble d’APIs permettant de travailler, depuis du code managé, avec les nouvelles fonctionnalités de Windows 7: Windows® API Code Pack for Microsoft® .NET Framework (v0.85)

Les fonctionnalités incluent dans cette version sont les suivantes:

  • Support for Windows Shell namespace objects, including the new Windows 7 libraries, Known Folders and non file system containers.
  • Windows Vista and Windows 7 Task Dialogs.
  • Windows 7 Explorer Browser Control supporting both WPF and Windows Forms.
  • Support for Shell property system.
  • Helpers for Windows 7 Taskbar Jumplists, Icon Overlay and Progress bar.
  • Support for Windows Vista and Windows 7 common file dialogs, including custom file dialog controls.
  • Support for Direct3D 11.0 and DXGI 1.0/1.1 APIs.
  • Sensor Platform APIs
  • Extended Linguistic Services APIs

Il est à noter que cette bibliothèque n’est pas finit: elle sera mise à jour/finalisée peu de temps après la sortie de la version RTM (Release To Manufacture) de Windows 7.

Je tâcherais de faire quelques posts expliquant comment utiliser certaines de ces nouvelles fonctionnalités Smile

 

A+

[WPF / MVVM] Comment disposer de données en “design time” ?

Lorsque l’on travaille avec WPF et le Pattern MVVM, on peut regretter le fait que le designer ne dispose pas de données, en design time, qui lui permettent de modifier facilement l’interface graphique.

Pour faciliter cela, j’ai créé une petite propriété attachée qui se charge de créer une instance du type passé en paramètre:

public static class DesignTimeHelper

{

    /// <summary>

    /// DependencyProperty used to store the DesignTime property.

    /// </summary>

        public static readonly DependencyProperty DesignTimeDataProperty =

        DependencyProperty.RegisterAttached("DesignTimeData", typeof(Type), typeof(DesignTimeHelper), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnDesignTimeDataChanged)));

 

    /// <summary>

    /// Gets the design time data.

    /// </summary>

    /// <param name="obj">The obj.</param>

    /// <returns></returns>

    public static Type GetDesignTimeData(DependencyObject obj)

    {

        return (Type)obj.GetValue(DesignTimeDataProperty);

    }

 

    /// <summary>

    /// Sets the design time data.

    /// </summary>

    /// <param name="obj">The obj.</param>

    /// <param name="value">The value.</param>

    public static void SetDesignTimeData(DependencyObject obj, Type value)

    {

        obj.SetValue(DesignTimeDataProperty, value);

    }

 

    /// <summary>

    /// Called when DesignTimeData changed.

    /// </summary>

    /// <param name="d">The source object.</param>

    /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>

    private static void OnDesignTimeDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

    {

        var isOnDesignMode = DesignerProperties.GetIsInDesignMode(new DependencyObject());

        if (isOnDesignMode)

        {

            var element = d as FrameworkElement;

            if (element == null)

                throw new NullReferenceException("element must not be null and must be an UIElement.");

 

            var designTimeDataType = e.NewValue as Type;

            if (designTimeDataType == null)

                throw new NullReferenceException("designTimeDataType must not be null.");

 

            element.DataContext = Activator.CreateInstance(designTimeDataType);

        }

    }

}

Pour utiliser cette propriété attachée, rien de plus simple: on se créé 2 ViewModels, l’un utilisé pour les données au “runtime” et l’autre utilisé pour les données en “designtime”:

image

Ensuite, il ne reste plus qu’à utiliser la propriété attachée:

image

En “design time”, on constate que les données sont bien différentes qu’au “runtime”:

image image

image

A titre d’informations, voici le contenu du ViewModel en mode “design”:

namespace TestToolbox.ViewModels.Design

{

    class SampleViewModel : ISampleViewModel

    {

        #region ISampleViewModel Members

 

        public string Text

        {

            get { return "Design time text"; }

        }

 

        public string Title

        {

            get { return "Design time title"; }

        }

 

        #endregion

    }

}

Et voici le ViewModel du mode “runtime”:

namespace TestToolbox.ViewModels

{

    public class SampleViewModel : ISampleViewModel

    {

        #region ISampleViewModel Members

 

        public string Text

        {

            get { return "Runtime text"; }

        }

 

        public string Title

        {

            get { return "Runtime title"; }

        }

 

        #endregion

    }

}

Et voila, c’est simple mais terriblement efficace ! A présent, votre designer peut travailler sur des données (fictives) qui vont lui simplifier la vie pour toute la partie design (il n’aura pas besoin d’exécuter l’application à chaque fois pour tester/visualiser le résultat).

 

A+

 

PS: Merci à Simon pour la suggestion de passer par un type plutôt qu’une simple chaîne de caractères Wink

[WPF] Envie de vous former à WPF ? Le Coach WPF est là pour ça !

wpf - accueil

Si vous souhaitez vous former à WPF (Windows Presentation Foundation) alors le Coach WPF est pour vous !

Attention, ici, pas question de parler de MVVM ou autre pattern de ce type: vous y découvrirez comment créer votre premier projet WPF, comment utiliser une base de données/un WebService avec une application WPF, etc. Comme vous pouvez le voir, rien de bien compliqué lorsque l’on maitrise la technologie mais qui peut s’avérer fort utile lorsque l’on débute Smile

Pour le moment, seul le premier atelier est en ligne mais mon petit doigt me dit que les ateliers suivants devraient bientôt voir le jour Wink

 

Le Coach WPF est ici: http://msdn2.microsoft.com/fr-fr/netframework/msdn.coach.wpf.aspx

La liste de tous les Coach est accessible là: http://msdn.microsoft.com/fr-fr/msdn.coach.aspx

 

A+

[WPF] Comment actionner une commande WPF lorsqu’un évènement est déclenché ?

Lorsque l’on travaille avec WPF et le pattern MVVM (Model View ViewModel), on essaye d’éviter au maximum de mettre du code directement dans la code behind. Ainsi, le code suivant n’est pas le mieux:

public partial class MainWindow : Window

{

    public MainWindow()

    {

        this.InitializeComponent();

    }

 

    <Button x:Name="btnTest"

            Content="Test Command"

            HorizontalAlignment="Center"

            VerticalAlignment="Center"

            MouseLeave="btnTest_MouseLeave" />

 

    private void btnTest_MouseLeave(object sender, MouseEventArgs e)

    {

        MessageBox.Show("Appel réussit !");

    }

}

A choisir, on préfèrera plutôt utiliser les commandes WPF plutôt que de s’abonner aux évènements directement dans le code behind.

OK mais dans ce cas, comment faire pour déclencher une commande lorsqu’un évènement survient ? La solution, toute bête, passe par l’utilisation des propriétés attachées de WPF. Ainsi, il suffit de créer une simple classe qui va containir 2 propriétés:

  • une pour la commande à appeler
  • une pour le nom de l’évènement à surveiller

Dès que vous affectez une valeur à la propriété servant à surveiller l’évènement qui vous intéresse, vous vous abonnez en fait à cet évènement. Puis, lorsque celui-ci est déclenché, vous appelez la commande que vous avez branché ! Voici un exemple d’implémentation (attention, notez qu’il s’’agit d’un exemple/prototype):

public class EventBehavior

{

    public static ICommand GetCommand(DependencyObject obj)

    {

        return (ICommand)obj.GetValue(CommandProperty);

    }

 

    public static void SetCommand(DependencyObject obj, string value)

    {

        obj.SetValue(CommandProperty, value);

    }

 

    public static readonly DependencyProperty CommandProperty =

        DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(EventBehavior), new FrameworkPropertyMetadata(null));

 

    public static string GetEventName(DependencyObject obj)

    {

        return (string)obj.GetValue(EventNameProperty);

    }

 

     public static void SetEventName(DependencyObject obj, string value)

    {

        obj.SetValue(EventNameProperty, value);

    }

 

    public static readonly DependencyProperty EventNameProperty =

        DependencyProperty.RegisterAttached("EventName", typeof(string), typeof(EventBehavior), new FrameworkPropertyMetadata(string.Empty, new PropertyChangedCallback(OnEventNameChanged)));

 

    private static void OnEventNameChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)

    {

        var element = target as UIElement;

        if(element != null)

        {

            if ((!string.IsNullOrEmpty((string)e.NewValue) && (string.IsNullOrEmpty((string)e.OldValue))))

            {

                var eventName = (string)e.NewValue;

 

                var eventInfo = element.GetType().GetEvent(eventName);

                if(eventInfo != null)

                {

                    SinkControlEvent(element, eventName);

                }

                else

                {

                    throw new NullReferenceException(string.Format("Event name {0} has not been found on this object !", eventName));

                }

            }

        }

        else

        {

            throw new NullReferenceException("This behavior can only be installed on UIElement objects !");

        }

    }

 

    /// <summary>

    /// Sinks the control event.

    /// Source: http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/ae1b155e-1388-431c-bc0e-e7846f9368c8

    /// </summary>

    /// <param name="sender">The sender.</param>

    /// <param name="eventName">Name of the event.</param>

    static void SinkControlEvent(object sender, string eventName)

    {

        // Get the event information for the specified event.   

        var eventInfo = sender.GetType().GetEvent(eventName);

 

        // Get the handler type for the specified event.   

        Type handlerType = eventInfo.EventHandlerType;

 

        // Get the ParameterInfo collection for the event handler's invoke method.   

        if (handlerType != null)

        {

            var parameterInfos = handlerType.GetMethod("Invoke").GetParameters();

 

            // Get the collection of types corresponding to the event handler's parameters.  

            Type[] parameterTypes = parameterInfos.Select(p => p.ParameterType).ToArray();

 

            // Get the type of the AnonymousDelegateClass, and fill the generic parameters.   

            Type type = typeof(AnonymousDelegateClass<,>).MakeGenericType(parameterTypes);

 

            // Get the constructor for the class that takes the string value.   

            var constructor = type.GetConstructor(new[] { typeof(string) });

 

            // Create an instance of the class, which will subscribe to the event specified.   

            object instance = constructor.Invoke(new object[] { eventName });

 

            // Get the Handler method, which will be the event handler for the event.   

            var method = type.GetMethod("OnEventRaised");

 

            // Create a delegate of the same type of the handler type based on the Handler method.  

            Delegate eventhandler = Delegate.CreateDelegate(handlerType, instance, method);

 

            // Finally, add the event handler to the object specified.   

            eventInfo.AddEventHandler(sender, eventhandler);

        }

    }  

}

 

/// <summary>

/// Anonymous delegate class.

/// </summary>

/// <typeparam name="TSender">The type of the sender.</typeparam>

/// <typeparam name="TEventargs">The type of the eventargs.</typeparam>

public class AnonymousDelegateClass<TSender, TEventargs> where TEventargs : EventArgs

{

    // This is the name of the event subscribed to.   

    public string Name { get; private set; }

 

    public AnonymousDelegateClass(string name)

    {

        Name = name;

    }

 

    // This the generic handler that is used to subscribe to the object.   

    public void OnEventRaised(TSender sender, TEventargs e)

    {

        var element = sender as UIElement;

        if (element != null)

        {

            var command = (ICommand)element.GetValue(EventBehavior.CommandProperty);

            command.Execute(e);

        }

        else

        {

            throw new NullReferenceException("This behavior can only be installed on UIElement objects !");

        }

    }

}

Pour utiliser tout cela, rien de plus simple:

<Button x:Name="btnTest"

        Content="Test Command"

        HorizontalAlignment="Center"

        VerticalAlignment="Center"

        Behaviors:EventBehavior.Command="{Binding ShowMessageCommand}"

        Behaviors:EventBehavior.EventName="MouseEnter" />

Et le tour est joué Smile

Pour votre gouverne, sachez que ce pattern est connu sous le nom d’Attached Behavior Pattern (la notion de Behaviors revient avec Expression Blend 3 Wink). Si vous voulez en savoir plus, ou bien si vous souhaitez avoir des implémentations plus complètes, je vous conseille les liens suivants:

 

A+

[WPF] Shazzam, un outil pour tester vos Pixel Shaders

Récemment, j’ai pas mal joué avec les Pixel Shaders de WPF et Silverlight 3.

J’ai alors découvert un outil fort sympathique, Shazzam,  qui permet:

  • d’écrire le code du Pixel Shader en HLSL
  • de tester le Shader directement (sans avoir besoin de l’inclure dans une application)
  • de générer le fichier portant l’extension “ps”
  • de générer le code C#/VB.NET permettant de charger le Shader dans une application WPF/Silverlight 3

 

Cela peut sembler futile mais il s’agit là d’un outil qui vous fera gagner énormément de temps si vous êtes amené à travailler avec les Pixel Shaders !

Pour en savoir plus, rendez-vous ici: http://wpfwonderland.wordpress.com/2008/10/08/shazzam-wpf-pixel-shader-effect-testing-tool-now-available/

 

A+

[Silverlight 3] SaveFileDialog et l’exception IOException: “The directory name is invalid”

J’ai rencontré un bug assez génant lorsque j’ai essayé le contrôle SaveFileDialog de Silverlight 3. En effet, à chaque fois que j’utilisais la méthode OpenFile, je recevais l’exception suivante:

IOException: The directory name is invalid

J’ai au début pensé à un problèmes de droits pour l’emplacement sur lequel je voulais sauvegarder le fichier mais il s’avère, suite à un échange sur le forum de Silverlight, que le problème vient plutôt du mode protégé d’Internet Explorer qui était activé pour la zone Intranet.

"IE -> Tools -> Internet Options -> Security –> Enable/Disable Protected Mode"

Lorsque j’ai désactivé le mode protégé, l’appel à la méthode OpenFile a fonctionné sans problèmes ! Bien sur, il s’agit là d’une solution temporaire car, pour des raisons de sécurités, il est recommandé de conserver le mode protégé activé Wink

 

A+

[Silverlight 3 / RIA Services] Téléchargez le code source du Live Meeting de ce soir

Suite au Live Meeting que j’ai eu l’occasion d’animer ce soir avec Julien DOLLON, vous pouvez télécharger le code source de l’application que j’ai démontré à cette adresse: http://morpheus.developpez.com/silverlight/EmployeesViewer_SL3.zip

A noter que ce fut une belle présentation avec pas moins de 90 participants !

Pour ceux qui n’ont pas pu venir, le prochain Live Meeting que j’organise avec Florent SANTIN aura lieu mardi prochain et parlera des interfaces riches (WPF/Silverlight) !

 

A bientôt !

[Blend] L’intellisense dans Expression Blend 3

La version 3 d’Expression Blend, qui est disponible depuis peu, apporte son lot de nouvelles fonctionnalités. Parmis ces fonctionnalités, on trouve l’apparition de l’intellisense au niveau du code XAML:

image 

Voila donc un point fortement appreciable pour ceux qui, comme moi, modifie pas mal le code XAML: plus besoin d’ouvrir Visual Studio pour profiter de l’intellisense !

Cependant, on peut remarquer un autre point intéressant: la réapparition de l’éditeur de code (C# ou VB) dans Expression Blend, avec intégration de l’Intellisense:

image

image

Certes, on ne va pas développer une application entière de cette façon mais pour des tests rapides, c’est toujours ça de gagner !

 

A+

Plus de Messages Page suivante »


Les 10 derniers blogs postés

- [Refactoring] ReSharper pour Visual Studio 2010 (Preview) par Thomas Jaskula le il y a 14 heures et 13 minutes

- [Refactoring] Analyser vos exceptions avec ReSharper Exceptional par Thomas Jaskula le il y a 15 heures et 27 minutes

- SharePoint 2007 : patterns & practices SharePoint Guidance par Philippe Sentenac [MVP SharePoint] le 07-03-2009, 09:56

- [Visual Studio 2010] Les tests cases c’est bien, mais je vais devoir tout réécrire ? par Etienne Margraff le 07-03-2009, 09:00

- MVP[Gribouillon].AddYear par The Grib's Lair [Sébastien PICAMELOT - MVP SharePoint] le 07-03-2009, 08:45

- Clinique INSIA - Projet de fin d’Etudes (Silverlight 3 MVVM et OutOfBrowser, WCF, TFS) - Part 1 par David REI le 07-02-2009, 23:38

- C’est la crise ? Bah pourquoi cramer du budget pub alors ? par Nix's Blog le 07-02-2009, 15:31

- Soyons MVP ! par TheSaib .NET blog le 07-02-2009, 12:15

- SharePoint : Gestion des Erreurs 6398, 7076 et 6482 par Blog Technique de Romelard Fabrice le 07-02-2009, 11:53

- EF avec WPF par Matthieu MEZIL le 07-02-2009, 10:18