Procedura: creare un componente aggiuntivo che restituisce un'interfaccia utenteHow to: Create an Add-In That Returns a UI

In questo esempio viene illustrato come creare un componente aggiuntivo che restituisce un Windows Presentation Foundation (WPF) in un host WPFWPF applicazione autonoma.This example shows how to create an add-in that returns a Windows Presentation Foundation (WPF) to a host WPFWPF standalone application.

Il componente aggiuntivo che restituisce un Interfaccia utenteUI vale a dire un WPFWPF controllo utente.The add-in returns a Interfaccia utenteUI that is a WPFWPF user control. Il contenuto del controllo utente è costituito da un unico pulsante che consente di visualizzare una finestra di messaggio.The content of the user control is a single button that, when clicked, displays a message box. Il WPFWPF applicazione autonoma ospita il componente aggiuntivo e lo visualizza il controllo utente, restituito dal componente aggiuntivo, il contenuto della finestra principale dell'applicazione.The WPFWPF standalone application hosts the add-in and displays the user control (returned by the add-in) as the content of the main application window.

PrerequisitiPrerequisites

In questo esempio viene evidenziato il WPFWPF estensioni per il .NET Framework.NET Framework aggiuntivo modello abilitare questo scenario, si presuppone quanto segue:This example highlights the WPFWPF extensions to the .NET Framework.NET Framework add-in model that enable this scenario, and assumes the following:

  • Conoscere il .NET Framework.NET Framework modello del componente aggiuntivo, tra cui sviluppo di pipeline, componenti aggiuntivi e host.Knowledge of the .NET Framework.NET Framework add-in model, including pipeline, add-in, and host development. Se non si ha familiarità con questi concetti, vedere aggiuntivi ed estensibilità.If you are unfamiliar with these concepts, see Add-ins and Extensibility. Per un'esercitazione che illustra l'implementazione di una pipeline, un componente aggiuntivo e un'applicazione host, vedere procedura dettagliata: creazione di un'applicazione estensibile.For a tutorial that demonstrates the implementation of a pipeline, an add-in, and a host application, see Walkthrough: Creating an Extensible Application.

  • Conoscenza del WPFWPF estensioni per il .NET Framework.NET Framework modello del componente aggiuntivo, che è disponibili qui: WPF Add-Ins Overview.Knowledge of the WPFWPF extensions to the .NET Framework.NET Framework add-in model, which can be found here: WPF Add-Ins Overview.

EsempioExample

Per creare un componente aggiuntivo che restituisce un WPFWPF Interfaccia utenteUI richiede codice specifico per ogni segmento della pipeline, il componente aggiuntivo e l'applicazione host.To create an add-in that returns a WPFWPFInterfaccia utenteUI requires specific code for each pipeline segment, the add-in, and the host application.

Implementazione del segmento di pipeline di contrattoImplementing the Contract Pipeline Segment

Un metodo deve essere definito dal contratto per la restituzione di un Interfaccia utenteUI, e il relativo valore restituito deve essere di tipo INativeHandleContract.A method must be defined by the contract for returning a Interfaccia utenteUI, and its return value must be of type INativeHandleContract. Questo viene dimostrato la GetAddInUI metodo il IWPFAddInContract contratto nel codice seguente.This is demonstrated by the GetAddInUI method of the IWPFAddInContract contract in the following code.

using System.AddIn.Contract;
using System.AddIn.Pipeline;

namespace Contracts
{
    /// <summary>
    /// Defines the services that an add-in will provide to a host application
    /// </summary>
    [AddInContract]
    public interface IWPFAddInContract : IContract
    {
        // Return a UI to the host application
        INativeHandleContract GetAddInUI();
    }
}

Imports System.AddIn.Contract
Imports System.AddIn.Pipeline

