MSDN-元数据筛选
http://msdn.microsoft.com/zh-cn/library/tbt775x3(v=vs.100).aspx
元数据筛选允许设计器在设计时修改组件或控件所公开的属性、特性和事件。
例如,Control 具有一个名为 Visible 的属性,该属性确定控件是否可见。 但是,无论该属性的值是多少,设计时控件总是应保持可见,以便开发人员可以在设计图面上定位它。 Control 的设计器在设计时用自己的版本替换 Visible 属性,以后再恢复此属性的运行时值。
若要执行元数据筛选,设计器可以实现 IDesignerFilter 接口,或者可以向设计时服务提供程序(该程序可在设计时环境中对任何组件执行元数据筛选)添加ITypeDescriptorFilterService 实现。
如果在设计时选中了某个组件,属性浏览器会通过 TypeDescriptor 的方法来查询该组件的特性、事件和属性。 在设计模式下查询组件的特性、事件和属性时,任何实现IDesignerFilter 接口的组件的设计器都有机会修改该组件返回的特性、事件和属性的集合。 任何活动 ITypeDescriptorFilterService 的方法随后都会被调用,这样,服务就可以随意筛选特性、事件和属性。
在对组件调用 TypeDescriptor 的 Refresh 方法时,在刷新“属性”窗口时,在建立或重新建立设计模式时,以及在设置主选项内容时,通常都会查询设计模式中组件的特性、事件和属性。 其他对象或设计时环境的方法可以在其他时间调用 TypeDescriptor 的方法。
IDesignerFilter 接口定义了一组能够在设计器中重写和实现的方法,以更改设计器所管理的组件在设计时公开的属性、事件或特性。
IDesignerFilter 接口的每一个方法都以“Pre”或“Post”作为前缀。根据允许添加、更改或移除的成员类型的不同,每一方法以“Attributes”、“Events”或“Properties”作为后缀。要添加任何特性、事件或属性,使用名称以“Pre”开头的相关方法。要更改或移除任何特性、事件或属性,使用名称以“Post”开头的相关方法。以“Pre”开头的方法在紧靠名称以“Post”开头的方法之前调用。
如果您要添加一个或多个特性,可实现对 PreFilterAttributes 方法的重写,该方法将新 System.Attribute 添加到传递给该方法的 IDictionary。字典中的关键字是特性的类型 ID。若要更改或移除一个或多个特性,可实现对 PostFilterAttributes 方法的重写。
如果您要添加一个或多个事件,可实现对 PreFilterEvents 方法的重写,该方法将新 EventDescriptor 添加到传递给该方法的 IDictionary。字典中的关键字是事件的名称。若要更改或移除一个或多个事件,可实现对 PostFilterEvents 方法的重写。
如果您要添加一个或多个属性,可实现对 PreFilterProperties 方法的重写,该方法将新 PropertyDescriptor 添加到传递给该方法的 IDictionary。字典中的关键字是属性的名称。若要更改或移除一个或多个属性,可实现对 PostFilterProperties 方法的重写。
![]() |
---|
当类对实现 IDesignerFilter 的设计器进行扩展时,每个 PostMethodName 方法应在更改自己的特性之后调用基类中相应的 PostMethodName 方法,每个PreMethodName 方法应在更改自己的特性之前调用基类中相应的 PreMethodName 方法。 |
下面的代码示例块说明了 IDesignerFilter 接口的方法签名。
public interface IDesignerFilter { void PostFilterAttributes(IDictionary attributes); void PostFilterEvents(IDictionary events); void PostFilterProperties(IDictionary properties); void PreFilterAttributes(IDictionary attributes); void PreFilterEvents(IDictionary events); void PreFilterProperties(IDictionary properties); } 下面的代码示例演示 IDesignerFilter 的实现,这一实现将设计器的 Color 属性添加到关联的组件中。需要添加对 System.Design.dll 的引用。 C#VB using System; using System.ComponentModel; using System.ComponentModel.Design; using System.Drawing; using System.Windows.Forms; using System.Windows.Forms.Design; namespace IDesignerFilterSample { public class DesignerFilterDesigner : ComponentDesigner, IDesignerFilter { // Designer color property to add to component. public Color TestColor { get { return this.intcolor; } set { this.intcolor = value; } } // Color for TestColor property. private Color intcolor = Color.Azure; public DesignerFilterDesigner() {} // Adds a color property of this designer to the component. protected override void PreFilterProperties(System.Collections.IDictionary properties) { base.PreFilterProperties(properties); // Adds a test property to the component. properties.Add("TestColor", TypeDescriptor.CreateProperty(typeof(DesignerFilterDesigner), "TestColor", typeof(System.Drawing.Color), null)); } } // Component with which the DesignerFilterDesigner is associated. [Designer(typeof(DesignerFilterDesigner))] public class TestComponent : Component { public TestComponent() {} } }
有关使用 IDesignerFilter 接口实现属性筛选的“Windows 窗体”控件设计器的示例,请参见 Windows 窗体设计器示例。
通过向可在设计时提供服务的服务提供程序中添加 ITypeDescriptorFilterService 实现,可为设计时项目中的任何组件提供元数据筛选,具体方法是使用设计模式中Component 的 Site 属性返回的 ISite 所实现的 IServiceContainer 接口的 AddService 方法。
下面的代码示例演示如何添加称为 ExampleFilterService 的 ITypeDescriptorFilterService 服务。
IDesignerHost dh = (IDesignerHost)this.Component.GetService(typeof(IDesignerHost)); if( dh != null ) { // First gets any previous ITypeDescriptorFilterService to replace when // the current service is removed, and to call if the new service // implements service chaining. ITypeDescriptorFilterService itdfs = (ITypeDescriptorFilterService)dh.GetService( typeof(ITypeDescriptorFilterService)); oldService = (ITypeDescriptorFilterService)dh.GetService( typeof(ITypeDescriptorFilterService)); if(oldService != null) // Removes any old ITypeDescriptorFilterService. dh.RemoveService(typeof(ITypeDescriptorFilterService)); // Adds an ExampleFilterService that implements service chaining. dh.AddService(typeof(ITypeDescriptorFilterService), new ExampleFilterService(oldService)); }