Share via


Procedura dettagliata: hosting di controlli compositi di WPF in Windows Form

Windows Presentation Foundation (WPF) fornisce un ambiente funzionale per la creazione di applicazioni. Tuttavia, quando si dispone di una grande quantità di codice Windows Forms, può essere opportuno estendere l'applicazione Windows Forms esistente con WPF anziché riscriverla dall'inizio. Uno scenario comune è dato dalla situazione in cui si desidera incorporare uno o più controlli implementati con WPF all'interno dell'applicazione Windows Forms. Per ulteriori informazioni sulla personalizzazione dei controlli WPF, vedere Personalizzazione dei controlli.

In questa procedura dettagliata viene descritta un'applicazione che ospita un controllo composito WPF per eseguire l'immissione di dati in un'applicazione Windows Forms. Il controllo composito è compresso in una DLL. Questa procedura generale può essere estesa ad applicazioni e controlli più complessi. Questa procedura dettagliata è stata progettata in modo che risulti quasi identica per aspetto e funzionalità a Procedura dettagliata: hosting di controlli Windows Form compositi in WPF. La differenza primaria risiede nel fatto che lo scenario di hosting risulta invertito.

La procedura dettagliata è divisa in due sezioni. Nella prima sezione viene brevemente descritta l'implementazione del controllo composito WPF. Nella seconda sezione viene illustrato in dettaglio come ospitare il controllo composito in un'applicazione Windows Forms, come ricevere eventi dal controllo e come accedere ad alcune delle proprietà del controllo.

Di seguito vengono elencate le attività illustrate nella procedura dettagliata:

  • Implementazione del controllo composito WPF.

  • Implementazione dell'applicazione host Windows Form.

Per un elenco di codice completo delle attività illustrate in questa procedura dettagliata, vedere Esempio di hosting di controlli compositi di WPF in Windows Form (la pagina potrebbe essere in inglese).

Prerequisiti

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

  • Visual Studio 2010.

Implementazione del controllo composito WPF.

Il controllo composito WPF utilizzato in questo esempio è un semplice form di immissione dati che accetta il nome e l'indirizzo dell'utente. Quando l'utente fa clic su uno di due pulsanti per indicare che l'attività è terminata, il controllo genera un evento personalizzato per la restituzione delle informazioni all'host. Nell’immagine riportata di seguito viene illustrato il controllo sottoposto a rendering.

Controllo composito WPF

Controllo WPF semplice

Creazione del progetto

Per avviare il progetto:

  1. Avviare Microsoft Visual Studio e aprire la finestra di dialogo Nuovo progetto.

  2. Nella categoria Visual C# e Windows, selezionare il modello Libreria di controlli utente WPF.

  3. Denominare il nuovo progetto MyControls.

  4. Come posizione, specificare una cartella di livello principale denominata in modo appropriato, ad esempio WindowsFormsHostingWpfControl. Successivamente, l'applicazione host verrà posizionata in questa cartella.

  5. Scegliere OK per creare il progetto. Il progetto predefinito contiene un singolo controllo denominato UserControl1.

  6. In Esplora soluzioni rinominare UserControl1 in MyControl1.

Il progetto dovrebbe presentare riferimenti alle DLL di sistema riportate di seguito. Se alcune di queste DLL non sono incluse per impostazione predefinita, aggiungerle al progetto.

  • PresentationCore

  • PresentationFramework

  • Sistema

  • WindowsBase

Creazione dell'interfaccia utente

L'user interface (UI) per il controllo composito è implementata con Extensible Application Markup Language (XAML). Il controllo composito UI è costituito da cinque elementi TextBox. A ogni elemento TextBox è associato un elemento TextBlock con funzione di etichetta. Nella parte inferiore sono presenti due elementi Button, OK e Cancel. Quando l'utente fa clic su uno dei due pulsanti, il controllo genera un evento personalizzato per la restituzione delle informazioni all'host.

Layout di base

I vari elementi dell'UI sono contenuti in un elemento Grid. È possibile utilizzare Grid per disporre il contenuto del controllo composito in modo molto simile a come si utilizzerebbe un elemento Table nel codice HTML. In WPF è inoltre disponibile un elemento Table, ma Grid rappresenta un'alternativa più semplice e più appropriata per semplici attività di layout.

Nel codice XAML seguente viene mostrato il layout di base. Questo codice XAML definisce la struttura complessiva del controllo specificando il numero di colonne e di righe dell'elemento Grid.

