Необходимо скрыть свойство только для дизайнера из PropertyGrid для элемента управления .NET Winforms, часть II

Это дополнительный вопрос к: Необходимо скрыть свойство только для конструктора из PropertyGrid для элемента управления.NET Winforms

Я заменил TypeDescriptorFilterService по умолчанию своей собственной реализацией (так здорово!), И обработчик событий FilterProperties запускается. Я вижу, как предыдущий вопрос помог скрыть эти конкретные свойства TableLayoutPanel.

Теперь у меня есть более общее требование к проекту - скрыть определенные свойства. Моя текущая конкретная цель - скрыть свойство "(Name)" для моего подкласса объекта Windows Form (мой проект.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. Пока мой объект формы (MyExtendedDesignerObjects.Form) также является IDesignerFilter, я не знаю, как / где подключить обработчик событий PreFilterProperties его дизайнера.

Думаю, как только я подключу эту логику предварительного фильтра, я смогу управлять всеми целями видимости свойств сетки свойств, которые у меня есть для этого проекта.

Спасибо за чтение.

1 ответ

Решение

Name property is a special property, it's added by a designer extender provider. You cannot hide it using this method, you need to find the extender provider which creates the Name property and replace it by another extender provider which creates the Name property having Browsable(false).

But for rest of properties, you can hide them after PostFilterProperties, by decorating them with Browsable(false)

Example 1 - Hide Locked and Tag property

Please pay attention to the point: Locked is a design-time property but Tag is a normal property.

Override FilterProperties method like this:

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

Example 2 - Hide Name property

In the following example, in the OnLoaded method of my custom designer surface, I have found the IExtenderProviderService and then I have removed the existing NameExtenderProvider and NameInheritedExtenderProvider and replaced them with my custom implementation. The custom implementations are essentially what I've extracted using reflector from system.design and just change the Browsable attribute to 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);
    }
}

Другие вопросы по тегам