Namespace Contracts
	''' <summary>
	''' Defines the services that an add-in will provide to a host application
	''' </summary>
	<AddInContract>
	Public Interface IWPFAddInContract
		Inherits IContract
		' Return a UI to the host application
		Function GetAddInUI() As INativeHandleContract
	End Interface
End Namespace

Implementazione del segmento di pipeline di visualizzazione componente aggiuntivoImplementing the Add-In View Pipeline Segment

Poiché il componente aggiuntivo implementa il Interfacce utenteUIs fornite come sottoclassi di FrameworkElement, il metodo nella vista è correlata a IWPFAddInView.GetAddInUI deve restituire un valore di tipo FrameworkElement.Because the add-in implements the Interfacce utenteUIs it provides as subclasses of FrameworkElement, the method on the add-in view that correlates to IWPFAddInView.GetAddInUI must return a value of type FrameworkElement. Il codice seguente illustra la visualizzazione componente aggiuntivo del contratto, implementata come interfaccia.The following code shows the add-in view of the contract, implemented as an interface.

using System.AddIn.Pipeline;
using System.Windows;

namespace AddInViews
{
    /// <summary>
    /// Defines the add-in's view of the contract
    /// </summary>
    [AddInBase]
    public interface IWPFAddInView
    {
        // The add-in's implementation of this method will return
        // a UI type that directly or indirectly derives from 
        // FrameworkElement.
        FrameworkElement GetAddInUI();
    }
}

Imports System.AddIn.Pipeline
Imports System.Windows

Namespace AddInViews
	''' <summary>
	''' Defines the add-in's view of the contract
	''' </summary>
	<AddInBase>
	Public Interface IWPFAddInView
		' The add-in's implementation of this method will return
		' a UI type that directly or indirectly derives from 
		' FrameworkElement.
		Function GetAddInUI() As FrameworkElement
	End Interface
End Namespace

Implementazione del segmento di pipeline dell'adattatore sul lato del componente aggiuntivoImplementing the Add-In-Side Adapter Pipeline Segment

Il metodo del contratto restituisce un INativeHandleContract, ma il componente aggiuntivo restituisce un FrameworkElement (come specificato da parte della vista del componente aggiuntivo).The contract method returns an INativeHandleContract, but the add-in returns a FrameworkElement (as specified by the add-in view). Di conseguenza, il FrameworkElement deve essere convertito in un INativeHandleContract prima di oltrepassare il limite di isolamento.Consequently, the FrameworkElement must be converted to an INativeHandleContract before crossing the isolation boundary. Questa operazione viene eseguita dall'adapter sul lato componente-chiamando ViewToContractAdapter, come illustrato nel codice seguente.This work is performed by the add-in-side adapter by calling ViewToContractAdapter, as shown in the following code.

using System.AddIn.Contract;
using System.AddIn.Pipeline;
using System.Windows;

using AddInViews;
using Contracts;

namespace AddInSideAdapters
{
    /// <summary>
    /// Adapts the add-in's view of the contract to the add-in contract
    /// </summary>
    [AddInAdapter]
    public class WPFAddIn_ViewToContractAddInSideAdapter : ContractBase, IWPFAddInContract
    {
        IWPFAddInView wpfAddInView;

        public WPFAddIn_ViewToContractAddInSideAdapter(IWPFAddInView wpfAddInView)
        {
            // Adapt the add-in view of the contract (IWPFAddInView) 
            // to the contract (IWPFAddInContract)
            this.wpfAddInView = wpfAddInView;
        }

        public INativeHandleContract GetAddInUI()
        {
            // Convert the FrameworkElement from the add-in to an INativeHandleContract 
            // that will be passed across the isolation boundary to the host application.
            FrameworkElement fe = this.wpfAddInView.GetAddInUI();
            INativeHandleContract inhc = FrameworkElementAdapters.ViewToContractAdapter(fe);
            return inhc;
        }
    }
}

Imports System.AddIn.Contract
Imports System.AddIn.Pipeline
Imports System.Windows

Imports AddInViews
Imports Contracts

