用于在不同程序集中定义的类型的 WPF 工具箱安装程序

标签 wpf visual-studio user-controls installation toolbox

我正在尝试为 WPF 控件创建 VSIX 安装程序。

据说很简单,但“简单”版本假设您在 VSIX 项目中创建 WPF 控件。

问题是,我的 UserControl 深藏在我的一个 DLL 中,我不认为将其拉出来是最好的设计。我想把它留在那里,但我似乎无法做到这一点并将控件添加到工具箱中。

一种选择是将安装到工具箱所需的代码移动到控件的程序集中,但这会添加对 Microsoft.VisualStudio.Shell.Immutable.10.0.dll 的依赖项。该程序集既由安装了 Visual Studio 的人员使用,又由在未安装 VS 的服务中运行的远程服务器使用,因此这是不行的。

我尝试的另一个选项是通过将 RegistrationAttribute 应用到代理来“欺骗”工具箱安装程序 VSIX,代理将注册其他程序集中定义的类型。以为这会起作用,但奇怪的事情发生了。

all kinds of weirdness in the toolbox

我没有得到两个控件,而是在命名奇怪的选项卡中得到了一堆 Border 控件(标准 WPF 边框),其中一些与我的一些命名空间相呼应。

当 WPF UserControl 是在 VSIX 之外的程序集中定义时,如何向工具箱注册该控件?

最佳答案

我能够提出类似于您提到的代理想法的概念证明。

您看到的问题是由错误的程序集注册引起的,因此我创建了一个名为 ProvideProxyToolboxControlAttribute 的新注册属性,该属性用作您所拥有的代理类的属性你的 VS 集成组件。它与 ProvideToolboxControlAttribute 几乎相同,只是它采用实际控件的类型。当然,这个新属性也将位于您的 VS 程序集中。

例如,假设我的非 VS 程序集中有一个名为 MyToolboxControl 的工具箱控件,我会在 VS 程序集中创建一个简单的代理类 MyToolboxControlProxy,它看起来如下像这样:

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

当然,神奇的事情发生在 ProvideProxyToolboxControlAttribute 中,它基本上就是这个类(为简洁起见,删除了注释和参数/错误检查):

[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));
        }
    }
}

它似乎工作得很好,我验证了该控件位于工具箱中并且添加了正确的注册表项。

希望这有帮助!

关于用于在不同程序集中定义的类型的 WPF 工具箱安装程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5008791/

相关文章:

c# - 命名空间前缀 "system"未定义

visual-studio - 任何推荐的 VC++ 设置,以便更好地对发布版本进行 PDB 分析

asp.net - 有没有办法向 ASP.NET 用户控件添加客户端方法?

c# - 在 XAML + windows 8 中渲染 Html

c# - 在 wpf/surface 中从网络加载图像

WPF DependencyProperty 链通知

c# - Visual Studio 宏 - 代码生成语言

.net - Visual Studio 2017 中的安装项目缺少 vs_setup.msi?

wpf - 在用户控件中获取工具提示以显示数据绑定(bind)文本并保持打开状态

c# - 当我将我的用户控件拖到设计 View 上时,Visual Studio 引发错误