In MyControl1.xaml sostituire il codice XAML esistente con il seguente :

<Grid xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="MyControls.MyControl1"
      Background="#DCDCDC"
      Width="375"
      Height="250"
      Name="rootElement"
      Loaded="Init">

  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="Auto"/>
  </Grid.ColumnDefinitions>

  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>


...


</Grid>

Aggiunta di elementi TextBlock e TextBox alla griglia

Un elemento dell'UI viene posizionato nella griglia impostando gli attributi RowProperty e ColumnProperty dell'elemento sul numero di righe e colonne appropriato. Ricordare che la numerazione delle righe e delle colonne è in base zero. Affinché un elemento occupi più colonne è necessario impostare il relativo attributo ColumnSpanProperty. Per ulteriori informazioni sugli elementi Grid, vedere Procedura: creare un elemento Grid.

Nel codice XAML seguente sono riportati gli elementi TextBox e TextBlock del controllo composito con i relativi attributi RowProperty e ColumnProperty, impostati per inserire correttamente gli elementi nella griglia.

In MyControl1.xaml, aggiungere il codice XAML seguente all'interno dell'elemento Grid.

<TextBlock Grid.Column="0"
      Grid.Row="0" 
      Grid.ColumnSpan="4"
      Margin="10,5,10,0"
      HorizontalAlignment="Center"
      Style="{StaticResource titleText}">Simple WPF Control</TextBlock>

<TextBlock Grid.Column="0"
      Grid.Row="1"
      Style="{StaticResource inlineText}"
      Name="nameLabel">Name</TextBlock>
<TextBox Grid.Column="1"
      Grid.Row="1"
      Grid.ColumnSpan="3"
      Name="txtName"/>

<TextBlock Grid.Column="0"
      Grid.Row="2"
      Style="{StaticResource inlineText}"
      Name="addressLabel">Street Address</TextBlock>
<TextBox Grid.Column="1"
      Grid.Row="2"
      Grid.ColumnSpan="3"
      Name="txtAddress"/>

<TextBlock Grid.Column="0"
      Grid.Row="3"
      Style="{StaticResource inlineText}"
      Name="cityLabel">City</TextBlock>
<TextBox Grid.Column="1"
      Grid.Row="3"
      Width="100"
      Name="txtCity"/>

<TextBlock Grid.Column="2"
      Grid.Row="3"
      Style="{StaticResource inlineText}"
      Name="stateLabel">State</TextBlock>
<TextBox Grid.Column="3"
      Grid.Row="3"
      Width="50"
      Name="txtState"/>

<TextBlock Grid.Column="0"
      Grid.Row="4"
      Style="{StaticResource inlineText}"
      Name="zipLabel">Zip</TextBlock>
<TextBox Grid.Column="1"
      Grid.Row="4"
      Width="100"
      Name="txtZip"/>

Applicazione di uno stile agli elementi dell'interfaccia utente

Molti degli elementi del form di immissione dati sono simili nell'aspetto, il che significa che presentano impostazioni identiche per molte delle loro proprietà. Anziché impostare separatamente gli attributi di ciascun elemento, il codice XAML precedente utilizza gli elementi Style per definire impostazioni delle proprietà standard per classi di elementi. In questo modo, è possibile ridurre la complessità del controllo e modificare l'aspetto di più elementi attraverso un singolo attributo di stile.

Poiché gli elementi Style sono contenuti nella proprietà Resources dell'elemento Grid, possono essere utilizzati da tutti gli elementi nel controllo. Se a uno stile è stato assegnato un nome, per applicarlo a un elemento aggiungere un elemento Style impostato sul nome dello stile. Gli stili a cui non è stato assegnato alcun nome diventano lo stile predefinito dell'elemento. Per ulteriori informazioni sugli stili WPF, vedere Applicazione di stili e modelli.

Nel codice XAML seguente vengono illustrati gli elementi Style per il controllo composito. Per vedere come gli stili vengono applicati agli elementi, vedere il codice XAML precedente. Ad esempio, l'ultimo elemento TextBlock presenta lo stile inlineText, mentre l'ultimo elemento TextBox utilizza lo stile predefinito.

In MyControl1.xaml, aggiungere il codice XAML seguente immediatamente dopo l'elemento Grid iniziale.

