Procédure pas à pas : création d'un éditeur de catégories

Mise à jour : novembre 2007

Le modèle d'extensibilité de Concepteur Windows Presentation Foundation (WPF) pour Visual Studio permet de créer des éditeurs personnalisés pour les catégories de propriétés, appelés "éditeurs de catégories". Grâce aux éditeurs de catégories, vous pouvez fournir une interface utilisateur personnalisée qui permet aux utilisateurs de modifier des propriétés connexes appartenant à une seule catégorie, comme les propriétés liées au texte. Dans cette procédure pas à pas, vous allez générer un éditeur de catégories qui permet aux utilisateurs de modifier les propriétés liées au texte d'un contrôle.

Dans cette procédure pas à pas, vous exécutez les tâches suivantes :

  • créer un projet de contrôle personnalisé WPF ;

  • créer un éditeur de catégories pouvant servir à modifier les propriétés liées au de ce contrôle ;

  • créer une classe qui hérite de CategoryEditor qui représente l'éditeur de catégories pour le contrôle ;

  • créer une classe qui hérite de IRegisterMetadata pour inscrire le nouvel éditeur étendu ;

  • tester l'éditeur de catégories au moment du design.

Composants requis

Les composants suivants sont nécessaires pour exécuter cette procédure pas à pas :

  • Visual Studio 2008.

Création du contrôle personnalisé

La première étape consiste à créer le projet pour le contrôle personnalisé. Le contrôle est un bouton simple avec une petite portion de code au moment du design, qui utilise la méthode GetIsInDesignMode pour implémenter un comportement au moment du design.

Pour créer le contrôle personnalisé

  1. Créez un projet de bibliothèque de contrôles personnalisés WPF dans Visual C# nommé CustomControlLibrary.

    Le code de CustomControl1 s'ouvre dans l'éditeur de code.

  2. Ajoutez une référence à l'assembly du Concepteur WPF suivant.

    • Microsoft.Windows.Design
  3. Dans l'éditeur de code de CustomControl1, remplacez le code dans l'espace de noms CustomControlLibrary par le code suivant :

    public class CustomControl1 : Button
    {
        public CustomControl1()
        {
            if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
            {
                Content = "I'm in design mode";
            }
        }
    }
    
  4. Le chemin de sortie du projet doit être "bin\".

  5. Générez la solution.

Création d'une classe pour encapsuler les informations sur les propriétés

L'éditeur de catégories que vous allez créer nécessite des informations sur les polices et les propriétés associées. Vous allez dès lors créer une classe qui encapsule ces informations. L'éditeur de catégories utilisera cette classe en tant que source de données.

Pour créer une classe qui encapsule des informations sur les propriétés de police

  1. Ajoutez à la solution un nouveau projet de bibliothèque de contrôles personnalisés WPF dans Visual C# nommé CustomControlLibrary.Design.

    Le code de CustomControl1 s'ouvre dans l'éditeur de code.

  2. Dans l'Explorateur de solutions, supprimez le fichier CustomControl1 du projet CustomControlLibrary.Design.

  3. Dans l'Explorateur de solutions, supprimez le dossier Thèmes du projet CustomControlLibrary.Design.

  4. Ajoutez une référence à l'assembly suivant de Concepteur WPF.

    • Microsoft.Windows.Design
  5. Ajoutez une référence au projet CustomControlLibrary.

  6. Le chemin de sortie du projet doit être "..\CustomControlLibrary\bin\". Cela permet de garder l'assembly du contrôle et l'assembly de métadonnées dans le même dossier, ce qui active la découverte de métadonnées pour les concepteurs.

  7. Ajoutez une nouvelle classe nommée FontList au projet CustomControlLibrary.Design.

  8. Dans l'éditeur de code pour FontList, remplacez le code généré automatiquement par le code suivant.

    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.Text;
    using System.Windows.Media;
    using System.Collections.ObjectModel;
    using System.Windows;
    using System.Windows.Data;
    using System.Globalization;
    
    namespace CustomControlLibrary.Design
    {
        public class FontList : ObservableCollection<FontFamily>
        {
            public FontList()
            {
                foreach (FontFamily ff in Fonts.SystemFontFamilies)
                {
                    Add(ff);
                }
            }
        }
    
        public class FontSizeList : ObservableCollection<double>
        {
            public FontSizeList()
            {
                Add(8);
                Add(9);
                Add(10);
                Add(11);
                Add(12);
                Add(14);
                Add(16);
                Add(18);
                Add(20);
            }
        }
    
        public class FontStyleConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                FontStyle fs = (FontStyle)value;
                return fs == FontStyles.Italic;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                if (value != null)
                {
                    bool isSet = (bool)value;
    
                    if (isSet)
                    {
                        return FontStyles.Italic;
                    }
                }
    
                return FontStyles.Normal;
            }
        }
    
        public class FontWeightConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                FontWeight fs = (FontWeight)value;
                return fs == FontWeights.Bold;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                if (value != null)
                {
                    bool isSet = (bool)value;
    
                    if (isSet)
                    {
                        return FontWeights.Bold;
                    }
                }
    
                return FontWeights.Normal;
            }
        }
    
    }
    

