C# 需要从.NET Winforms控件的PropertyGrid隐藏仅设计器属性
我深入研究了在我的C#/.NET解决方案中使用Winforms designer(System.ComponentModel.Design命名空间),以便我的用户能够访问我正在运行的应用程序中的表单设计器。大部分工作正常,但我遇到了一个非常具体的问题:我在Microsoft控件上遇到了一个只在设计时出现的属性,即控件的设计时实例。我希望抑制该属性,以便用户在将该控件的实例放置在我的程序的Winform设计图面实现上时无法修改该属性 详细信息:当用户将控件从工具箱拖放到设计器表面时,我会确保选中该控件新添加的设计器实例(以便它显示调整大小句柄,并使属性网格显示该控件的设计时属性)。我使用选择服务的GetSelectedComponents()方法将设计器图面上的选定对象绑定到属性网格,并将属性网格的SelectedObjects属性指定给结果 我工具箱中的许多控件都是.NET控件。其中之一是.NET WinformsTableLayoutPanel控件。将该控件的实例放置在设计器图面上时,将在绑定的PropertyGrid中看到一个Columns属性。我希望抑制该属性,以便它不会出现在属性网格中 问题是此Columns属性似乎不存在于TableLayoutPanel类型的属性列表中,因此使用C# 需要从.NET Winforms控件的PropertyGrid隐藏仅设计器属性,c#,.net,winforms,windows-forms-designer,design-surface,C#,.net,Winforms,Windows Forms Designer,Design Surface,我深入研究了在我的C#/.NET解决方案中使用Winforms designer(System.ComponentModel.Design命名空间),以便我的用户能够访问我正在运行的应用程序中的表单设计器。大部分工作正常,但我遇到了一个非常具体的问题:我在Microsoft控件上遇到了一个只在设计时出现的属性,即控件的设计时实例。我希望抑制该属性,以便用户在将该控件的实例放置在我的程序的Winform设计图面实现上时无法修改该属性 详细信息:当用户将控件从工具箱拖放到设计器表面时,我会确保选中该
selectedComponents[0].GetType().GetProperties()
,例如,不包含Columns属性。此外,我无法为现有的Columns属性创建新属性或替代属性,因为它在设计时未显示为TableLayoutPanel控件的公开属性,因此我无法使用Browsable(false)
属性对其进行修饰
我似乎无法利用PreFilterProperties
或PostFilterProperties
,因为我无法交互和自定义TableLayoutPanel的设计器
如何抑制TableLayoutPanel的列设计器属性,使其不出现在属性网格中,而无需编写自己的设计器?如果您试图避免自己编写
TableLayoutPanelDesigner
,那么,我可以提出一个解决办法
是负责调用设计器方法的接口。该类在其ServiceContainer
中注册了该接口实现的实例。因此,您可以删除现有的已注册实例,并注册自己实现的ITypeScriptorFilterService
的新实例
在新的实现中,重写FilterProperties
并执行您认为合适的操作,例如,您可以检查组件的类型是否为TableLayoutPanel
,然后不要调用其设计器预过滤器属性
然后,为了总结解决方案,您需要通过从DesignSurface
类派生并删除已注册的ITypeDescriptorFilterService
并注册您创建的所需实例来创建自己的设计图面
示例
仅供参考,您要查找的属性的名称是ColumnStyles
,默认情况下它具有Browsable(false)
属性。但是TableLayoutPanel
的默认设计器将用可浏览的版本替换此属性
我在本例中所做的是阻止设计器使这些属性可见
首先提供ITypeDescriptorFilterService
的自定义实现。下面的一个实际上是系统中现有的实现。设计
程序集,我已更改其过滤器属性
方法,并检查组件是否为TableLayoutPanel
,我没有要求执行任何操作
using System;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms;
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");
if (typeof(TableLayoutPanel).IsAssignableFrom(component.GetType()))
return true;
IDesigner designer = this.GetDesigner(component);
if (designer is IDesignerFilter)
{
((IDesignerFilter)designer).PreFilterProperties(properties);
((IDesignerFilter)designer).PostFilterProperties(properties);
}
return designer != null;
}
}
然后通过从DesignSurface
派生来创建设计图面:
using System;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms;
public class MyDesignSurface : DesignSurface
{
public MyDesignSurface() : base()
{
this.ServiceContainer.RemoveService(typeof(ITypeDescriptorFilterService));
this.ServiceContainer.AddService(typeof(ITypeDescriptorFilterService), new TypeDescriptorFilterService());
}
}
然后,例如,通过以下方式初始化设计图面:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var surface = new MyDesignSurface();
var host = (IDesignerHost)surface.GetService(typeof(IDesignerHost));
var selectionService = (ISelectionService)surface.GetService(typeof(ISelectionService));
surface.BeginLoad(typeof(Form));
var root = (Form)host.RootComponent;
var tableLayoutPanel1 = (Control)host.CreateComponent(typeof(TableLayoutPanel), "tableLayoutPanel1");
root.Controls.Add(tableLayoutPanel1);
var view = (Control)surface.View;
view.Dock = DockStyle.Fill;
this.Controls.Add(view);
selectionService.SetSelectedComponents(new[] { tableLayoutPanel1 });
var propertyGrid1 = new PropertyGrid() { Dock = DockStyle.Right, Width = 200 };
this.Controls.Add(propertyGrid1);
propertyGrid1.SelectedObjects = selectionService.GetSelectedComponents().Cast<object>().ToArray();
}
}
公共部分类表单1:表单
{
公共表格1()
{
初始化组件();
var surface=新的MyDesignSurface();
var host=(IDesignerHost)surface.GetService(typeof(IDesignerHost));
var selectionService=(ISelectionService)surface.GetService(typeof(ISelectionService));
表面。开始加载(类型(形式));
var root=(Form)host.RootComponent;
var tableLayoutPanel1=(Control)host.CreateComponent(typeof(TableLayoutPanel),“tableLayoutPanel1”);
添加(tableLayoutPanel1);
var view=(Control)surface.view;
view.Dock=DockStyle.Fill;
this.Controls.Add(视图);
selectionService.SetSelectedComponents(新[]{tableLayoutPanel1});
var propertyGrid1=new PropertyGrid(){Dock=DockStyle.Right,Width=200};
this.Controls.Add(propertyGrid1);
propertyGrid1.SelectedObjects=selectionService.GetSelectedComponents().Cast().ToArray();
}
}
然后运行designer应用程序,您将看到列
和行
属性按预期隐藏
您需要隐藏
ColumnCount
和RowCount
属性,以及指定用于编辑/添加/删除列和行的谓词。如果有帮助,属性名称为ColumnStyles
Columns
是它的显示名。哇,我没有想到这一点,我很惊讶微软决定将ColumnStyles作为属性名而不是ColumnStyles(我想知道他们为什么这么做)