Skip to main content
A newer version of this page is available. .

Custom Editors

  • 13 minutes to read

This document provides general information on creating custom editors that you can use for standalone and in-place editing (e.g., in the GridControl, TreeList and BarManager). You can refer to the Editor Class Structure topic, which describes the object model applied in the XtraEditors library with which your editors must comply.

The document consists of the following sections.

General Information

Creating a custom editor involves three steps:

  • Create a custom editor class implementing specific behavior

    If you need to implement completely new functionality for your editor, you can inherit from the BaseEdit class, which is the root ancestor for all editors in the XtraEditors library. If the editor you are creating has something in common with an existing editor, you can inherit from the appropriate editor instead. For information on the editors included in the library, see the Editor Hierarchy topic.

  • Create a custom repository item class storing editor-specific properties

    Each editor in the XtraEditors library has an associated object called a repository item, which stores editor-specific settings and event handlers. For instance, settings for a DateEdit control are encapsulated by the RepositoryItemDateEdit class, while settings for an ImageComboBoxEdit editor are provided by the RepositoryItemImageComboBox class. All repository items are derived from the base RepositoryItem class.

    For each custom editor, you must create a custom repository item class. This class should at least override the EditorTypeName property. In addition, the custom repository item can introduce new settings, new events or redefine the processing of default settings. If you derive an editor from the BaseEdit class, you should create a new repository item by deriving it from the RepositoryItem class. For example, if you create a DateEdit descendant, you should inherit the new repository item from the RepositoryItemDateEdit class.

    The editor’s Properties property must be overridden in order to return a corresponding repository item.

  • Register the editor and repository item

    Each editor must be registered in an internal registration collection so that this editor can then be accessed using a PersistentRepository component or any container control (XtraGrid, XtraBars, etc.). The registration code must be placed in a static method of the repository item class.

These three steps, described below in detail, involve the creation of custom editor infrastructure classes. You can create them manually in code, or use the Windows Data Editor template accessible in the Template Gallery to generate these classes automatically. To open this template, right-click your project in the Solution Explorer and select Add DevExpress Item -> New Item.

CustomEditor-LaunchTemplateGallery

In the project gallery that will open, select the Windows Data Editor template. The template allows you to select the base editor and specify additional generation options.

CustomEditor-TemplateGallery

Use the check boxes provided to specify whether to generate custom classes responsible for painting, storing view information, and dropdown window functionality. When deselecting a certain check box, the default class that performs the corresponding operations will be used by the generated custom editor.

Generally, you place the code that implements custom editors in a separate library. For instance, after compiling the library, it can be added to an application project by selecting PROJECT | Add Reference in the main menu of Visual Studio. From then on, the custom editor can be accessed by the PersistentRepository‘s Designer, or any container control’s Designer.

Note

Custom editors attached to the application are searched by the Designer only when it is opened for the first time. So, if you open the Designer and add a reference to the editors library, the editor will not be displayed the next time the Designer is opened. In that case, you need to reload the application to see the custom editors that have been added.

Custom Editor Class

Each custom editor should override the EditorTypeName property and return a unique name, which identifies the control from among the existing editors in the XtraEditors library. The string returned by this property should match the result returned by the corresponding repository item’s EditorTypeName property, and also match the string used when registering the editor in the XtraEditors library (see below).

If a new repository item class is created for the editor, then the editor’s Properties property must be overridden. You should only override the get method, and this must only return the Properties object type of the base class - cast to a corresponding repository item type. Note that the value of the Properties property must not be created manually. A corresponding object is created automatically based on the registration information.

The custom editor must also provide a static constructor, which calls the registration code. See the example below.

Note

To make the custom editor available in the Toolbox, apply the ToolboxItem(true) attribute to the editor class.

Custom Repository Item Class

For the repository item, you need to override the EditorTypeName property, which should return a unique name identifying the corresponding editor. The name must match the name returned by the editor’s EditorTypeName property. EditorTypeName is primarily used internally. It’s also valuable in specific cases at design time (for instance, in the PersistentRepository editor). You should also provide the same editor type name when registering the editor (see below).