Création du modèle pour l'éditeur de catégories

L'éditeur de catégories est créé à l'aide d'un modèle de données XAML. Il s'agit d'une interface utilisateur simple qui crée une liaison avec plusieurs propriétés liées au texte.

Pour créer le modèle pour l'éditeur de catégories

  1. Ajoutez une nouvelle classe nommée EditorResources au projet CustomControlLibrary.Design.

  2. Dans l'éditeur de code pour EditorResources, remplacez le code généré automatiquement par le code suivant.

    namespace CustomControlLibrary.Design
    {
        using System;
        using System.Collections.Generic;
        using System.Text;
        using System.Windows;
        public partial class EditorResources : ResourceDictionary {
            public EditorResources()
                : base()
            {
                InitializeComponent();
            }
        }
    }
    
  3. Dans le menu Projet, cliquez sur Ajouter un dictionnaire de ressources.

  4. Nommez le fichier EditorResources.xaml, puis cliquez sur Ajouter.

  5. Dans l'affichage de EditorResources en mode XAML, remplacez le code XAML généré automatiquement par le code XAML suivant.

    <ResourceDictionary
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:PropertyEditing="clr-namespace:Microsoft.Windows.Design.PropertyEditing;assembly=Microsoft.Windows.Design"
        xmlns:Local="clr-namespace:CustomControlLibrary.Design"
        xmlns:Media="clr-namespace:System.Windows.Media;assembly=PresentationCore"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        x:Class="CustomControlLibrary.Design.EditorResources">
        <Local:FontList x:Key="FontFamilyList"/>
        <Local:FontSizeList x:Key="FontSizeList"/>
        <Local:FontStyleConverter x:Key="FontStyleConverter"/>
        <Local:FontWeightConverter x:Key="FontWeightConverter"/>
        <DataTemplate x:Key="TextCategoryEditorTemplate">
            <StackPanel Margin="5">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="1*"/>
                        <ColumnDefinition Width="50"/>
                    </Grid.ColumnDefinitions>
                    <ComboBox 
                        Grid.Column="0"
                        Margin="2"
                        ItemsSource="{Binding Source={StaticResource FontFamilyList}}" 
                        DisplayMemberPath="FamilyNames.Values[0]"
                        SelectedItem="{Binding [FontFamily].PropertyValue.Value}"/>
                    <ComboBox 
                        Grid.Column="1"
                        Margin="2"
                        ItemsSource="{Binding Source={StaticResource FontSizeList}}"
                        SelectedItem="{Binding [FontSize].PropertyValue.Value}"/>
                </Grid>
                <StackPanel Orientation="Horizontal">
                    <CheckBox 
                        Margin="2"
                        Content="Bold"
                        IsChecked="{Binding Path=[FontWeight].PropertyValue.Value, Converter={StaticResource FontWeightConverter}}"/>
                    <CheckBox 
                        Margin="2"
                        Content="Italic"
                        IsChecked="{Binding Path=[FontStyle].PropertyValue.Value, Converter={StaticResource FontStyleConverter}}"/>
                </StackPanel>
            </StackPanel>
        </DataTemplate>
    </ResourceDictionary>
    
  6. Générez la solution.

Encapsulation du modèle et inscription de l'éditeur de catégories

Après avoir créé le modèle de l'éditeur de catégories, vous devez créer une classe qui hérite de CategoryEditor pour utiliser le modèle en tant qu'éditeur personnalisé. Vous devez également inscrire le nouvel éditeur de catégories.