<Grid.Resources>
  <Style x:Key="inlineText" TargetType="{x:Type TextBlock}">
    <Setter Property="Margin" Value="10,5,10,0"/>
    <Setter Property="FontWeight" Value="Normal"/>
    <Setter Property="FontSize" Value="12"/>
  </Style>
  <Style x:Key="titleText" TargetType="{x:Type TextBlock}">
    <Setter Property="DockPanel.Dock" Value="Top"/>
    <Setter Property="FontWeight" Value="Bold"/>
    <Setter Property="FontSize" Value="14"/>
    <Setter Property="Margin" Value="10,5,10,0"/>
  </Style>
  <Style TargetType="{x:Type Button}">
    <Setter Property="Margin" Value="10,5,10,0"/>
    <Setter Property="Width" Value="60"/>
  </Style>
  <Style TargetType="{x:Type TextBox}">
    <Setter Property="Margin" Value="10,5,10,0"/>
  </Style>
</Grid.Resources>

Aggiunta dei pulsanti OK e Annulla

Gli elementi finali del controllo composito sono gli elementi Button OK e Annulla, i quali occupano le prime due colonne dell'ultima riga dell'elemento Grid. Questi elementi utilizzano un gestore eventi comune, ButtonClicked, e lo stile Button predefinito definito nel codice XAML precedente.

In MyControl1.xaml, aggiungere il codice XAML seguente dopo l'ultimo elemento TextBox. La parte XAML del controllo composito è ora completata.

<Button Grid.Row="5"
        Grid.Column="0"
        Name="btnOK"
        Click="ButtonClicked">OK</Button>
<Button Grid.Row="5"
        Grid.Column="1"
        Name="btnCancel"
        Click="ButtonClicked">Cancel</Button>

Implementazione del file code-behind

Nel file code-behind, MyControl1.xaml.cs, sono implementate tre attività essenziali:

  1. Gestione dell'evento che si verifica quando l'utente fa clic su uno dei pulsanti.

  2. Recupero dei dati dagli elementi TextBox e relativo assemblaggio in un oggetto argomento dell'evento personalizzato.

  3. Generazione dell'evento OnButtonClick personalizzato che notifica all'host la fine dell'operazione dell'utente e conseguente passaggio dei dati all'host.

Il controllo espone inoltre alcune proprietà di colori e tipi di carattere che consentono di modificare l'aspetto della pagina. A differenza della classe WindowsFormsHost, utilizzata per l'hosting di un controllo Windows Forms, la classe ElementHost espone unicamente la proprietà Background del controllo. Per mantenere le similitudini tra questo esempio di codice e quello illustrato nella Procedura dettagliata: hosting di controlli Windows Form compositi in WPF, il controllo espone direttamente le proprietà rimanenti.

Struttura di base del file code-behind

Il file code-behind è costituito da un singolo spazio dei nomi, MyControls, che conterrà due classi, MyControl1 e MyControlEventArgs.

namespace MyControls
{
  public partial class MyControl1 : Grid
  {
    //...
  }
  public class MyControlEventArgs : EventArgs
  {
    //...
  }
}

La prima classe, MyControl1, è una classe parziale che contiene il codice che implementa la funzionalità dell'UI definita in MyControl1.xaml. Quando viene analizzato il file MyControl1.xaml, il codice XAML viene convertito nella stessa classe parziale e le due classi parziali vengono unite per formare il controllo compilato. Per questo motivo, il nome della classe nel file code-behind deve corrispondere al nome della classe assegnato a MyControl1.xaml e deve ereditare dall'elemento radice del controllo. La seconda classe, MyControlEventArgs, è una classe di argomenti degli eventi che consente di reinviare i dati all'host.

Aprire il file MyControl1.xaml.cs. Modificare la dichiarazione di classe esistente in modo che abbia il seguente nome e erediti da Grid.

public partial class MyControl1 : Grid

Inizializzazione del controllo

Nel codice riportato di seguito vengono implementate diverse attività di base:

  • Dichiarazione di un evento privato, OnButtonClick, e del delegato associato, MyControlEventHandler.

  • Creazione di molteplici variabili globali private per l'archiviazione dei dati dell'utente. Questi dati vengono esposti tramite proprietà corrispondenti.

  • Implementazione di un gestore, Init, per l'evento Loaded del controllo. Questo gestore inizializza le variabili globali assegnando ad esse i valori definiti in MyControl1.xaml. A tale scopo, utilizza la proprietà Name assegnata a un elemento TextBlock tipico, nameLabel, per accedere alle impostazioni delle proprietà di quell'elemento.

