我很想在C#/。NET解决方案中使用Winforms设计器(System.ComponentModel.Design命名空间),以便我的用户可以访问正在运行的应用程序中的表单设计器。它的大部分工作都很好,但是我遇到了一个非常具体的问题:我在Microsoft控件上遇到了一个仅在设计时出现的属性,即该控件在设计时的实例。我想隐藏该属性,以便用户在将该控件的实例放置在程序的Winform设计图实现上时无法对其进行修改。
详细信息:当用户将控件从工具箱拖放到设计器图面时,我确保选择了该控件的新添加的设计器实例(以便它显示调整大小的句柄,以便属性网格显示该控件)。控件的设计时属性)。通过使用选择服务的 GetSelectedComponents()方法,并将属性网格的 SelectedObjects 属性分配给结果,将设计器图面上的选定对象绑定到属性网格。
我的工具箱上的许多控件都是.NET控件。其中之一是.NET Winforms TableLayoutPanel 控件。当将该控件的实例放置在设计器图面上时,您将在绑定的 PropertyGrid 中看到一个 Columns 属性。我想隐藏该属性,以使其不会出现在 PropertyGrid 中。
问题是 TableLayoutPanel 类型的属性列表中似乎不存在此Columns属性-例如,使用selectedComponents[0].GetType().GetProperties()
不包含< strong>列属性。另外,我无法为现有的 Columns 属性创建新属性或替代属性,因为在设计时该属性不会显示为 TableLayoutPanel 控件的公开属性,因此无法用Browsable(false)
属性修饰它。
我似乎无法利用PreFilterProperties
或PostFilterProperties
,因为我无法交互和自定义 TableLayoutPanel的设计器。
如何隐藏 TableLayoutPanel 的 Columns 设计器属性,以使该属性不会出现在 PropertyGrid 中,而无需编写我的自己的设计师?
答案 0 :(得分:2)
如果您想避免自己写TableLayoutPanelDesigner
,那么这里是我可以建议的解决方法。
ITypeDescriptorFilterService
是负责调用设计者的PreFilterProperties
方法的接口。 DesignSurface
类具有在其ServiceContainer
中注册的该接口的实现的实例。因此,您可以删除现有的注册实例,并注册自己的ITypeDescriptorFilterService
实现的新实例。
在新的实现中,重写FilterProperties
并执行您认为合适的任何事情,例如,您可以检查组件的类型是否为TableLayoutPanel
,然后不要调用其设计者{{1 }}。
然后要包装该解决方案,您需要通过从PreFilterProperties
类派生并删除已注册的DesignSurface
并注册您创建的所需实例来创建自己的设计图。
示例
仅供参考,您要查找的属性的名称为ITypeDescriptorFilterService
,默认情况下具有ColumnStyles
属性。但是Browsable(false)
的默认设计器使用可浏览的版本替换了此属性。
在此示例中,我所做的是阻止设计器使这些属性可见。
首先提供TableLayoutPanel
的自定义实现。实际上,以下示例是ITypeDescriptorFilterService
程序集中的现有实现,我更改了其System.Design
方法,并检查组件是否为FilterProperties
,但我什么也不要求。>
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();
}
}
和Columns
属性被隐藏了。
您需要隐藏Rows
和ColumnCount
属性,还需要隐藏分配给用于编辑/添加/删除列和行的动词。