The repository item class must contain a static constructor, which should call the registration code. The registration code must be placed in a separate static method.

If you add new properties or events to the repository item, then you need to override the Assign method. This must copy the settings from a repository item passed as the method’s parameter to the current repository item.

Editor Registration

The code that registers a new editor must be placed in a separate static method of the repository item class. This registration code links the custom editor with the corresponding repository item, view info and painter objects. This information is used when creating both standalone and in-place editors.

As mentioned above, the custom editor and repository item must contain static constructors that call this registration method.

The following attribute must be added to the repository item class: [UserRepositoryItem(“RegisterCustomEdit”)] (where “RegisterCustomEdit” is the name of the static registration method).

To provide registration information on the custom editor, an DevExpress.XtraEditors.Registrator.EditorClassInfo object must be created. You can use the following overload of the class’s constructor to provide registration information:


public EditorClassInfo(
    string name,            // Specifies the editor's name.
    Type editorType,        // Specifies the type of the editor class.
    Type repositoryType,    // Specifies the type of the custom repository item class.
    Type viewInfoType,      // Specifies the type of the editor's ViewInfo class.
    BaseEditPainter painter,// An instance of the editor's Painter class.
    bool designTimeVisible, // Specifies whether or not the custom editor 
                            // will be visible at design time within container controls 
                            // (for instance, when creating an in-place editor
                            // within Grid Control or XtraBars).
    Image image,            // Specifies the image that will be displayed along 
                            // with the editor's name within container controls.
    Type accessibleType     // Specifies the type of the object 
                            // that provides accessibility information.
);

Generally, the viewInfoType and accessibleType parameters need to be set to ViewInfo and AccessibilityInformation types that correspond to the custom editor’s ancestor. For the painter parameter, you need to specify an instance of a corresponding Painter class. The following table describes the classes that correspond to specific standard editors in the XtraEditors library:

Editor

ViewInfo class (the DevExpress.XtraEditors.ViewInfo namespace)

Painter class (the DevExpress.XtraEditors.Drawing namespace)

AccessibilityInformation class (the DevExpress.Accessibility namespace)

BaseEdit

BaseEditViewInfo

BaseEditPainter

BaseEditAccessible

BreadCrumbEdit

BreadCrumbEditViewInfo

BreadCrumbEditPainter

ComboBoxEditAccessible

ButtonEdit

ButtonEditViewInfo

ButtonEditPainter

ButtonEditAccessible

CalcEdit

CalcEditViewInfo

ButtonEditPainter

PopupEditAccessible

CameraControl

CameraControlViewInfo

CameraControlPainter

none

CheckedComboBoxEdit

PopupContainerEditViewInfo

ButtonEditPainter

PopupEditAccessible

CheckEdit

CheckEditViewInfo

CheckEditPainter

CheckEditAccessible

ColorEdit

ColorEditViewInfo

ColorEditPainter

PopupEditAccessible

ColorPickEdit

ColorEditViewInfo

ColorEditPainter

PopupEditAccessible

ComboBoxEdit

ComboBoxViewInfo

ButtonEditPainter

PopupEditAccessible

DateEdit

DateEditViewInfo

ButtonEditPainter

PopupEditAccessible

FontEdit

ComboBoxViewInfo

ButtonEditPainter

PopupEditAccessible

GridLookUpEdit

GridLookUpEditBaseViewInfo

ButtonEditPainter

PopupEditAccessible

HyperLinkEdit

HyperLinkEditViewInfo

HyperLinkEditPainter

ButtonEditAccessible

ImageComboBoxEdit

ImageComboBoxEditViewInfo

ImageComboBoxEditPainter

PopupEditAccessible

ImageEdit

ImageEditViewInfo

BlobBaseEditPainter

PopupEditAccessible

LookUpEdit

LookUpEditViewInfo

ButtonEditPainter

PopupEditAccessible

MarqueeProgressBarControl

MarqueeProgressBarViewInfo

ProgressBarPainter

ProgressBarAccessible

MemoEdit

MemoEditViewInfo

MemoEditPainter

TextEditAccessible