Eliminare il costruttore esistente e aggiungere il codice seguente alla classe MyControl1.

public delegate void MyControlEventHandler(object sender, MyControlEventArgs args);
public event MyControlEventHandler OnButtonClick;
private FontWeight _fontWeight;
private double _fontSize;
private FontFamily _fontFamily;
private FontStyle _fontStyle;
private SolidColorBrush _foreground;
private SolidColorBrush _background;

private void Init(object sender, EventArgs e)
{
    //They all have the same style, so use nameLabel to set initial values.
    _fontWeight = nameLabel.FontWeight;
    _fontSize = nameLabel.FontSize;
    _fontFamily = nameLabel.FontFamily;
    _fontStyle = nameLabel.FontStyle;
    _foreground = (SolidColorBrush)nameLabel.Foreground;
    _background = (SolidColorBrush)rootElement.Background;
}

Gestione degli eventi Click dei pulsanti

L'utente indica il termine dell'attività di immissione dati facendo clic sul pulsante OK o Annulla nella parte inferiore. Entrambi i pulsanti utilizzano lo stesso gestore dell'evento Click, ButtonClicked. A entrambi i pulsanti è stato assegnato un nome, btnOK o btnCancel, attraverso il quale il gestore è in grado di determinare su quale pulsante è stato fatto clic esaminando il valore dell'argomento sender. Tramite il gestore è possibile eseguire le attività riportate di seguito:

  • Creazione di un oggetto MyControlEventArgs che contiene i dati degli elementi TextBox.

  • Se l'utente fa clic sul pulsante Annulla, imposta la proprietà IsOK dell'oggetto MyControlEventArgs su false.

  • Generazione dell'evento OnButtonClick per indicare all'host la fine delle operazioni dell'utente e il passaggio dei dati raccolti all'host stesso.

Aggiungere il codice seguente alla classe MyControl1, dopo il metodo Init.

private void ButtonClicked(object sender, RoutedEventArgs e)
{
    MyControlEventArgs retvals = new MyControlEventArgs(true,
                                                        txtName.Text,
                                                        txtAddress.Text,
                                                        txtCity.Text,
                                                        txtState.Text,
                                                        txtZip.Text);
    if (sender == btnCancel)
    {
        retvals.IsOK = false;
    }
    if (OnButtonClick != null)
        OnButtonClick(this, retvals);
}

Creazione di proprietà

La parte restante della classe espone semplicemente le proprietà che corrispondono alle variabili globali descritte in precedenza. Quando una proprietà viene modificata, la funzione di accesso set modifica l'aspetto del controllo modificando le proprietà dell'elemento corrispondente e aggiornando le variabili globali sottostanti.

Aggiungere il codice riportato di seguito alla classe MyControl1.

public FontWeight MyControl_FontWeight
{
    get { return _fontWeight; }
    set
    {
        _fontWeight = value;
        nameLabel.FontWeight = value;
        addressLabel.FontWeight = value;
        cityLabel.FontWeight = value;
        stateLabel.FontWeight = value;
        zipLabel.FontWeight = value;
    }
}
public double MyControl_FontSize
{
    get { return _fontSize; }
    set
    {
        _fontSize = value;
        nameLabel.FontSize = value;
        addressLabel.FontSize = value;
        cityLabel.FontSize = value;
        stateLabel.FontSize = value;
        zipLabel.FontSize = value;
    }
}
public FontStyle MyControl_FontStyle
{
    get { return _fontStyle; }
    set
    {
        _fontStyle = value;
        nameLabel.FontStyle = value;
        addressLabel.FontStyle = value;
        cityLabel.FontStyle = value;
        stateLabel.FontStyle = value;
        zipLabel.FontStyle = value;
    }
}
public FontFamily MyControl_FontFamily
{
    get { return _fontFamily; }
    set
    {
        _fontFamily = value;
        nameLabel.FontFamily = value;
        addressLabel.FontFamily = value;
        cityLabel.FontFamily = value;
        stateLabel.FontFamily = value;
        zipLabel.FontFamily = value;
    }
}

public SolidColorBrush MyControl_Background
{
    get { return _background; }
    set
    {
        _background = value;
        rootElement.Background = value;
    }
}
public SolidColorBrush MyControl_Foreground
{
    get { return _foreground; }
    set
    {
        _foreground = value;
        nameLabel.Foreground = value;
        addressLabel.Foreground = value;
        cityLabel.Foreground = value;
        stateLabel.Foreground = value;
        zipLabel.Foreground = value;
    }
}

