首页 > 解决方案 > 需要从 .NET Winforms 控件的 PropertyGrid 中隐藏仅设计器的属性(第二部分)

问题描述

这是一个后续问题:Need To Hide A Designer-Only Property From PropertyGrid For A .NET Winforms Control

我已经用我自己的实现替换了默认的 TypeDescriptorFilterService(太酷了!),并且 FilterProperties 事件处理程序正在触发。我看到上一个问题如何帮助隐藏那些特定的 TableLayoutPanel 属性。

现在我对隐藏某些属性的项目有更一般的要求。我目前的具体目标是隐藏我的子类 Windows 窗体对象的“(名称)”属性(我的 .NET 项目利用设计器在内部管理对象名称,并且不希望允许用户在某些条件下更改甚至查看该值)。为了隐藏 Name 属性(实际上显示(Name)在属性网格上),我添加了以下代码:

  public bool FilterProperties(IComponent component, IDictionary properties)
  {
     if (component == null)
        throw new ArgumentNullException("component");
     if (properties == null)
        throw new ArgumentNullException("properties");
     if (typeof(MyExtendedDesignerObjects.Form).IsAssignableFrom(component.GetType()))
     {
        properties.Remove("Name");
        return true;
     }
     IDesigner designer = this.GetDesigner(component);
     if (designer is IDesignerFilter)
     {
        ((IDesignerFilter)designer).PreFilterProperties(properties);
        ((IDesignerFilter)designer).PostFilterProperties(properties);
     }
     return designer != null;
  }

我的MyExtendedDesignerObjects.Form继承自 System.Windows.Forms.Form。虽然我的 Form 对象 ( MyExtendedDesignerObjects.Form) 也是一个 IDesignerFilter,但我不知道如何/在何处连接其设计器的 PreFilterProperties 事件处理程序。

我想一旦我可以连接这个预过滤器逻辑,那么我就可以管理我为这个项目制定的所有属性网格属性可见性目标。

感谢您的阅读。

标签: c#.netwinformswindows-forms-designerdesign-surface

解决方案


Name 属性是一个特殊的属性,它是由设计器扩展提供者添加的。您无法使用此方法隐藏它,您需要找到创建该属性的扩展器提供程序并将其Name替换为另一个创建该Name属性的扩展程序提供程序Browsable(false)

但是对于其余的属性,您可以在 之后隐藏它们,方法PostFilterProperties是用Browsable(false)

示例 1 - 隐藏LockedTag属性

请注意一点:Locked是设计时属性,但是Tag是普通属性。

重写FilterProperties方法如下:

bool ITypeDescriptorFilterService.FilterProperties(IComponent component, IDictionary properties)
{
    if (component == null)
        throw new ArgumentNullException("component");
    if (properties == null)
        throw new ArgumentNullException("properties");


    properties.Remove("Tag");


    IDesigner designer = this.GetDesigner(component);
    if (designer is IDesignerFilter)
    {
        ((IDesignerFilter)designer).PreFilterProperties(properties);
        ((IDesignerFilter)designer).PostFilterProperties(properties);

        var propertyName = "Locked";
        var attributeArray = new Attribute[] { BrowsableAttribute.No };
        var property = properties[propertyName];
        if (property != null)
            properties[propertyName] = TypeDescriptor.CreateProperty(typeof(IDesigner),
                (PropertyDescriptor)property, attributeArray);
    }

    return designer != null;
}

示例 2 - 隐藏Name属性

在下面的示例中,在OnLoaded我的自定义设计器表面的方法中,我找到了IExtenderProviderService,然后我删除了现有的NameExtenderProviderNameInheritedExtenderProvider用我的自定义实现替换它们。自定义实现本质上是我使用 system.design 中的反射器提取的,只需将Browsable属性更改为 false:

using System;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms.Design;

public class TypeDescriptorFilterService : ITypeDescriptorFilterService
{
    internal TypeDescriptorFilterService()
    {
    }

    private IDesigner GetDesigner(IComponent component)
    {
        ISite site = component.Site;
        if (site != null)
        {
            IDesignerHost service = site.GetService(typeof(IDesignerHost)) as IDesignerHost;
            if (service != null)
                return service.GetDesigner(component);
        }
        return (IDesigner)null;
    }

