Procedura dettagliata: creazione di un editor di categorie

Il modello di estensibilità per WPF Designer per Visual Studio consente di creare editor personalizzati per le categorie di proprietà noti come editor di categorie. Gli editor di categorie consentono di fornire un'interfaccia utente personalizzata che permette agli utenti di modificare le proprietà correlate che appartengono a un'unica categoria, ad esempio le proprietà correlate al testo. In questa procedura dettagliata, viene compilato un editor di categorie che consente agli utenti di modificare le proprietà correlate al testo di un controllo.

Questa procedura dettagliata prevede l'esecuzione delle attività seguenti:

  • Creazione di un progetto di controllo personalizzato WPF.

  • Creazione di un editor di categorie che possa essere utilizzato per modificare le proprietà correlate al testo di quel controllo.

  • Creazione di una classe che eredita dall'oggetto CategoryEditor che rappresenta l'editor di categorie per il controllo.

  • Creazione di una classe che implementa l'interfaccia IProvideAttributeTable per registrare il nuovo editor esteso.

  • Test dell'editor di categorie in fase di progettazione.

Prerequisiti

Per completare la procedura dettagliata, è necessario disporre dei componenti seguenti:

  • Visual Studio 2010.

Creazione del controllo personalizzato

Il primo passaggio consiste nella creazione del progetto per il controllo personalizzato. Il controllo è un semplice pulsante con una piccola quantità di codice Design-Time che utilizza il metodo GetIsInDesignMode per implementare un comportamento in fase di progettazione.

Per creare il controllo personalizzato

  1. In Visual C# creare un nuovo progetto di libreria di controlli personalizzati WPF denominato CustomControlLibrary.

    Il codice per CustomControl1 verrà aperto nell'editor di codice.

  2. Nell'editor del codice per CustomControl1, sostituire il codice nello spazio dei nomi CustomControlLibrary con il codice seguente:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace CustomControlLibrary
    {
        public class CustomControl1 : Button
        {
            public CustomControl1()
            {
                if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
                {
                    Content = "In design mode";
                }
            }
        }
    }
    
  3. Impostare il percorso di output del progetto su "bin\".

  4. Compilare la soluzione.

Creazione di una classe per incapsulare le informazioni sulle proprietà

L'editor di categorie che viene creato, richiede alcune informazioni sui tipi di carattere e sulle proprietà associate, in modo da consentire la creazione di una classe che incapsula tali informazioni e e che sarà utilizzata come origine dati dall'editor di categorie.

Per creare una classe che incapsula le informazioni sulle proprietà dei tipi di carattere

  1. In Visual C# aggiungere alla soluzione un nuovo progetto di libreria di controlli personalizzati WPF denominato CustomControlLibrary.Design.

    Il codice per CustomControl1 verrà aperto nell'editor del codice.

  2. In Esplora soluzioni eliminare il file CustomControl1 dal progetto CustomControlLibrary.Design.

  3. In Esplora soluzioni eliminare la cartella Themes dal progetto CustomControlLibrary.Design.

  4. Aggiungere un riferimento ai seguenti assembly di WPF Designer.

    • Microsoft.Windows.Design.Extensibility

    • Microsoft.Windows.Design.Interaction

  5. Aggiungere un riferimento al progetto CustomControlLibrary.

  6. Impostare il percorso di output del progetto su ".. \CustomControlLibrary\bin\". In questo modo l'assembly del controllo e l'assembly dei metadati verranno mantenuti nella stessa cartella, consentendo l'individuazione di metadati per le finestre di progettazione.

  7. Aggiungere una nuova classe denominata FontList al progetto CustomControlLibrary.Design.

  8. Nell'editor del codice per FontList sostituire il codice generato automaticamente con il codice seguente.

    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;
            }
        }
    
    }
    

Creazione del modello per l'editor di categorie

L'editor di categorie viene creato utilizzando un modello di dati XAML. Si tratta di una semplice interfaccia utente che viene associata a molte proprietà correlate al testo.