Namespace AddInSideAdapters
	''' <summary>
	''' Adapts the add-in's view of the contract to the add-in contract
	''' </summary>
	<AddInAdapter>
	Public Class WPFAddIn_ViewToContractAddInSideAdapter
		Inherits ContractBase
		Implements IWPFAddInContract
		Private wpfAddInView As IWPFAddInView

		Public Sub New(ByVal wpfAddInView As IWPFAddInView)
			' Adapt the add-in view of the contract (IWPFAddInView) 
			' to the contract (IWPFAddInContract)
			Me.wpfAddInView = wpfAddInView
		End Sub

        Public Function GetAddInUI() As INativeHandleContract Implements IWPFAddInContract.GetAddInUI
            ' Convert the FrameworkElement from the add-in to an INativeHandleContract 
            ' that will be passed across the isolation boundary to the host application.
            Dim fe As FrameworkElement = Me.wpfAddInView.GetAddInUI()
            Dim inhc As INativeHandleContract = FrameworkElementAdapters.ViewToContractAdapter(fe)
            Return inhc
        End Function
	End Class
End Namespace

Implementazione del segmento di pipeline di visualizzazione hostImplementing the Host View Pipeline Segment

Poiché l'applicazione host visualizzerà un FrameworkElement, il metodo nella visualizzazione host correlata a IWPFAddInHostView.GetAddInUI deve restituire un valore di tipo FrameworkElement.Because the host application will display a FrameworkElement, the method on the host view that correlates to IWPFAddInHostView.GetAddInUI must return a value of type FrameworkElement. Il codice seguente illustra la visualizzazione host del contratto, implementata come interfaccia.The following code shows the host view of the contract, implemented as an interface.

using System.Windows;

namespace HostViews
{
    /// <summary>
    /// Defines the host's view of the add-in
    /// </summary>
    public interface IWPFAddInHostView
    {
        // The view returns as a class that directly or indirectly derives from 
        // FrameworkElement and can subsequently be displayed by the host 
        // application by embedding it as content or sub-content of a UI that is 
        // implemented by the host application.
        FrameworkElement GetAddInUI();
    }
}

Imports System.Windows

Namespace HostViews
	''' <summary>
	''' Defines the host's view of the add-in
	''' </summary>
	Public Interface IWPFAddInHostView
		' The view returns as a class that directly or indirectly derives from 
		' FrameworkElement and can subsequently be displayed by the host 
		' application by embedding it as content or sub-content of a UI that is 
		' implemented by the host application.
		Function GetAddInUI() As FrameworkElement
	End Interface
End Namespace

Implementazione del segmento di pipeline dell'adattatore sul lato hostImplementing the Host-Side Adapter Pipeline Segment

Il metodo del contratto restituisce un INativeHandleContract, ma l'applicazione host prevede un FrameworkElement (come specificato dalla visualizzazione host).The contract method returns an INativeHandleContract, but the host application expects a FrameworkElement (as specified by the host view). Di conseguenza, il INativeHandleContract deve essere convertito in un FrameworkElement dopo aver oltrepassato il limite di isolamento.Consequently, the INativeHandleContract must be converted to a FrameworkElement after crossing the isolation boundary. Questa operazione viene eseguita dall'adapter sul lato host chiamando ContractToViewAdapter, come illustrato nel codice seguente.This work is performed by the host-side adapter by calling ContractToViewAdapter, as shown in the following code.

using System.AddIn.Contract;
using System.AddIn.Pipeline;
using System.Windows;

using Contracts;
using HostViews;

namespace HostSideAdapters
{
    /// <summary>
    /// Adapts the add-in contract to the host's view of the add-in
    /// </summary>
    [HostAdapter]
    public class WPFAddIn_ContractToViewHostSideAdapter : IWPFAddInHostView
    {
        IWPFAddInContract wpfAddInContract;
        ContractHandle wpfAddInContractHandle;

