Поделиться через


Attributes and Design-Time Support

Caution

This content was written for .NET Framework. If you're using .NET 6 or a later version, use this content with caution. The designer system has changed for Windows Forms and it's important that you review the Designer changes since .NET Framework article.

Design-time support extensions are typically implemented in code that exists separately from the code for a component. A variety of attributes are used to associate design-time support providers with a type or an individual member of a type.

Attributes for Associating Design-Time Support

A DesignerAttribute associates a designer with a type. A TypeConverterAttribute associates a type converter with a type or type member. An EditorAttribute associates a UI type editor with a type or type member.

Attributes for Customizing Component Initialization

You can specify a default value for a property to be set when a component is loaded at design time by applying a DefaultValueAttribute to a property. A DefaultValueAttribute overrides a value set by component initialization code at design time, but the attribute does not override a value set by a designer.

Attributes for Customizing Properties Window Behavior

You can indicate whether a property or event should be listed in a Properties window by applying a BrowsableAttribute to it. You can also modify the set of properties and events exposed to the Properties window at design time using a designer that implements the IDesignerFilter interface. You can specify the category under which a property or event should be listed in the Properties window by applying a CategoryAttribute to the property or event. You can specify a description to be displayed for a property or event in the Properties window by applying a DescriptionAttribute to the property or event.

You can specify whether a property can be set only at design time by applying a DesignOnlyAttribute to the property. You can specify whether a property is read only or read/write at design time by applying a ReadOnlyAttribute to the property.

You can specify whether a property should be listed with its name in parentheses in the Properties window by applying a ParenthesizePropertyNameAttribute to the property with a value of true.

You can specify whether a property that has nested, or child, properties should be notified when the value of a nested property changes by applying a NotifyParentPropertyAttribute to the nested property that should raise the notification.

You can specify whether the properties for a component should be refreshed, no properties should be refreshed, or the designer view should be repainted by applying a RefreshPropertiesAttribute with an appropriate RefreshProperties value to a property or event.

Attributes for Customizing Design-Time Serialization Behavior

You can specify whether the values of a property are serialized, or whether the values of a collection property are serialized, by applying a DesignerSerializationVisibilityAttribute with an appropriate DesignerSerializationVisibility enumeration value to the property. There is extensive support for this task in Visual Studio. Walkthrough: Serializing Collections of Standard Types with the DesignerSerializationVisibilityAttribute
Walkthrough: Serializing Collections of Standard Types with the DesignerSerializationVisibilityAttribute
Walkthrough: Serializing Collections of Standard Types with the DesignerSerializationVisibilityAttribute
Walkthrough: Serializing Collections of Standard Types with the DesignerSerializationVisibilityAttribute

You can specify that a type is serializable by applying a SerializableAttribute to the type. You can provide custom serialization by implementing the ISerializable interface or providing a custom serializer. For more information about serialization, see Serialization [from BPUEDev11].

For more information about commonly used design-time attributes, see Design-Time Attributes for Components.

Applying Attributes

Design-time attributes are applied to properties, events, classes, and even to assemblies. The following code example shows attributes applied to a class and then to properties and events.

' The attribute is the element in angle brackets, and the parameters 
' in the attribute syntax are arguments of the constructor 
' of the attribute class.
' 
' Attributes applied at the class level.
<DefaultEvent("ValueChanged"), _
DefaultProperty("Number")> _
Public Class MyControl
   Inherits Control   
   ...
   ' Attribute applied to a property.
   <DefaultValue(False)> _
   Public Shadows ReadOnly Property TabStop() As Boolean
      ...
   End Property
   
   ' Attribute applied to a property.
   <CategoryAttribute("Data")> _
   Public ReadOnly Property Number() As Integer
      ...
   End Property 
   
   ' Attribute applied to an event.
   <Description("Raised when the Value displayed changes.")>  _
   Public Event ValueChanged As EventHandler
   ...
End Class
// The attribute is the element in brackets, and the parameters in 
// the attribute syntax are arguments of the constructor 
// of the attribute class.
// 
// Attributes applied at the class level.
[DefaultEvent("ValueChanged")]
[DefaultProperty("Number")]
public class MyControl : Control {
   ...
   // Attribute applied to a property.
   [DefaultValue(false)]
   public new bool TabStop {...
   }

   // Attribute applied to a property.
   [CategoryAttribute("Data")]
   public int Number {...}

   // Attribute applied to an event.
   [Description("Raised when the Value displayed changes.")]
   public event EventHandler ValueChanged;
}

By convention, attribute classes are named AttributeNameAttribute. The System.ComponentModel namespace contains many base attribute classes.

Design-Time Attributes and Inheritance

