需要从 PropertyGrid 为 .NET Winforms 控件隐藏设计器专用属性第二部分 [英] Need To Hide A Designer-Only Property From PropertyGrid For A .NET Winforms Control Part II

查看:44
本文介绍了需要从 PropertyGrid 为 .NET Winforms 控件隐藏设计器专用属性第二部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个后续问题:

This is a follow-up question to: Need To Hide A Designer-Only Property From PropertyGrid For A .NET Winforms Control

I have replaced the default TypeDescriptorFilterService with my own implementation (so cool!), and the FilterProperties event handler is firing. I see how the previous question helped to hide those specific TableLayoutPanel properties.

Now I have a more general requirement on a project to hide certain properties. My current specific goal is to hide the "(Name)" property for my subclassed Windows Form object (my .NET project that leverages the designer manages object names internally and does not want to allow users to change or even see that value under certain conditions). To hide the Name property (actually shown as (Name) on the property grid) I added this code:

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

MyMyExtendedDesignerObjects.Form inherits from System.Windows.Forms.Form. While my Form object (MyExtendedDesignerObjects.Form) is also an IDesignerFilter, I don't know how/where to wire-up its designer's PreFilterProperties event handler.

I think once I can get this pre-filter logic wired-up, then I can manage all of the property grid property-visibility goals I have for this project.

Thank you for reading.

解决方案

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

这篇关于需要从 PropertyGrid 为 .NET Winforms 控件隐藏设计器专用属性第二部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