        public WPFAddIn_ContractToViewHostSideAdapter(IWPFAddInContract wpfAddInContract)
        {
            // Adapt the contract (IWPFAddInContract) to the host application's
            // view of the contract (IWPFAddInHostView)
            this.wpfAddInContract = wpfAddInContract;

            // Prevent the reference to the contract from being released while the
            // host application uses the add-in
            this.wpfAddInContractHandle = new ContractHandle(wpfAddInContract);
        }

        public FrameworkElement GetAddInUI()
        {
            // Convert the INativeHandleContract that was passed from the add-in side
            // of the isolation boundary to a FrameworkElement
            INativeHandleContract inhc = this.wpfAddInContract.GetAddInUI();
            FrameworkElement fe = FrameworkElementAdapters.ContractToViewAdapter(inhc);
            return fe;
        }
    }
}

Imports System.AddIn.Contract
Imports System.AddIn.Pipeline
Imports System.Windows

Imports Contracts
Imports HostViews

Namespace HostSideAdapters
	''' <summary>
	''' Adapts the add-in contract to the host's view of the add-in
	''' </summary>
	<HostAdapter>
	Public Class WPFAddIn_ContractToViewHostSideAdapter
        Implements IWPFAddInHostView
		Private wpfAddInContract As IWPFAddInContract
		Private wpfAddInContractHandle As ContractHandle

		Public Sub New(ByVal wpfAddInContract As IWPFAddInContract)
			' Adapt the contract (IWPFAddInContract) to the host application's
			' view of the contract (IWPFAddInHostView)
			Me.wpfAddInContract = wpfAddInContract

			' Prevent the reference to the contract from being released while the
			' host application uses the add-in
			Me.wpfAddInContractHandle = New ContractHandle(wpfAddInContract)
		End Sub

        Public Function GetAddInUI() As FrameworkElement Implements IWPFAddInHostView.GetAddInUI
            ' Convert the INativeHandleContract that was passed from the add-in side
            ' of the isolation boundary to a FrameworkElement
            Dim inhc As INativeHandleContract = Me.wpfAddInContract.GetAddInUI()
            Dim fe As FrameworkElement = FrameworkElementAdapters.ContractToViewAdapter(inhc)
            Return fe
        End Function
	End Class
End Namespace

Implementazione del componente aggiuntivoImplementing the Add-In

Con il lato del componente-scheda aggiuntivo creato e la visualizzazione, il componente aggiuntivo (WPFAddIn1.AddIn) deve implementare il IWPFAddInView.GetAddInUI per restituire un FrameworkElement oggetto (un UserControl in questo esempio).With the add-in-side adapter and add-in view created, the add-in (WPFAddIn1.AddIn) must implement the IWPFAddInView.GetAddInUI method to return a FrameworkElement object (a UserControl in this example). L'implementazione del UserControl, AddInUI, viene visualizzato per il codice seguente.The implementation of the UserControl, AddInUI, is shown by the following code.

    <UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="WPFAddIn1.AddInUI">
    
    <StackPanel>
		<Button Click="clickMeButton_Click" Content="Click Me!" />
    </StackPanel>
    
</UserControl>
using System.Windows;
using System.Windows.Controls;

namespace WPFAddIn1
{
    public partial class AddInUI : UserControl
    {
        public AddInUI()
        {
            InitializeComponent();
        }

        void clickMeButton_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Hello from WPFAddIn1");
        }
    }
}

Imports System.Windows
Imports System.Windows.Controls

Namespace WPFAddIn1
	Partial Public Class AddInUI
		Inherits UserControl
		Public Sub New()
			InitializeComponent()
		End Sub

		Private Sub clickMeButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
			MessageBox.Show("Hello from WPFAddIn1")
		End Sub
	End Class
End Namespace

L'implementazione del IWPFAddInView.GetAddInUI da parte del componente aggiuntivo deve semplicemente restituire una nuova istanza della AddInUI, come illustrato nel codice seguente.The implementation of the IWPFAddInView.GetAddInUI by the add-in simply needs to return a new instance of AddInUI, as shown by the following code.

using System.AddIn;
using System.Windows;

using AddInViews;

namespace WPFAddIn1
{
    /// <summary>
    /// Add-In implementation
    /// </summary>
    [AddIn("WPF Add-In 1")]
    public class WPFAddIn : IWPFAddInView
    {
        public FrameworkElement GetAddInUI()
        {
            // Return add-in UI
            return new AddInUI();
        }
    }
}

Imports System.AddIn
Imports System.Windows

Imports AddInViews

Namespace WPFAddIn1
	''' <summary>
	''' Add-In implementation
	''' </summary>
	<AddIn("WPF Add-In 1")>
	Public Class WPFAddIn
        Implements IWPFAddInView
        Public Function GetAddInUI() As FrameworkElement Implements IWPFAddInView.GetAddInUI
            ' Return add-in UI
            Return New AddInUI()
        End Function
	End Class