Reinvio dei dati all'host

Il componente finale del file è la classe MyControlEventArgs utilizzata per reinviare i dati raccolti all'host.

Aggiungere il codice riportato di seguito allo spazio dei nomi MyControls: L'implementazione non presenta particolari difficoltà e non verrà trattata ulteriormente.

public class MyControlEventArgs : EventArgs
{
    private string _Name;
    private string _StreetAddress;
    private string _City;
    private string _State;
    private string _Zip;
    private bool _IsOK;

    public MyControlEventArgs(bool result,
                              string name,
                              string address,
                              string city,
                              string state,
                              string zip)
    {
        _IsOK = result;
        _Name = name;
        _StreetAddress = address;
        _City = city;
        _State = state;
        _Zip = zip;
    }

    public string MyName
    {
        get { return _Name; }
        set { _Name = value; }
    }
    public string MyStreetAddress
    {
        get { return _StreetAddress; }
        set { _StreetAddress = value; }
    }
    public string MyCity
    {
        get { return _City; }
        set { _City = value; }
    }
    public string MyState
    {
        get { return _State; }
        set { _State = value; }
    }
    public string MyZip
    {
        get { return _Zip; }
        set { _Zip = value; }
    }
    public bool IsOK
    {
        get { return _IsOK; }
        set { _IsOK = value; }
    }
}

Compilare la soluzione. La compilazione creerà una DLL denominata MyControls.dll.

Implementazione dell'applicazione host Windows Form

L'applicazione host Windows Forms utilizza un oggetto ElementHost per l'hosting del controllo composito WPF. L'applicazione gestisce l'evento OnButtonClick per ricevere i dati dal controllo composito. Nell'applicazione è inoltre disponibile un insieme di pulsanti di opzione utilizzabili per modificare l'aspetto del controllo. Di seguito viene illustrata l'applicazione.

Controllo composito WPF ospitato in un'applicazione Windows Form

Windows Form che ospita un controllo Avalon

Creazione del progetto

Per avviare il progetto:

  1. Avviare Visual Studio e aprire la finestra di dialogo Nuovo progetto.

  2. Nella categoria Visual C# e Windows, selezionare il modello Applicazione Windows Form.

  3. Denominare il nuovo progetto WFHost.

  4. Come posizione, specificare la stessa cartella di livello principale che contiene il progetto MyControls.

  5. Scegliere OK per creare il progetto.

È inoltre necessario aggiungere riferimenti alla DLL che contiene MyControl1 e altri assembly.

  1. Fare clic con il pulsante destro del mouse in Esplora soluzioni e selezionare Aggiungi riferimento.

  2. Fare clic sulla scheda Sfoglia e passare alla cartella che contiene MyControls.dll. In questa procedura dettagliata, questa cartella è MyControls\bin\Debug.

  3. Selezionare MyControls.dll, quindi scegliere OK.

  4. Aggiungere riferimenti agli assembly riportati di seguito.

    • PresentationCore

    • PresentationFramework

    • System.Xaml

    • WindowsBase

    • WindowsFormsIntegration

Implementazione dell'interfaccia utente per l'applicazione