MemoExEdit

MemoExEditViewInfo

BlobBaseEditPainter

PopupEditAccessible

MRUEdit

MRUEditViewInfo

ButtonEditPainter

PopupEditAccessible

PictureEdit

PictureEditViewInfo

PictureEditPainter

BaseEditAccessible

PopupContainerEdit

PopupContainerEditViewInfo

ButtonEditPainter

PopupEditAccessible

PopupGalleryEdit

PopupGalleryEditViewInfo

ButtonEditPainter

PopupEditAccessible

ProgressBarControl

ProgressBarViewInfo

ProgressBarPainter

ProgressBarAccessible

RadioGroup

RadioGroupViewInfo

RadioGroupPainter

RadioGroupAccessible

RatingControl

RatingControlViewInfo

RatingControlPainter

RatingControlAccessible

RangeTrackBarControl

RangeTrackBarViewInfo

RangeTrackBarPainter

RangeTrackBarAccessible

RichTextEdit/RepositoryItemRichTextEdit

Note

The RichTextEdit is a simplified version of the RichEditControl.

It is hidden from the Toolbox, and is not intended to be used as a standalone control.

However, the RepositoryItemRichTextEdit object is public,

and it can be used to display RTF data in container controls (XtraGrid, XtraTreeList, etc.).

To display/edit RTF data in a standalone control,

use RichEditControl.

RichTextEditViewInfo

RichTextEditPainter

TextEditAccessible

SearchLookUpEdit

SearchLookUpEditBaseViewInfo

ButtonEditPainter

PopupEditAccessible

SearchControl

SearchControlViewInfo

ButtonEditPainter

PopupEditAccessible

SparklineEdit

SparklineEditViewInfo

SparklineEditPainter

BaseEditAccessible

SpinEdit

BaseSpinEditViewInfo

ButtonEditPainter

BaseSpinEditAccessible

TextEdit

TextEditViewInfo

TextEditPainter

TextEditAccessible

TimeEdit

BaseSpinEditViewInfo

ButtonEditPainter

BaseSpinEditAccessible

TimeSpanEdit

TimeSpanEditViewInfo

TimeSpanEditPainter

TimeSpanEditAccessible

TokenEdit

TokenEditViewInfo

TokenEditPainter

TokenEditAccessible

ToggleSwitch

ToggleSwitchViewInfo

ToggleSwitchPainter

ToggleSwitchAccessible

TrackBarControl

TrackBarViewInfo

TrackBarPainter

TrackBarAccessible

TreeListLookUpEdit

TreeListLookUpEditBaseViewInfo

ButtonEditPainter

PopupEditAccessible

ZoomTrackBarControl

ZoomTrackBarViewInfo

ZoomTrackBarPainter

ZoomTrackBarAccessible

After the EditorClassInfo has been created, it must be added to the static DevExpress.XtraEditors.Registrator.EditorRegistrationInfo.Default.Editors collection. See the code below for an example of creating a custom editor.

Dropdown editors support popup forms in which an end-user can select values or edit data. When defining a custom dropdown editor, you can override the PopupBaseEdit.CreatePopupForm method to provide your own popup form. The following table lists popup form types used by DevExpress dropdown editors. You can derive your popup form from one of these classes:

Dropdown Editor Popup Form Type (a PopupBaseForm descendant)
CalcEdit PopupCalcEditForm
CheckedComboBoxEdit CheckedPopupContainerForm
ColorEdit PopupColorEditForm
ComboBoxEdit PopupListBoxForm
DateEdit PopupDateEditForm or VistaPopupDateEditForm
ImageComboboxEdit PopupImageComboBoxEditListBoxForm
ImageEdit ImagePopupForm
LookUpEdit PopupLookUpEditForm
MemoExEdit MemoExPopupForm
MRUEdit PopupMRUForm
PopupContainerEdit PopupContainerForm
TokenEdit TokenEditPopupForm
BreadCrumbEdit BreadCrumbPopupForm

Example

Consider this simple example for creating a custom editor (CustomEdit). It represents the TextEdit class descendant. The new repository item class is RepositoryItemCustomEdit. It introduces a new property (UseDefaultMode) for illustration purposes.


