Como: Criar um suplemento que é uma interface do usuário
This example shows how to create an add-in that is a Windows Presentation Foundation (WPF) interface do usuário (UI) which is hosted by a WPF standalone application.
O suplemento é um UI Isto é um WPF controle de usuário. O conteúdo do controle de usuário é um único botão que, quando clicada, exibe uma caixa de mensagem. The WPF aplicativo autônomo hospeda o suplemento UI sistema autônomo o conteúdo da janela principal do aplicativo.
Pré-requisitos
Este exemplo realça o WPF extensões para o .NET Framework suplemento do modelo que permitem esse cenário e pressupõe o seguinte:
Conhecimento sobre o .NET Framework suplemento do modelo, incluindo pipeline, suplementos e desenvolvimento de host. Se não estão familiarizados com esses conceitos, consulte Adicionar-em Visão geral. Para obter um tutorial que demonstra a implementação de um pipeline, um suplemento e um aplicativo host, consulte Demonstra Passo a passo: Criando um aplicativo extensível.
Conhecimento sobre o WPF extensões para o .NET Framework modelo de suplemento, que pode ser encontrado aqui: Visão Geral dos Suplementos do Windows Presentation Foundation.
Exemplo
Para o exemplo completo que acompanha este tópico, consulte Adicionar-Em É um exemplo de interface do usuário.
Exemplo
To create an add-in that is a WPF UI requires specific code for each pipeline segment, the add-in, and the host application.
Implementando o segmento de pipeline do contrato
Quando um suplemento é um UI, o contrato para o suplemento deve implementar INativeHandleContract. No exemplo, IWPFAddInContract implementa INativeHandleContract, sistema autônomo mostra o código a seguir.
using System.AddIn.Contract; // INativeHandleContract
using System.AddIn.Pipeline; // AddInContractAttribute
namespace Contracts
{
/// <summary>
/// Defines the services that an add-in will provide to a host application.
/// In this case, the add-in is a UI.
/// </summary>
[AddInContract]
public interface IWPFAddInContract : INativeHandleContract {}
}
Implementando o segmento de Pipeline View de suplemento
Como o suplementos é implementado como uma subclasse do tipo FrameworkElement, a exibição do suplemento também deve ter como subclasse FrameworkElement. O seguinte código mostra a exibição do suplemento do contrato, implementado como a classe WPFAddInView.
using System.AddIn.Pipeline; // AddInBaseAttribute
using System.Windows.Controls; // UserControl
namespace AddInViews
{
/// <summary>
/// Defines the add-in's view of the contract.
/// </summary>
[AddInBase]
public class WPFAddInView : UserControl { }
}
Aqui, a exibição do suplemento se origina do UserControl. Consequentemente, o suplemento UI também deve se originar do UserControl.
Implementando o suplemento-side adaptador pipeline segmento
Enquanto o contrato é um INativeHandleContract, o suplemento é um FrameworkElement (sistema autônomo especificado pelo add - no modo de exibição segmento de pipeline). Portanto, o FrameworkElement deve ser convertido em um INativeHandleContract antes de cruzar o limite de isolamento. O trabalho é executado pelo adaptador no lado do suplemento chamando ViewToContractAdapter, como exibido no código a seguir.
using System; // IntPtr
using System.AddIn.Contract; // INativeHandleContract
using System.AddIn.Pipeline; // AddInAdapterAttribute, FrameworkElementAdapters, ContractBase
using System.Security.Permissions;
using AddInViews; // WPFAddInView
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
{
WPFAddInView wpfAddInView;
public WPFAddIn_ViewToContractAddInSideAdapter(WPFAddInView wpfAddInView)
{
// Adapt the add-in view of the contract (WPFAddInView)
// to the contract (IWPFAddInContract)
this.wpfAddInView = wpfAddInView;
}
/// <summary>
/// ContractBase.QueryContract must be overridden to:
/// * Safely return a window handle for an add-in UI to the host
/// application's application.
/// * Enable tabbing between host application UI and add-in UI, in the
/// "add-in is a UI" scenario.
/// </summary>
public override IContract QueryContract(string contractIdentifier)
{
if (contractIdentifier.Equals(typeof(INativeHandleContract).AssemblyQualifiedName))
{
return FrameworkElementAdapters.ViewToContractAdapter(this.wpfAddInView);
}
return base.QueryContract(contractIdentifier);
}
/// <summary>
/// GetHandle is called by the WPF add-in model from the host application's
/// application domain to to get the window handle for an add-in UI from the
/// add-in's application domain. GetHandle is called if a window handle isn't
/// returned by other means ie overriding ContractBase.QueryContract,
/// as shown above.
/// NOTE: This method requires UnmanagedCodePermission to be called
/// (full-trust by default), to prevent illegal window handle
/// access in partially trusted scenarios. If the add-in could
/// run in a partially trusted application domain
/// (eg AddInSecurityLevel.Internet), you can safely return a window
/// handle by overriding ContractBase.QueryContract, as shown above.
/// </summary>
[SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public IntPtr GetHandle()
{
return FrameworkElementAdapters.ViewToContractAdapter(this.wpfAddInView).GetHandle();
}
}
}
No suplemento modelo no qual um suplemento retorna um UI (consulte a Como: Criar um suplemento que retorna uma interface do usuário), adaptador suplementar convertido a FrameworkElement para um INativeHandleContract chamando ViewToContractAdapter. ViewToContractAdapter também deve ser chamado neste modelo, embora você precise implementar um método do qual escrever o código chamá-lo. Isso é feito substituindo QueryContract e implementando o código que chama ViewToContractAdapter se o código que está chamando QueryContract está esperando um INativeHandleContract. Nesse caso, o chamador será o adaptador do lado do host, que é tratado numa seção subsequente.
Observação: |
---|
Você também precisa substituir QueryContract Neste modelo para habilitar a navegação por TAB entre o aplicativo host UI e suplemento UI. Para obter mais informações, consulte "WPF suplemento limitações" emVisão Geral dos Suplementos do Windows Presentation Foundation. |
Como o adaptador no lado do suplemento implementa uma interface que deriva de INativeHandleContract, você também precisará implementar GetHandle, embora isso é ignorado quando QueryContract será substituída.
Implementando o segmento de pipeline exibir host
Nesse modelo, o aplicativo host tipicamente espera que o modo de host seja uma subclasse FrameworkElement. O adaptador do lado do host deve converter o INativeHandleContract em um FrameworkElement após o INativeHandleContract cruzar o limite de isolamento. Porque um método não está sendo chamado pelo aplicativo host para obter o FrameworkElement, a exibição do host deve "return" de FrameworkElement Por que o contém. Consequentemente, o modo de host deve se originar de uma subclasse de FrameworkElement que pode conter outro UIs tal como UserControl. O seguinte código mostra o modo de host do contrato, implementado como a classe WPFAddInHostView.
using System.Windows.Controls; // UserControl
namespace HostViews
{
/// <summary>
/// Defines the host's view of the add-in
/// </summary>
public class WPFAddInHostView : UserControl { }
}
Implementando o segmento de pipeline do adaptador no lado do host
Enquanto o contrato é um INativeHandleContract, o aplicativo host espera um UserControl (sistema autônomo especificado pela exibição do host). Consequentemente, o INativeHandleContract deve ser convertido em um FrameworkElement após cruzar o limite de isolamento, antes de ser definido como conteúdo do modo de host (que se origina do UserControl).
O trabalho é executado pelo adaptador do lado do host, como exibido no código a seguir.
using System.AddIn.Contract; // INativeHandleContract
using System.AddIn.Pipeline; // HostAdapterAttribute, FrameworkElementAdapters, ContractHandle
using System.Windows; // FrameworkElement
using Contracts; // IWPFAddInContract
using HostViews; // WPFAddInHostView
namespace HostSideAdapters
{
/// <summary>
/// Adapts the add-in contract to the host's view of the add-in
/// </summary>
[HostAdapter]
public class WPFAddIn_ContractToViewHostSideAdapter : WPFAddInHostView
{
IWPFAddInContract wpfAddInContract;
ContractHandle wpfAddInContractHandle;
public WPFAddIn_ContractToViewHostSideAdapter(IWPFAddInContract wpfAddInContract)
{
// Adapt the contract (IWPFAddInContract) to the host application's
// view of the contract (WPFAddInHostView)
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);
// Convert the INativeHandleContract for the add-in UI that was passed
// from the add-in side of the isolation boundary to a FrameworkElement
string aqn = typeof(INativeHandleContract).AssemblyQualifiedName;
INativeHandleContract inhc = (INativeHandleContract)wpfAddInContract.QueryContract(aqn);
FrameworkElement fe = (FrameworkElement)FrameworkElementAdapters.ContractToViewAdapter(inhc);
// Add FrameworkElement (which displays the UI provided by the add-in) as
// content of the view (a UserControl)
this.Content = fe;
}
}
}
sistema autônomo você pode ver, o adaptador do host adquire o INativeHandleContract chamando o adaptador no lado do suplemento QueryContract método (Este é o ponto em que o INativeHandleContract cruza o limite de isolamento).
Então, o adaptador do lado do host converte o INativeHandleContract em um FrameworkElement chamando ContractToViewAdapter. Finalmente, o FrameworkElement é definido como conteúdo do modo de host.
Implementando o Suplemento
Com o adaptador do lado do suplemento e a exibição do suplemento ajustados, o suplemento pode ser implementado sendo originado da exibição do suplemento, como mostrado no código a seguir.
<addInViews:WPFAddInView
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:addInViews="clr-namespace:AddInViews;assembly=AddInViews"
x:Class="WPFAddIn1.AddInUI">
<Grid>
<Button Click="clickMeButton_Click" Content="Click Me!" />
</Grid>
</addInViews:WPFAddInView>
using System.AddIn; // AddInAttribute
using System.Windows; // MessageBox, RoutedEventArgs
using AddInViews; // WPFAddInView
namespace WPFAddIn1
{
/// <summary>
/// Implements the add-in by deriving from WPFAddInView
/// </summary>
[AddIn("WPF Add-In 1")]
public partial class AddInUI : WPFAddInView
{
public AddInUI()
{
InitializeComponent();
}
void clickMeButton_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Hello from WPFAddIn1");
}
}
}
Neste exemplo, você pode ver uma vantagem interessante desse modelo: sistema autônomo desenvolvedores de suplemento só precisam implementar o suplemento (sistema autônomo está o UI também), em vez de dois um add - na classe e um add - no UI.
Implementando o Aplicativo Host
Com o adaptador do host e a exibição do host criado, o aplicativo host pode usar o .NET Framework modelo suplementar para em em aberto o pipeline e adquirir um modo de exibição do host de suplemento. Esses passos são mostrados no seguinte código:
// 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(WPFAddInHostView), appPath);
AddInToken wpfAddInToken = addInTokens[0];
this.wpfAddInHostView = wpfAddInToken.Activate<WPFAddInHostView>(AddInSecurityLevel.Internet);
// Display add-in UI
this.addInUIHostGrid.Children.Add(this.wpfAddInHostView);
O aplicativo host utiliza um código de modelo de suplemento .NET Framework típico para ativar o suplemento, que implicitamente retorna o modo de host para o aplicativo host. O aplicativo host subsequentemente exibe o modo de host (que é um UserControl) a partir de um Grid.
O código para processar interações com o suplemento UI é executado no domínio de aplicativo do suplemento. Essas interações incluem o seguinte:
Exibindo o MessageBox.
Esta atividade é completamente isolada do aplicativo host.
Consulte também
Tarefas
Adicionar-Em É um exemplo de interface do usuário
Conceitos
Visão Geral dos Suplementos do Windows Presentation Foundation