L'interfaccia utente per l'applicazione Windows Form contiene diversi controlli per interagire con il controllo composito WPF.

  1. In Progettazione Windows Form aprire Form1.

  2. Ingrandire il form affinché possa contenere i controlli.

  3. Nell'angolo superiore destro del form aggiungere un controllo System.Windows.Forms.Panel per contenere il controllo composito WPF.

  4. Aggiungere i controlli System.Windows.Forms.GroupBox seguenti al form.

    Nome

    Text

    groupBox1

    Colore di sfondo

    groupBox2

    Foreground Color

    groupBox3

    Font Size

    groupBox4

    Font Family

    groupBox5

    Stile

    groupBox6

    Font Weight

    groupBox7

    Data from control

  5. Aggiungere i controlli System.Windows.Forms.RadioButton seguenti ai controlli System.Windows.Forms.GroupBox.

    GroupBox

    Nome

    Text

    groupBox1

    radioBackgroundOriginal

    Originale

    groupBox1

    radioBackgroundLightGreen

    LightGreen

    groupBox1

    radioBackgroundLightSalmon

    LightSalmon

    groupBox2

    radioForegroundOriginal

    Originale

    groupBox2

    radioForegroundRed

    Rosso

    groupBox2

    radioForegroundYellow

    Yellow

    groupBox3

    radioSizeOriginal

    Originale

    groupBox3

    radioSizeTen

    10

    groupBox3

    radioSizeTwelve

    12

    groupBox4

    radioFamilyOriginal

    Originale

    groupBox4

    radioFamilyTimes

    Times New Roman

    groupBox4

    radioFamilyWingDings

    WingDings

    groupBox5

    radioStyleOriginal

    Normal

    groupBox5

    radioStyleItalic

    Italic

    groupBox6

    radioWeightOriginal

    Originale

    groupBox6

    radioWeightBold

    Grassetto

  6. Aggiungere i controlli System.Windows.Forms.Label seguenti all'ultimo System.Windows.Forms.GroupBox. Questi controlli visualizzano i dati restituiti dal controllo composito WPF.

    GroupBox

    Nome

    Text

    groupBox7

    lblName

    Name:

    groupBox7

    lblAddress

    Street Address:

    groupBox7

    lblCity

    City:

    groupBox7

    lblState

    State:

    groupBox7

    lblZip

    Zip:

Inizializzazione del form

Il codice di hosting viene in genere implementato nel gestore dell'evento Load del form. Nel codice seguente sono riportati il gestore dell'evento Load, un gestore per l'evento Loaded del controllo composito WPF e dichiarazioni per molteplici variabili globali che verranno utilizzate in un secondo momento.

In Progettazione Windows Form fare doppio clic sul form per creare un gestore dell'evento Load. Nella parte superiore di Form1.cs, aggiungere le istruzioni using seguenti.

using System;
using System.Windows;
using System.Windows.Navigation;
using System.Windows.Controls;
using System.Windows.Media;

namespace MyControls
{
    public partial class MyControl1 : Grid
    {
        public delegate void MyControlEventHandler(object sender, MyControlEventArgs args);
        public event MyControlEventHandler OnButtonClick;
        private FontWeight _fontWeight;
        private double _fontSize;
        private FontFamily _fontFamily;
        private FontStyle _fontStyle;
        private SolidColorBrush _foreground;
        private SolidColorBrush _background;

        private void Init(object sender, EventArgs e)
        {
            //They all have the same style, so use nameLabel to set initial values.
            _fontWeight = nameLabel.FontWeight;
            _fontSize = nameLabel.FontSize;
            _fontFamily = nameLabel.FontFamily;
            _fontStyle = nameLabel.FontStyle;
            _foreground = (SolidColorBrush)nameLabel.Foreground;
            _background = (SolidColorBrush)rootElement.Background;
        }

        private void ButtonClicked(object sender, RoutedEventArgs e)
        {
            MyControlEventArgs retvals = new MyControlEventArgs(true,
                                                                txtName.Text,
                                                                txtAddress.Text,
                                                                txtCity.Text,
                                                                txtState.Text,
                                                                txtZip.Text);
            if (sender == btnCancel)
            {
                retvals.IsOK = false;
            }
            if (OnButtonClick != null)
                OnButtonClick(this, retvals);
        }

        public FontWeight MyControl_FontWeight
        {
            get { return _fontWeight; }
            set
            {
                _fontWeight = value;
                nameLabel.FontWeight = value;
                addressLabel.FontWeight = value;
                cityLabel.FontWeight = value;
                stateLabel.FontWeight = value;
                zipLabel.FontWeight = value;
            }
        }
        public double MyControl_FontSize
        {
            get { return _fontSize; }
            set
            {
                _fontSize = value;
                nameLabel.FontSize = value;
                addressLabel.FontSize = value;
                cityLabel.FontSize = value;
                stateLabel.FontSize = value;
                zipLabel.FontSize = value;
            }
        }
        public FontStyle MyControl_FontStyle
        {
            get { return _fontStyle; }
            set
            {
                _fontStyle = value;
                nameLabel.FontStyle = value;
                addressLabel.FontStyle = value;
                cityLabel.FontStyle = value;
                stateLabel.FontStyle = value;
                zipLabel.FontStyle = value;
            }
        }
        public FontFamily MyControl_FontFamily
        {
            get { return _fontFamily; }
            set
            {
                _fontFamily = value;
                nameLabel.FontFamily = value;
                addressLabel.FontFamily = value;
                cityLabel.FontFamily = value;
                stateLabel.FontFamily = value;
                zipLabel.FontFamily = value;
            }
        }

