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 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+
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 
A+
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
) 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 
A+
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é:
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:
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é:
Ensuite, j’ai supprimé les fichiers du répertoire et tout est revenu à la normal:
Et le tour est joué 
A+
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:
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+
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 
<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+
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'.

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”:
Puis compiler votre projet. Là, un fichier app.manifest va apparaitre dans le répertoire Properties de votre projet:
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:
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 
A+
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:
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 !
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:
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 
A bientôt pour la suite 
A+
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:
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”:
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 
A+
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:
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+
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):
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 
A+
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 
A+
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”:
Ensuite, il ne reste plus qu’à utiliser la propriété attachée:
En “design time”, on constate que les données sont bien différentes qu’au “runtime”:
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 
Si vous souhaitez vous former à WPF (Windows Presentation Foundation) alors le Coach WPF est là 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 
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 
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+
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é 
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
). 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+
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+
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é 
A+
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 !
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:
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:
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+
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