Per creare un modello per l'editor di categorie

  1. Aggiungere una nuova classe denominata EditorResources al progetto CustomControlLibrary.Design.

  2. Nell'editor del codice per EditorResources sostituire il codice generato automaticamente con il codice seguente.

    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. Scegliere Aggiungi dizionario risorse dal menu Progetto.

  4. Denominare il file EditorResources.xaml e fare clic su Aggiungi.

  5. In visualizzazione XAML per EditorResources, sostituire il codice XAML generato automaticamente con il codice XAML seguente.

        <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.Interaction"
        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}}" 
                        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. Compilare la soluzione.

Incapsulamento del modello e registrazione dell'editor di categorie

Una volta creato il modello per l'editor di categorie, è necessario creare una classe che eredita l'oggetto CategoryEditor per utilizzare il modello come editor personalizzato ed è necessario registrare il nuovo editor di categorie.

Per incapsulare e registrare l'editor di categorie

  1. Aggiungere una nuova classe denominata TextCategoryEditor al progetto CustomControlLibrary.Design.

  2. Nell'editor del codice per TextCategoryEditor sostituire il codice generato automaticamente con il codice seguente.

    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. Aggiungere una nuova classe denominata Metadata al progetto CustomControlLibrary.Design.

  4. Nell'editor del codice per Metadata sostituire il codice generato automaticamente con il codice seguente.

    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;
    
    // The ProvideMetadata assembly-level attribute indicates to designers
    // that this assembly contains a class that provides an attribute table. 
    [assembly: ProvideMetadata(typeof(CustomControlLibrary.Design.Metadata))]
    
    namespace CustomControlLibrary.Design
    {
        // Container for any general design-time metadata to initialize.
        // Designers look for a type in the design-time assembly that 
        // implements IProvideAttributeTable. If found, designers instantiate 
        // this class and access its AttributeTable property automatically.
        internal class Metadata : IProvideAttributeTable
        {
            // Accessed by the designer to register any design-time metadata.
            public AttributeTable AttributeTable
            {
                get
                {
                    AttributeTableBuilder builder = new AttributeTableBuilder();
                    builder.AddCustomAttributes
                        (typeof(CustomControl1),
                        new EditorAttribute(
                            typeof(TextCategoryEditor), 
                            typeof(TextCategoryEditor)));
                    return builder.CreateTable();
                }
            }
        }
    }
    
  5. Compilare la soluzione.

Test dell'editor di categorie

A questo punto, l'editor di categorie è completo e pronto per l'utilizzo. Resta solo da verificarne il funzionamento. Per il test dell'editor di categorie verrà aggiunta un'applicazione WPF al progetto e il controllo personalizzato all'applicazione WPF; inoltre, verrà osservato il funzionamento dell'editor di categorie.

Per eseguire il test dell'editor di categorie

  1. In Visual C# aggiungere alla soluzione un nuovo progetto di applicazione WPF denominato DemoApplication.

    MainWindow.xaml viene aperto in WPF Designer.

  2. Aggiungere un riferimento al progetto CustomControlLibrary.

  3. In visualizzazione XAML per MainWindow.xaml sostituire il codice XAML generato automaticamente con il codice XAML seguente. Con questo codice XAML vengono aggiunti un riferimento allo spazio dei nomi CustomControlLibrary e il controllo personalizzato CustomControl1. Il pulsante viene visualizzato in visualizzazione Progettazione con il testo per indicare che si trova in modalità progettazione. Se il pulsante non viene visualizzato, può essere necessario fare clic sulla barra informazioni nella parte superiore della finestra di progettazione per ricaricare la visualizzazione.

        <Window x:Class="DemoApplication.MainWindow"
        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. In visualizzazione Progettazione, selezionare il controllo.

  5. Nella finestra Proprietà individuare la categoria Testo.

    Verrà visualizzata un'interfaccia utente per specificare proprietà Text diverse dagli altri controlli. È possibile selezionare un nome e una dimensione per il tipo di carattere dagli elenchi a discesa. È possibile specificare grassetto e corsivo selezionando le caselle di controllo.

  6. Apportare le modifiche alle proprietà rappresentate in questa categoria. Notare che le modifiche vengono riflesse nel controllo.

Vedere anche

Attività

Procedura dettagliata: implementazione di un editor di colori

Procedura: creare un editor di valori

Altre risorse

Creazione di editor personalizzati

Estensibilità di Progettazione WPF