        public SolidColorBrush MyControl_Background
        {
            get { return _background; }
            set
            {
                _background = value;
                rootElement.Background = value;
            }
        }
        public SolidColorBrush MyControl_Foreground
        {
            get { return _foreground; }
            set
            {
                _foreground = value;
                nameLabel.Foreground = value;
                addressLabel.Foreground = value;
                cityLabel.Foreground = value;
                stateLabel.Foreground = value;
                zipLabel.Foreground = value;
            }
        }
    }

    public class MyControlEventArgs : EventArgs
    {
        private string _Name;
        private string _StreetAddress;
        private string _City;
        private string _State;
        private string _Zip;
        private bool _IsOK;

        public MyControlEventArgs(bool result,
                                  string name,
                                  string address,
                                  string city,
                                  string state,
                                  string zip)
        {
            _IsOK = result;
            _Name = name;
            _StreetAddress = address;
            _City = city;
            _State = state;
            _Zip = zip;
        }

        public string MyName
        {
            get { return _Name; }
            set { _Name = value; }
        }
        public string MyStreetAddress
        {
            get { return _StreetAddress; }
            set { _StreetAddress = value; }
        }
        public string MyCity
        {
            get { return _City; }
            set { _City = value; }
        }
        public string MyState
        {
            get { return _State; }
            set { _State = value; }
        }
        public string MyZip
        {
            get { return _Zip; }
            set { _Zip = value; }
        }
        public bool IsOK
        {
            get { return _IsOK; }
            set { _IsOK = value; }
        }
    }
}
using System.Windows;
using System.Windows.Forms.Integration;
using System.Windows.Media;

Sostituire il contenuto della classe Form1 esistente con il codice riportato di seguito.

private ElementHost ctrlHost;
private MyControls.MyControl1 wpfAddressCtrl;
System.Windows.FontWeight initFontWeight;
double initFontSize;
System.Windows.FontStyle initFontStyle;
System.Windows.Media.SolidColorBrush initBackBrush;
System.Windows.Media.SolidColorBrush initForeBrush;
System.Windows.Media.FontFamily initFontFamily;

public Form1()
{
    InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
    ctrlHost = new ElementHost();
    ctrlHost.Dock = DockStyle.Fill;
    panel1.Controls.Add(ctrlHost);
    wpfAddressCtrl = new MyControls.MyControl1();
    wpfAddressCtrl.InitializeComponent();
    ctrlHost.Child = wpfAddressCtrl;

    wpfAddressCtrl.OnButtonClick +=
        new MyControls.MyControl1.MyControlEventHandler(
        avAddressCtrl_OnButtonClick);
    wpfAddressCtrl.Loaded += new RoutedEventHandler(
        avAddressCtrl_Loaded);
}

void avAddressCtrl_Loaded(object sender, EventArgs e)
{
    initBackBrush = (SolidColorBrush)wpfAddressCtrl.MyControl_Background;
    initForeBrush = wpfAddressCtrl.MyControl_Foreground;
    initFontFamily = wpfAddressCtrl.MyControl_FontFamily;
    initFontSize = wpfAddressCtrl.MyControl_FontSize;
    initFontWeight = wpfAddressCtrl.MyControl_FontWeight;
    initFontStyle = wpfAddressCtrl.MyControl_FontStyle;
}

Il metodo Form1_Load nel codice precedente mostra la procedura generale per l'hosting di un controllo WPF:

  1. Creare un nuovo oggetto ElementHost.

  2. Impostare la proprietà Dock del controllo su DockStyle.Fill.

  3. Aggiungere il controllo ElementHost all'insieme Controlsdel controllo Panel.

  4. Creare un'istanza del controllo WPF.

  5. Ospitare il controllo composito nel form assegnando il controllo alla proprietà Child del controllo ElementHost.

Le due righe rimanenti nel metodo Form1_Load associano i gestori a due eventi del controllo:

  • OnButtonClick è un evento personalizzato che viene generato dal controllo composito quando l'utente fa clic sul pulsante OK o Annulla. L'evento deve essere gestito per ottenere la risposta dell'utente e per raccogliere i dati specificati.

  • Loaded è un evento standard che viene generato da un controllo WPF dopo essere stato caricato completamente. L'evento viene utilizzato perché nell'esempio è necessario inizializzare molteplici variabili globali utilizzando le proprietà del controllo. Al momento dell'evento Load del form, il controllo non è ancora caricato completamente e quei valori sono ancora impostati su null. Per poter accedere a queste proprietà, è necessario attendere che si verifichi l'evento Loaded del controllo.