End Namespace

Implementazione dell'applicazione hostImplementing the Host Application

Con l'adattatore host sul lato host creato e la visualizzazione, è possibile utilizzare l'applicazione host di .NET Framework.NET Framework modello di componente aggiuntivo per aprire la pipeline, acquisire una visualizzazione host del componente aggiuntivo e chiamata di IWPFAddInHostView.GetAddInUI (metodo).With the host-side adapter and host view created, the host application can use the .NET Framework.NET Framework add-in model to open the pipeline, acquire a host view of the add-in, and call the IWPFAddInHostView.GetAddInUI method. Il codice riportato di seguito illustra i diversi passaggi.These steps are shown in the following code.

// Get add-in pipeline folder (the folder in which this application was launched from)
string appPath = Environment.CurrentDirectory;

// Rebuild visual add-in pipeline
string[] warnings = AddInStore.Rebuild(appPath);
if (warnings.Length > 0)
{
    string msg = "Could not rebuild pipeline:";
    foreach (string warning in warnings) msg += "\n" + warning;
    MessageBox.Show(msg);
    return;
}

// Activate add-in with Internet zone security isolation
Collection<AddInToken> addInTokens = AddInStore.FindAddIns(typeof(IWPFAddInHostView), appPath);
AddInToken wpfAddInToken = addInTokens[0];
this.wpfAddInHostView = wpfAddInToken.Activate<IWPFAddInHostView>(AddInSecurityLevel.Internet);

// Get and display add-in UI
FrameworkElement addInUI = this.wpfAddInHostView.GetAddInUI();
this.addInUIHostGrid.Children.Add(addInUI);
' Get add-in pipeline folder (the folder in which this application was launched from)
Dim appPath As String = Environment.CurrentDirectory

' Rebuild visual add-in pipeline
Dim warnings() As String = AddInStore.Rebuild(appPath)
If warnings.Length > 0 Then
    Dim msg As String = "Could not rebuild pipeline:"
    For Each warning As String In warnings
        msg &= vbLf & warning
    Next warning
    MessageBox.Show(msg)
    Return
End If

' Activate add-in with Internet zone security isolation
Dim addInTokens As Collection(Of AddInToken) = AddInStore.FindAddIns(GetType(IWPFAddInHostView), appPath)
Dim wpfAddInToken As AddInToken = addInTokens(0)
Me.wpfAddInHostView = wpfAddInToken.Activate(Of IWPFAddInHostView)(AddInSecurityLevel.Internet)

' Get and display add-in UI
Dim addInUI As FrameworkElement = Me.wpfAddInHostView.GetAddInUI()
Me.addInUIHostGrid.Children.Add(addInUI)

Vedere ancheSee Also

Componenti aggiuntivi ed estendibilitàAdd-ins and Extensibility
Cenni preliminari sui componenti aggiuntivi di WPFWPF Add-Ins Overview