2011-02-15 16 views
6

Estoy intentando crear un instalador VSIX para un control WPF.Instalador de la caja de herramientas WPF para un tipo definido en un ensamblaje diferente

Supuestamente es fácil, pero la versión "fácil" asume que crea el control WPF en el proyecto VSIX.

El problema es que tengo mi UserControl ubicado en una de mis DLL, y no creo que sacarlo sea el mejor diseño. Me gustaría dejarlo allí, pero parece que no puedo hacer esto Y tener el control agregado a la caja de herramientas.

Una opción sería mover el código que necesito para instalarlo en la caja de herramientas en el conjunto del control, sino que añadiría una dependencia a Microsoft.VisualStudio.Shell.Immutable.10.0.dll. El ensamblado lo usa alguien con Visual Studio instalado y un servidor remoto que se ejecuta dentro de un servicio donde VS no está instalado, por lo que es un no-go.

Otra opción que probé fue "engañar" al instalador de herramientas VSIX al aplicar el RegistrationAttribute a proxies que registraría los tipos definidos en el otro ensamblado. Pensé que funcionaría, pero sucedieron cosas raras.

all kinds of weirdness in the toolbox

En lugar de obtener dos controles, me sale un montón de controles de frontera (la frontera estándar de WPF) en pestañas nombres extraños, algunos de los cuales se hacen eco de algunos de mis espacios de nombres.

¿Cómo puedo registrar un UserControl de WPF con la Caja de herramientas cuando el control está definido en un conjunto que no sea el VSIX?

+0

¿Dónde se supone que el control WPF debe estar en el proyecto VSIX? Además, ¿qué quiere decir con la versión "fácil"? – Matt

+1

@Matt: Sin suposiciones, solo cómo se diseñan las herramientas. Si sigue los tutoriales de MSDN [aquí] (http://msdn.microsoft.com/en-us/library/ee712573.aspx) y [aquí] (http://msdn.microsoft.com/en-us/library/ee712574.aspx) o simplemente mire la plantilla instalada, verá que está orientada hacia (los tutoriales y la plantilla) combinando el instalador y el control en el mismo proyecto. O bien, podría tratar de responder mi pregunta, en cuyo caso encontrará que no hay nada * fácil * sobre hacerlo de otra manera. – Will

+0

@Will Creo que veo tu punto, parece que el atributo ProvideToolboxControl es la dependencia de la que hablas? – Matt

Respuesta

2

Pude organizar una prueba de concepto similar a la idea de proxy que mencionó.

El problema que está viendo es causado por el registro del ensamblaje incorrecto, así que creé un nuevo atributo de registro llamado ProvideProxyToolboxControlAttribute que se usa como un atributo en las clases proxy que tiene en su ensamblado de integración VS. Es casi idéntico al ProvideToolboxControlAttribute, excepto que toma el tipo del control real. Por supuesto, este nuevo atributo también estaría en su ensamblaje VS.

Por ejemplo, decir que tengo una caja de herramientas de control en mi conjunto no VS llamada MyToolboxControl, que crearía un simple clase de proxy MyToolboxControlProxy en mi ensamblaje VS que tiene este aspecto:

[ProvideProxyToolboxControl("MyToolboxControl", typeof(NonVsAssembly.MyToolboxControl))] 
public class ToolboxControlProxy 
{ 
} 

Y, por supuesto , la magia sucede en ProvideProxyToolboxControlAttribute, que es básicamente sólo esta clase (comentarios y parámetro/verificación de errores removidos por razones de brevedad):

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] 
[System.Runtime.InteropServices.ComVisibleAttribute(false)] 
public sealed class ProvideProxyToolboxControlAttribute : RegistrationAttribute 
{ 
    private const string ToolboxControlsInstallerPath = "ToolboxControlsInstaller"; 
    public ProvideProxyToolboxControlAttribute(string name, Type controlType) 
    { 
     this.Name = name; 
     this.ControlType = controlType; 
    } 

    private string Name { get; set; } 

    private Type ControlType { get; set; } 

    public override void Register(RegistrationAttribute.RegistrationContext context) 
    { 
     using (Key key = context.CreateKey(String.Format(CultureInfo.InvariantCulture, "{0}\\{1}", 
                 ToolboxControlsInstallerPath, 
                 ControlType.AssemblyQualifiedName))) 
     { 
      key.SetValue(String.Empty, this.Name); 
      key.SetValue("Codebase", ControlType.Assembly.Location); 
      key.SetValue("WPFControls", "1"); 
     } 
    } 
    public override void Unregister(RegistrationAttribute.RegistrationContext context) 
    { 
     if (context != null) 
     { 
      context.RemoveKey(String.Format(CultureInfo.InvariantCulture, "{0}\\{1}", 
                 ToolboxControlsInstallerPath, 
                 ControlType.AssemblyQualifiedName)); 
     } 
    } 
} 

parece que funciona bien, comprobé que el control está en la caja de herramientas y que la pr Se agregaron claves de registro operativo.

Espero que esto ayude!

+0

Gracias por la ayuda en esto. Pasará una semana más o menos antes de que pueda rodar esto y ver si funciona para mí. – Will

+0

Hace un par de meses más o menos ... – Will

+0

@Lo diría un par de años. – TechNyquist

Cuestiones relacionadas