Pour encapsuler et inscrire votre éditeur de catégories

  1. Ajoutez une nouvelle classe nommée TextCategoryEditor au projet CustomControlLibrary.Design.

  2. Dans l'éditeur de code pour TextCategoryEditor, remplacez le code généré automatiquement par le code suivant.

    namespace CustomControlLibrary.Design {
        using System;
        using System.Collections.Generic;
        using System.Text;
        using System.Windows;
        using System.Windows.Controls;
        using System.Windows.Data;
        using Microsoft.Windows.Design.PropertyEditing;
    
        public class TextCategoryEditor : CategoryEditor {
    
            private EditorResources res = new EditorResources();
            public TextCategoryEditor()
            {
            }
    
            public override bool ConsumesProperty(PropertyEntry property)
            {
                return true;
            }
    
            public override DataTemplate EditorTemplate
            {
                get {
                    return res["TextCategoryEditorTemplate"] as DataTemplate;
                }
            }
    
            public override object GetImage(Size desiredSize)
            {
                return null;
            }
    
            public override string TargetCategory
            {
                get { return "Text"; }
            }
        }
    }
    
  3. Ajoutez une nouvelle classe nommée Metadata au projet CustomControlLibrary.Design.

  4. Dans l'éditeur de code pour Metadata, remplacez le code généré automatiquement par le code suivant.

    namespace CustomControlLibrary.Design
    {
        using System;
        using System.Collections.Generic;
        using System.Text;
        using Microsoft.Windows.Design.Metadata;
        using System.ComponentModel;
        using Microsoft.Windows.Design.PropertyEditing;
        using System.Windows.Media;
        using System.Windows.Controls;
        using System.Windows;
        using CustomControlLibrary;
    
        // Container for any general design-time metadata that we want to initialize.
        // Designers will look for a type in the design-time assembly that implements IRegisterMetadata.
        // If found, they will instantiate it and call its Register() method automatically.
        internal class Metadata : IRegisterMetadata
        {
    
            // Called by the WPF Designer to register any design-time metadata
            public void Register()
            {
                AttributeTableBuilder builder = new AttributeTableBuilder();
                builder.AddCustomAttributes
                    (typeof( CustomControl1), 
                    "Enter text",
                    PropertyValueEditor.CreateEditorAttribute(
                        typeof(TextCategoryEditor)));
                MetadataStore.AddAttributeTable(builder.CreateTable());
            }
        }
    }
    
  5. Générez la solution.

Test de l'éditeur de catégories

Votre éditeur de catégories est à présent terminé et prêt à être utilisé. Il ne reste plus qu'à le tester. Pour tester l'éditeur de catégories, ajoutez une application WPF à votre projet, ajoutez le contrôle personnalisé à votre application WPF et affichez l'éditeur de catégories en action.

Pour tester l'éditeur de catégories

  1. Ajoutez à la solution un nouveau projet d'application WPF dans Visual C# nommé DemoApplication.

    Window1.xaml s'ouvre dans le Concepteur WPF.

  2. Ajoutez une référence au projet CustomControlLibrary.

  3. Dans l'affichage de Window1.xaml en mode XAML, remplacez le code XAML généré automatiquement par le code XAML suivant. Ce code XAML ajoute une référence à l'espace de noms CustomControlLibrary, ainsi que le contrôle personnalisé CustomControl1. Le bouton apparaît en mode Design avec du texte indiquant que ce mode est activé. Si le bouton ne s'affiche pas, il peut s'avérer nécessaire de cliquer sur la barre d'informations, située dans la partie supérieure du concepteur, pour recharger la vue.

    <Window x:Class="DemoApplication.Window1"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300" xmlns:my="clr-namespace:CustomControlLibrary;assembly=CustomControlLibrary">
        <Grid>
            <my:CustomControl1 Margin="30,30,30,30" Name="customControl11"></my:CustomControl1>
        </Grid>
    </Window>
    
  4. En mode Design, sélectionnez le contrôle.

  5. Dans la fenêtre Propriétés, recherchez la catégorie Texte.

    Une interface utilisateur permettant de spécifier des propriétés de texte (Text) s'affiche. Cette interface diffère des autres contrôles. Vous pouvez sélectionner un nom et une taille de police dans les listes déroulantes. Vous pouvez spécifier la mise en forme gras et italique en activant les cases à cocher correspondantes.

  6. Modifiez les propriétés représentées dans cette catégorie. Notez que ces modifications sont répercutées dans le contrôle.

Voir aussi

Tâches

Procédure pas à pas : implémentation d'un éditeur de couleurs

Comment : créer un éditeur de valeurs

Autres ressources

Création d'éditeurs personnalisés

Extensibilité du concepteur WPF