Il gestore dell'evento Loaded viene descritto nel codice precedente. Il gestore OnButtonClick viene descritto nella sezione successiva.

Gestione di OnButtonClick

L'evento OnButtonClick si verifica quando l'utente fa clic sul pulsante OK o Annulla.

Il gestore eventi controlla il campo IsOK dell'argomento dell'evento per determinare su quale pulsante è stato fatto clic. Le variabili lbldati corrispondono ai controlli Label descritti in precedenza. Se l'utente fa clic sul pulsante OK, i dati dei controlli TextBox del controllo vengono assegnati al controllo Label corrispondente. Se l'utente fa clic su Cancel, i valori di Text vengono impostati sulle stringhe predefinite.

Aggiungere il codice del gestore dell'evento clic sul pulsante alla classe Form1.

void avAddressCtrl_OnButtonClick(
    object sender,
    MyControls.MyControl1.MyControlEventArgs args)
{
    if (args.IsOK)
    {
        lblAddress.Text = "Street Address: " + args.MyStreetAddress;
        lblCity.Text = "City: " + args.MyCity;
        lblName.Text = "Name: " + args.MyName;
        lblState.Text = "State: " + args.MyState;
        lblZip.Text = "Zip: " + args.MyZip;
    }
    else
    {
        lblAddress.Text = "Street Address: ";
        lblCity.Text = "City: ";
        lblName.Text = "Name: ";
        lblState.Text = "State: ";
        lblZip.Text = "Zip: ";
    }
}

Compilare ed eseguire l'applicazione. Aggiungere testo al controllo composito WPF, quindi scegliere OK. Il testo viene visualizzato nelle etichette. A questo punto, il codice non è stato aggiunto per gestire i pulsanti di opzione.

Modifica dell'aspetto del controllo

I controlli RadioButton presenti nel form consentono all'utente di modificare i colori di sfondo e di primo piano del controllo composito WPF, nonché molte proprietà dei tipi di carattere. Il colore di sfondo è esposto dall'oggetto ElementHost. Le proprietà rimanenti sono esposte come proprietà personalizzate del controllo.

Fare doppio clic su ogni controllo RadioButton nel form per creare gestori per l'evento CheckedChanged. Sostituire i gestori dell'evento CheckedChanged con il codice riportato di seguito.

private void radioBackgroundOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Background = initBackBrush;
}

private void radioBackgroundLightGreen_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Background = new SolidColorBrush(Colors.LightGreen);
}

private void radioBackgroundLightSalmon_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Background = new SolidColorBrush(Colors.LightSalmon);
}

private void radioForegroundOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Foreground = initForeBrush;
}

private void radioForegroundRed_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Foreground = new System.Windows.Media.SolidColorBrush(Colors.Red);
}

private void radioForegroundYellow_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Foreground = new System.Windows.Media.SolidColorBrush(Colors.Yellow);
}

private void radioFamilyOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontFamily = initFontFamily;
}

private void radioFamilyTimes_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontFamily = new System.Windows.Media.FontFamily("Times New Roman");
}

private void radioFamilyWingDings_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontFamily = new System.Windows.Media.FontFamily("WingDings");
}

private void radioSizeOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontSize = initFontSize;
}

private void radioSizeTen_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontSize = 10;
}

private void radioSizeTwelve_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontSize = 12;
}

private void radioStyleOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontStyle = initFontStyle;
}

private void radioStyleItalic_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontStyle = System.Windows.FontStyles.Italic;
}

private void radioWeightOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontWeight = initFontWeight;
}

private void radioWeightBold_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontWeight = FontWeights.Bold;
}

Compilare ed eseguire l'applicazione. Fare clic sui diversi pulsanti di opzione per visualizzare l'effetto sul controllo composito WPF.

Vedere anche

Attività

Procedura dettagliata: hosting di controlli compositi 3D di WPF in Windows Form

Riferimenti

ElementHost

WindowsFormsHost

Concetti

Procedura dettagliata: hosting di controlli Windows Form compositi in WPF

Altre risorse

WPF Designer