When you derive a component or control from a base component that has design-time attributes, your component inherits the design-time functionality of the base class. If the base functionality is adequate for your purposes, you do not have to reapply the attributes. However, you can override attributes of the same type or apply additional attributes to the derived component. The following code fragment shows a custom control that overrides the Text property inherited from Control by overriding the BrowsableAttribute attribute applied in the base class.

Public Class MyControl
   Inherits Control
   ' The base class has [Browsable(true)] applied to the Text property.
   <Browsable(False)>  _
   Public Overrides Property [Text]() As String
      ...
   End Property 
   ...
End Class
public class MyControl : Control {
// The base class has [Browsable(true)] applied to the Text property.
[Browsable(false)]
 public override string Text {...}
...
}

Applying a Type Converter, UI Type Editor, or Designer Attribute

To associate a design-time support provider with a type or type member, apply the appropriate type of attribute on the line above the class declaration or member declaration. The following code example shows a TypeConverterAttribute applied to a type.

<TypeConverter(GetType(MyColorConverter)), _
Editor(GetType(MyColorEditor), GetType(UITypeEditor))> _
Structure MyColor
   ...
End Structure
[ TypeConverter(typeof(MyColorConverter))]
[ Editor(typeof(MyColorEditor), typeof(UITypeEditor))] 
struct MyColor {...}

If the type of a property does not have a type converter or UI type editor associated with it, or if you want to override the default type converter or UI type editor associated with the type of a property, you can apply an attribute to the property itself. To associate a type converter with a property, apply a TypeConverterAttribute to the property declaration, as shown in the following code example.

<TypeConverter(GetType(PointConverter))> _
Public Property MyLocation() As Point
   ...
End Property       
[ TypeConverter(typeof(PointConverter))]
        public Point MyLocation {...}  

To associate a UI type editor with a property, apply an EditorAttribute to the property, as shown in the following code example.

<Editor(GetType(FlashTrackBarDarkenByEditor), _
GetType(UITypeEditor))>  _
Public Property DarkenBy() As Byte
   ...
End Property
[ Editor(typeof(FlashTrackBarDarkenByEditor), typeof(UITypeEditor))]
        public byte DarkenBy {...}

A designer can be associated with a type, but not a property. To associate a designer with a type, apply a DesignerAttribute directly above the class declaration, as shown in the following code example.

<Designer(GetType(HelpLabel.HelpLabelDesigner))> _
Public Class HelpLabel
   Inherits System.Windows.Forms.Control
   Implements System.ComponentModel.IExtenderProvider
   ...
End Class
    [Designer(typeof(HelpLabel.HelpLabelDesigner))]
    public class HelpLabel : System.Windows.Forms.Control, System.ComponentModel.IExtenderProvider {...}

Note

In the above examples, the constructors for the TypeConverterAttribute,EditorAttribute, and DesignerAttribute classes accept System.Type objects as their arguments. This form of constructor for these attributes works if the type is in the same assembly as the design-time classes. If the design-time classes are in a different assembly, then a different form of the attribute constructor (called the assembly-qualified format) is needed, as shown in the following code example.

<Designer("System.Windows.Forms.Design.DocumentDesigner, System.Design")>  _
Public Class MyForm
   Inherits Form
   ...
End Class
[Designer("System.Windows.Forms.Design.DocumentDesigner, System.Design")]
public class MyForm : Form {...}

Assembly-Level Design-Time Attribute

ASP.NET provides an assembly-level attribute (System.Web.UI.TagPrefixAttribute) that enables a control developer to specify a tag prefix for an ASP.NET control. The tag prefix is automatically injected by Visual Studio in the Register directive for the control, so that the control can be used declaratively on the page with the pre-specified tag prefix (<tagprefix:controlname runat = server /> ).

Note

The TagPrefixAttribute works only in visual designers. If you author ASP.NET pages using a text editor such as Notepad, you need to specify the tag prefix and the namespace yourself in the Register directive for the control.

The following code example shows how to apply the TagPrefixAttribute. The first argument to the attribute's constructor specifies the namespace and the second specifies the tag prefix.

<assembly: TagPrefix("SimpleControls", "simple")>
Namespace SimpleControls
   <Designer("SimpleControl.Design.SimpleDesigner, SimpleControl")>  _
   Public Class SimpleControl
      Inherits System.Web.UI.WebControls.WebControl
      ...
   End Class 
End Namespace
[ assembly:TagPrefix("SimpleControls", "simple") ]
namespace SimpleControls {
    [
        Designer("SimpleControl.Design.SimpleDesigner, SimpleControl")
    ]
    public class SimpleControl : System.Web.UI.WebControls.WebControl {}
}

See Also

Tasks

How to: Implement a Type Converter

How to: Implement a UI Type Editor

How to: Apply Attributes in Windows Forms Controls

Concepts

Attributes in Windows Forms Controls

Design-Time Attributes for Components

Other Resources

Extending Design-Time Support

Custom Designers