using System.Drawing;
using System.Reflection;
using System.ComponentModel;
using System.Windows.Forms;
using System.Reflection;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Repository;
using DevExpress.XtraEditors.Registrator;
using DevExpress.XtraEditors.Drawing;
using DevExpress.XtraEditors.ViewInfo;
using DevExpress.Accessibility;

namespace DevExpress.CustomEditors {

    //The attribute that points to the registration method
    [UserRepositoryItem("RegisterCustomEdit")]
    public class RepositoryItemCustomEdit : RepositoryItemTextEdit {

        //The static constructor that calls the registration method
        static RepositoryItemCustomEdit() { RegisterCustomEdit(); }

        //Initialize new properties
        public RepositoryItemCustomEdit() {            
            useDefaultMode = true;
        }

        //The unique name for the custom editor
        public const string CustomEditName = "CustomEdit";

        //Return the unique name
        public override string EditorTypeName { get { return CustomEditName; } }

        //Register the editor
        public static void RegisterCustomEdit() {
            //Icon representing the editor within a container editor's Designer
            Image img = null;
            try {
                img = (Bitmap)Bitmap.FromStream(Assembly.GetExecutingAssembly().
                  GetManifestResourceStream("DevExpress.CustomEditors.CustomEdit.bmp"));
            }
            catch {
            }
            EditorRegistrationInfo.Default.Editors.Add(new EditorClassInfo(CustomEditName, 
              typeof(CustomEdit), typeof(RepositoryItemCustomEdit), 
              typeof(TextEditViewInfo), new TextEditPainter(), true, img, typeof(TextEditAccessible)));
        }

        //A custom property
        private bool useDefaultMode;

        public bool UseDefaultMode {
            get { return useDefaultMode; }
            set {
                if(useDefaultMode != value) {
                    useDefaultMode = value;                        
                    OnPropertiesChanged();
                }
            }
        }

        //Override the Assign method
        public override void Assign(RepositoryItem item) {
            BeginUpdate(); 
            try {
                base.Assign(item);
                RepositoryItemCustomEdit source = item as RepositoryItemCustomEdit;
                if(source == null) return;
                useDefaultMode = source.UseDefaultMode;
            }
            finally {
                EndUpdate();
            }
        }
    }

    [ToolboxItem(true)]
    public class CustomEdit : TextEdit {

        //The static constructor that calls the registration method
        static CustomEdit() { RepositoryItemCustomEdit.RegisterCustomEdit(); }

        //Initialize the new instance
        public CustomEdit() {
            //...
        }

        //Return the unique name
        public override string EditorTypeName { get { return 
            RepositoryItemCustomEdit.CustomEditName; } }

        //Override the Properties property
        //Simply type-cast the object to the custom repository item type
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public new RepositoryItemCustomEdit Properties {
            get { return base.Properties as RepositoryItemCustomEdit; }
        }

    }
}

The above registration method associates the custom image (which was added as a resource to the project) with the editor. This image will be displayed at design time in a PersistentRepository‘s Designer or a container editor’s Designer.

To add an image as a resource to the project, do the following:

  • Right-click the project in the Solution Explorer and select Add | Existing Item…. Load the custom image that will be associated with the editor.
  • Select the image added in the Solution Explorer. Its name must match the name of the editor. If not, rename the image (for example, by pressing the F2 key).
  • Right-click the image in the Solution Explorer and select Properties. In the Properties window, set the Build Action item to Embedded Resource.

The full name used to refer to the image is the value of the Default Namespace setting plus the name of the image. The Default Namespace must be set to the name of the namespace where the custom editor is declared. To change the Default Namespace setting, right click the project in the Solution Explorer and select Properties. In the invoked dialog, modify the Default Namespace setting (Root Namespace in the VB IDE). In the above example, it must be set to “DevExpress.CustomEditors”.

For additional examples on creating custom editors, refer to the MyControls1 demo located in the following folder: “%PUBLIC%\Documents\DevExpress Demos 18.2\Components\WinForms\CS".

See Also