Export (0) Print
Expand All

Metadata Filtering

Metadata filtering allows a designer to modify the set of properties, attributes and events exposed by a component or control at design time.

For example, Control has a property named Visible that determines whether the control is visible. At design time, however, the control should always remain visible, regardless of the value of this property, so that a developer can position it on the design surface. The designer for Control replaces the Visible property with its own version at design time and later restores the run-time value of this property.

To perform metadata filtering, a designer can either implement the IDesignerFilter interface, or add an ITypeDescriptorFilterService implementation to the design-time services provider that can perform metadata filtering on any component in the design-time environment.

When a component is selected at design time, the property browser queries the component for its attributes, events, and properties through the methods of a TypeDescriptor. When a component is queried for its attributes, events, and properties in design mode, any designer for the component that implements the IDesignerFilter interface is given an opportunity to modify the set of attributes, events, and properties returned by the component. The methods of any active ITypeDescriptorFilterService are called next to allow the service to do any filtering of attributes, events and properties.

A component in design mode is typically queried for its attributes, events and properties when the Refresh method of TypeDescriptor is called on the component, when the Properties window is refreshed, when design mode is established or reestablished, and when the primary selection is set. Methods of other objects or a design-time environment may call the methods of a TypeDescriptor at other times.

The IDesignerFilter interface defines a set of methods that can be overridden and implemented in a designer to alter the properties, events, or attributes exposed by the component managed by the designer at design time.

Each method of the IDesignerFilter interface is prefixed with either "Pre" or "Post". Each method is suffixed with either "Attributes", "Events", or "Properties", depending on which type of member it allows you to add, change, or remove. To add any attributes, events, or properties, use the relevant method whose name begins with "Pre". To change or remove any attributes, events, or properties, use the relevant method whose name begins with "Post". The methods whose names begin with "Pre" are called immediately before the methods whose names begin with "Post".

If you want to add an attribute or attributes, implement an override of the PreFilterAttributes method that adds the new System.Attribute to the IDictionary passed to the method. The keys in the dictionary are the type IDs of the attributes. To change or remove an attribute or attributes, implement an override of the PostFilterAttributes method.

If you want to add an event or events, implement an override of the PreFilterEvents method that adds the new EventDescriptor to the IDictionary passed to the method. The keys in the dictionary are the names of the events. To change or remove an event or events, implement an override of the PostFilterEvents method.

If you want to add a property or properties, implement an override of the PreFilterProperties method that adds the new PropertyDescriptor to the IDictionary passed to the method. The keys in the dictionary are the names of the properties. To change or remove a property or properties, implement an override of the PostFilterProperties method.

Note Note

When a class extends a designer that implements IDesignerFilter, each PostMethodName method should call the corresponding PostMethodName method of the base class after changing its own attributes, and each PreMethodName method should call the corresponding PreMethodName method of the base class before changing its own attributes.

The following code example block shows the method signatures of the IDesignerFilter interface.

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

The following code example demonstrates an implementation of IDesignerFilter that adds a Color property of the designer to the associated component. You need to add a reference to System.Design.dll.

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()
      {}
   }
}

For an example of a Windows Forms control designer that implements property filtering using the IDesignerFilter interface, see the Windows Forms Designer Sample.

You can provide metadata filtering for any component in a design-time project by adding an ITypeDescriptorFilterService implementation to the service provider that provides services at design time, using the AddService method of the IServiceContainer interface implemented by the ISite returned by the Site property of a Component sited in design mode.

The following code example demonstrates how to add an ITypeDescriptorFilterService service called ExampleFilterService.

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

For an example ITypeDescriptorFilterService implementation, see the reference documentation for the ITypeDescriptorFilterService class.

Show:
© 2014 Microsoft