    bool ITypeDescriptorFilterService.FilterAttributes(IComponent component, IDictionary attributes)
    {
        if (component == null)
            throw new ArgumentNullException("component");
        if (attributes == null)
            throw new ArgumentNullException("attributes");
        IDesigner designer = this.GetDesigner(component);
        if (designer is IDesignerFilter)
        {
            ((IDesignerFilter)designer).PreFilterAttributes(attributes);
            ((IDesignerFilter)designer).PostFilterAttributes(attributes);
        }
        return designer != null;
    }

    bool ITypeDescriptorFilterService.FilterEvents(IComponent component, IDictionary events)
    {
        if (component == null)
            throw new ArgumentNullException("component");
        if (events == null)
            throw new ArgumentNullException("events");
        IDesigner designer = this.GetDesigner(component);
        if (designer is IDesignerFilter)
        {
            ((IDesignerFilter)designer).PreFilterEvents(events);
            ((IDesignerFilter)designer).PostFilterEvents(events);
        }
        return designer != null;
    }

    bool ITypeDescriptorFilterService.FilterProperties(IComponent component, IDictionary properties)
    {
        if (component == null)
            throw new ArgumentNullException("component");
        if (properties == null)
            throw new ArgumentNullException("properties");

        IDesigner designer = this.GetDesigner(component);
        if (designer is IDesignerFilter)
        {
            ((IDesignerFilter)designer).PreFilterProperties(properties);
            ((IDesignerFilter)designer).PostFilterProperties(properties);
        }

        return designer != null;
    }
}

public class MyDesignSurface : DesignSurface
{
    public MyDesignSurface() : base()
    {
        this.ServiceContainer.RemoveService(typeof(ITypeDescriptorFilterService));
        this.ServiceContainer.AddService(typeof(ITypeDescriptorFilterService), new TypeDescriptorFilterService());
    }

    protected override void OnLoaded(LoadedEventArgs e)
    {
        base.OnLoaded(e);
        var svc = (IExtenderProviderService)this.ServiceContainer.GetService(typeof(IExtenderProviderService));
        var providers = (ArrayList)svc.GetType().GetField("_providers",
            System.Reflection.BindingFlags.NonPublic |
            System.Reflection.BindingFlags.Instance).GetValue(svc);
        foreach (IExtenderProvider p in providers.ToArray())
            if (p.ToString().Contains("NameExtenderProvider") ||
               p.ToString().Contains("NameInheritedExtenderProvider"))
                svc.RemoveExtenderProvider(p);

        svc.AddExtenderProvider(new NameExtenderProvider());
        svc.AddExtenderProvider(new NameInheritedExtenderProvider());
    }
}


[ProvideProperty("Name", typeof(IComponent))]
public class NameExtenderProvider : IExtenderProvider
{
    private IComponent baseComponent;

    internal NameExtenderProvider()
    {
    }

    protected IComponent GetBaseComponent(object o)
    {
        if (this.baseComponent == null)
        {
            ISite site = ((IComponent)o).Site;
            if (site != null)
            {
                IDesignerHost service = (IDesignerHost)site.GetService(typeof(IDesignerHost));
                if (service != null)
                    this.baseComponent = service.RootComponent;
            }
        }
        return this.baseComponent;
    }

    public virtual bool CanExtend(object o)
    {
        return this.GetBaseComponent(o) == o || TypeDescriptor.GetAttributes(o)[typeof(InheritanceAttribute)].Equals((object)InheritanceAttribute.NotInherited);
    }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    [ParenthesizePropertyName(true)]
    [MergableProperty(false)]
    [Category("Design")]
    [Browsable(false)]
    public virtual string GetName(IComponent comp)
    {
        ISite site = comp.Site;
        if (site != null)
            return site.Name;
        return (string)null;
    }

    public void SetName(IComponent comp, string newName)
    {
        ISite site = comp.Site;
        if (site == null)
            return;
        site.Name = newName;
    }

    public class MyFormDesigner : DocumentDesigner
    {

    }
}

public class NameInheritedExtenderProvider : NameExtenderProvider
{
    internal NameInheritedExtenderProvider()
    {
    }
    public override bool CanExtend(object o)
    {
        return this.GetBaseComponent(o) != o && !TypeDescriptor.GetAttributes(o)[typeof(InheritanceAttribute)].Equals((object)InheritanceAttribute.NotInherited);
    }

    [ReadOnly(true)]
    public override string GetName(IComponent comp)
    {
        return base.GetName(comp);
    }
}

在此处输入图像描述


推荐阅读