【问题标题】:How do you create a simple Automation Extender for Visual Studio with UITypeEditor如何使用 UITypeEditor 为 Visual Studio 创建一个简单的自动化扩展器
【发布时间】:2015-09-21 15:43:34
【问题描述】:

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

什么是最简单的实现,以便我可以开始? 如何使用 UITypeEditAttribute 创建用户界面以某种方式收集值?

【问题讨论】:

    标签: visual-studio ide extensibility


    【解决方案1】:

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

    由于这是一个高级主题,因此暗示您在开始实施之前对完成所有步骤感到满意(这些都是常见的编程任务)。

    如果有任何不清楚的地方,请发表评论,我会尽量简化。请注意,这被配置为在 Visual Studio 中为 Visual C# 文件创建自定义属性。当您运行或调试 Visual Studio 包并单击任何 .cs 文件时,自定义属性应显示在属性窗口中。提供的 cmets 是必需的说明。

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

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

    [ComVisible(true)] // Important!
    public interface IMyDynamicExtender
    {
        String NewProperty { get; set; }
    }
    

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

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

    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";
        }
    }
    

    【讨论】:

    • 这个答案有效,但是这些自定义属性也可以保存在 csproj 文件中吗?
    • 我能够将自定义属性放在旧的 csproj 格式上。而且,它肯定会适用于更新的格式。但是,您基本上需要在文件中包含显式元素来容纳您存储信息的每个文件的自定义 id 属性。我不确定复制、移动、删除、恢复的意外后果,这可能会导致一些困难的挑战。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-28
    • 1970-01-01
    • 1970-01-01
    • 2019-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多