Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Actualización: noviembre 2007
En este ejemplo se muestra cómo crear un complemento que devuelve una interfaz de usuario (UI) de Windows Presentation Foundation (WPF) a una aplicación host WPF independiente.
El complemento devuelve una interfaz de usuario que es un control de usuario de WPF. El contenido del control de usuario es un botón único que muestra un cuadro de mensaje cuando se hace clic en él. La aplicación WPF independiente hospeda el complemento y muestra el control de usuario (devuelto por el complemento) como el contenido de la ventana de la aplicación principal.
Requisitos previos
En este ejemplo se resaltan las extensiones de WPF del modelo de complementos de .NET Framework que habilitan este escenario y se supone lo siguiente:
Conocimientos del modelo de complementos de .NET Framework, lo que incluye la programación de canalizaciones, complementos y host. Si no está familiarizado con estos conceptos, vea Información general sobre complementos. Para obtener un tutorial que muestra la implementación de una canalización, un complemento y una aplicación host, vea Tutorial: Crear una aplicación extensible.
Conocimientos de las extensiones de WPF del modelo de complementos de .NET Framework, que encontrará en Información general sobre complementos de Windows Presentation Foundation.
Ejemplo
Para obtener el ejemplo completo que acompaña a este tema, vea Ejemplo Add-In Returns a UI.
Ejemplo
Para crear un complemento que devuelve una interfaz de usuario de WPF se necesita un código concreto para cada segmento de la canalización, el complemento y la aplicación host.
Implementar el segmento de canalización del contrato
El contrato debe definir un método para devolver una interfaz de usuario y su valor devuelto debe ser de tipo INativeHandleContract. El método GetAddInUI del contrato IWPFAddInContract lo muestra en el código siguiente.
using System.AddIn.Contract; // IContract, INativeHandleContract
using System.AddIn.Pipeline; // AddInContractAttribute
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();
}
}
Implementar el segmento de canalización de la vista de complemento
Dado que el complemento implementa las UIs que proporciona como subclases de FrameworkElement, el método en la vista de complemento que guarda correlación con IWPFAddInView.GetAddInUI debe devolver un valor de tipo FrameworkElement. En el código siguiente se muestra la vista de complemento del contrato, implementada como una interfaz.
using System.AddIn.Pipeline; // AddInBaseAttribute
using System.Windows; // FrameworkElement
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();
}
}
Implementar el segmento de canalización del adaptador del complemento
El método del contrato devuelve una interfaz INativeHandleContract, pero el complemento devuelve un objeto FrameworkElement (según lo especificado en la vista de complemento). Por consiguiente, el objeto FrameworkElement se debe convertir en una interfaz INativeHandleContract antes de cruzar el límite de aislamiento. Este trabajo lo realiza el adaptador del complemento mediante una llamada a ViewToContractAdapter, como se muestra en el código siguiente.
using System.AddIn.Contract; // INativeHandleContract
using System.AddIn.Pipeline; // AddInAdapterAttribute, FrameworkElementAdapters, ContractBase
using System.Windows; // FrameworkElement
using AddInViews; // IWPFAddInView
using Contracts; // IWPFAddInContract
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;
}
}
}
Implementar el segmento de canalización de la vista de host
Dado que la aplicación host mostrará un objeto FrameworkElement, el método en la vista de host que guarda correlación con IWPFAddInHostView.GetAddInUI debe devolver un valor de tipo FrameworkElement. En el código siguiente se muestra la vista de host del contrato, implementada como una interfaz.
using System.Windows; // FrameworkElement
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();
}
}
Implementar el segmento de canalización del adaptador del host
El método del contrato devuelve una interfaz INativeHandleContract, pero la aplicación host espera un objeto FrameworkElement (según lo especificado por la vista de host). Por consiguiente, la interfaz INativeHandleContract se debe convertir en un objeto FrameworkElement después de cruzar el límite de aislamiento. Este trabajo lo realiza el adaptador del host mediante una llamada a ContractToViewAdapter, como se muestra en el código siguiente.
using System.AddIn.Contract; // INativeHandleContract
using System.AddIn.Pipeline; // HostAdapterAttribute, FrameworkElementAdapters, ContractHandle
using System.Windows; // FrameworkElement
using Contracts; // IWPFAddInContract
using HostViews; // IWPFAddInHostView
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;
}
}
}
Implementar el complemento
Con el adaptador y la vista de complemento creados, el complemento (WPFAddIn1.AddIn) debe implementar el método IWPFAddInView.GetAddInUI para que se devuelva un objeto FrameworkElement (UserControl en este ejemplo). La implementación de UserControl, AddInUI, se muestra en el código siguiente.
<UserControl
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WPFAddIn1.AddInUI">
<StackPanel>
<Button Click="clickMeButton_Click" Content="Click Me!" />
</StackPanel>
</UserControl>
using System.Windows; // MessageBox, RoutedEventArgs
using System.Windows.Controls; // UserControl
namespace WPFAddIn1
{
public partial class AddInUI : UserControl
{
public AddInUI()
{
InitializeComponent();
}
void clickMeButton_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Hello from WPFAddIn1");
}
}
}
La implementación de IWPFAddInView.GetAddInUI por parte del complemento únicamente tiene que devolver una nueva instancia de AddInUI, como se muestra en el código siguiente.
using System.AddIn; // AddInAttribute
using System.Windows; // FrameworkElement
using AddInViews; // IWPFAddInView
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();
}
}
}
Implementar la aplicación host
Con el adaptador y la vista de host creados, la aplicación host puede utilizar el modelo de complementos de .NET Framework para abrir la canalización, adquirir una vista de host del complemento y llamar al método IWPFAddInHostView.GetAddInUI. Estos pasos se muestran en el código siguiente.
// 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);
Vea también
Tareas
Conceptos
Información general sobre complementos
Información general sobre complementos de Windows Presentation Foundation