需要从 属性Grid 中为 .NET Winforms 控件隐藏仅供设计师使用的 属性 第二部分
Need To Hide A Designer-Only Property From PropertyGrid For A .NET Winforms Control Part II
这是以下问题的后续问题:
我已将默认的 TypeDescriptorFilterService 替换为我自己的实现(太酷了!),并且 FilterProperties 事件处理程序正在触发。我看到上一个问题如何帮助隐藏那些特定的 TableLayoutPanel 属性。
现在我对一个项目有一个更一般的需求,就是隐藏某些属性。我当前的具体目标是为我的子类 Windows Form 对象隐藏“(Name)”属性(我利用设计器的 .NET 项目在内部管理对象名称并且不想让用户更改甚至在某些条件下看到该值)。要隐藏名称 属性(实际上在 属性 网格上显示为 (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;
}
MyMyExtendedDesignerObjects.Form
继承自 System.Windows.Forms.Form。虽然我的表单对象 (MyExtendedDesignerObjects.Form
) 也是一个 IDesignerFilter,但我不知道 how/where 连接其设计器的 PreFilterProperties 事件处理程序。
我想一旦我可以连接这个预过滤器逻辑,那么我就可以管理我为这个项目设定的所有 属性 网格 属性- 可见性目标。
感谢您的阅读。
名称属性是一个特殊的属性,它是由设计器扩展程序提供者添加的。您不能使用此方法隐藏它,您需要找到创建 Name
属性 的扩展程序提供程序并将其替换为另一个创建 Name
属性 的扩展程序提供程序具有 Browsable(false)
.
但对于其余属性,您可以在 PostFilterProperties
之后隐藏它们,方法是用 Browsable(false)
装饰它们
示例 1 - 隐藏 Locked
和 Tag
属性
请注意一点: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
然后删除了现有的 NameExtenderProvider
和 NameInheritedExtenderProvider
并用我的自定义实现替换它们。自定义实现本质上是我使用 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);
}
}
这是以下问题的后续问题:
我已将默认的 TypeDescriptorFilterService 替换为我自己的实现(太酷了!),并且 FilterProperties 事件处理程序正在触发。我看到上一个问题如何帮助隐藏那些特定的 TableLayoutPanel 属性。
现在我对一个项目有一个更一般的需求,就是隐藏某些属性。我当前的具体目标是为我的子类 Windows Form 对象隐藏“(Name)”属性(我利用设计器的 .NET 项目在内部管理对象名称并且不想让用户更改甚至在某些条件下看到该值)。要隐藏名称 属性(实际上在 属性 网格上显示为 (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;
}
MyMyExtendedDesignerObjects.Form
继承自 System.Windows.Forms.Form。虽然我的表单对象 (MyExtendedDesignerObjects.Form
) 也是一个 IDesignerFilter,但我不知道 how/where 连接其设计器的 PreFilterProperties 事件处理程序。
我想一旦我可以连接这个预过滤器逻辑,那么我就可以管理我为这个项目设定的所有 属性 网格 属性- 可见性目标。
感谢您的阅读。
名称属性是一个特殊的属性,它是由设计器扩展程序提供者添加的。您不能使用此方法隐藏它,您需要找到创建 Name
属性 的扩展程序提供程序并将其替换为另一个创建 Name
属性 的扩展程序提供程序具有 Browsable(false)
.
但对于其余属性,您可以在 PostFilterProperties
之后隐藏它们,方法是用 Browsable(false)
示例 1 - 隐藏 Locked
和 Tag
属性
请注意一点: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
然后删除了现有的 NameExtenderProvider
和 NameInheritedExtenderProvider
并用我的自定义实现替换它们。自定义实现本质上是我使用 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);
}
}