如何使用UITypeEditor为Visual Studio创建简单的Automation Extender

jwi*_*ize 2 ide extensibility visual-studio

在Visual Studio中,当您在解决方案资源管理器中选择项目或项目项时,有时您可能想要向属性窗口(按F4时弹出的窗口)添加自定义属性。另外,要填充这些属性的值,我需要添加一个按钮以弹出一个表单,以便我可以在设计时从用户那里收集信息。

什么是最简单的实现,这样我就可以开始了?如何使用UITypeEditAttribute创建一个用户界面来收集值?

jwi*_*ize 5

这是我能想到的最简单的实现。

既然这是一个高级主题,则意味着您在开始执行之前可以轻松完成所有步骤(这些都是常见的编程任务)。

如果有任何不清楚的地方,请评论,我将尝试简化。请注意,此属性配置为在Visual Studio中为Visual C#文件创建自定义属性。当您运行或调试Visual Studio程序包,然后单击任何.cs文件时,自定义属性应显示在属性窗口中。提供的注释是必需的说明。

在此处输入图片说明

  1. 创建一个Visual Studio包。
  2. 创建一个接口,该接口实现要添加到属性页面的自定义属性。
  3. 创建一个实现自定义属性接口的类,并用属性装饰自定义属性。
  4. 创建实现IExtenderProvider接口的类,并重写GetExtenderCanExtend方法。
  5. 创建一个继承自UITypeEditor的新类,并重写GetEditStyleEditValue方法。

让我们开始吧。

1.在Visual Studio中创建包。

Package.cs

// ... 
public sealed class ThePackage : Package
{
    private DTE2 Host;
    private ObjectExtenders _extensionManager;
    private MyExtenderProvider _extenderProvider;
    protected override void Initialize()
    {

    Host = (DTE2)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SDTE));
    _extenderProvider = new MyExtenderProvider();

    _extenderProviderCookie = Host.ObjectExtenders.RegisterExtenderProvider(VSConstants.CATID.CSharpFileProperties_string,
        "MyExtenderProvider", _extenderProvider);
    }
    protected override void Dispose(bool disposing)
    {
        Host.ObjectExtenders.UnregisterExtenderProvider(_extenderProviderCookie);
        _extenderProvider = null;
        base.Dispose(disposing);
    }
}
Run Code Online (Sandbox Code Playgroud)

2.创建实现所需的自定义属性的类。

[ComVisible(true)] // Important!
public interface IMyDynamicExtender
{
    String NewProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

3.创建一个实现自定义属性接口的类。

[ComVisible(true)] // Important!
public class NewPropertyExtender : IMyDynamicExtender, IDisposable
{
    // These attibutes supply the property with some information
    // on how to display and which UITypeEditor to use.
    [DisplayName("New Property")]
    [Category("New")]
    [Description("Specifies the new property")]
    [Editor(typeof(CustomUiTypeEditor), typeof(UITypeEditor))]
    public String NewProperty { get; set; }
    private readonly IExtenderSite _extenderSite;
    private readonly int _cookie;
    private bool _disposed;

    public NewPropertyExtender(IExtenderSite extenderSite, int cookie)
    {
        _extenderSite = extenderSite;
        _cookie = cookie;
    }

    public void Dispose()
    {
        Dispose(true);
        // take the instance off of the finalization queue.
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (_disposed) return;
        if (disposing && _cookie != 0)
        {
            _extenderSite.NotifyDelete(_cookie);
        }
        _disposed = true;
    }
}
Run Code Online (Sandbox Code Playgroud)

4.创建实现[IExtenderProvider]接口的类,并覆盖[GetExtender]和[CanExtend]方法。

public class MyExtenderProvider : IExtenderProvider
{
    private IMyDynamicExtender _extender;
    public object GetExtender(string extenderCatid, string extenderName,           
         object extendeeObject, IExtenderSite extenderSite,
        int cookie)
    {
        return _extender = CanExtend(extenderCatid, extenderName, extendeeObject) ?  
            new NewPropertyExtender(extenderSite, cookie) : null;
    }

    public bool CanExtend(string extenderCatid, string extenderName, object extendeeObject)
    {
        // Some implementation will be here in the real world. 
        return true;
    }
} 
Run Code Online (Sandbox Code Playgroud)

5.创建一个新类,该类继承自[UITypeEditor],并覆盖[GetEditStyle]和[EditValue]方法。

public class CustomUiTypeEditor : UITypeEditor
{
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.Modal;
    }

    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        // Use the result of a dialog or something else here.
        return "HELLO WORLD";
    }
}
Run Code Online (Sandbox Code Playgroud)