Back to Devexpress

How to: Create custom 'fixed' item

windowsforms-4233-controls-and-libraries-form-layout-managers-layout-and-data-layout-controls-examples-how-to-create-custom-fixed-item.md

latest13.1 KB
Original Source

How to: Create custom 'fixed' item

  • Aug 01, 2019
  • 7 minutes to read

Specific layout items are constantly displayed in the Customization Form, and are never removed from the Customization Form when dragged onto a Layout Control. These items are called ‘fixed’. They come first, and are painted bold in the Customization Form. Currently, the Layout Control supports the following predefined ‘fixed’ items: Empty Space Items, Label, Separator and Splitter.

The LayoutControl.RegisterFixedItemType method allows a custom ‘fixed’ item to be registered for runtime use in a Layout Control. This item will be constantly displayed in the Customization Control at runtime, and when an end-user drops it onto a Layout Control, your custom code will be called and an instance of it will be created.

First, create a custom ‘fixed’ item by deriving it from the LayoutControlItem class and implementing the DevExpress.XtraLayout.IFixedLayoutControlItem interface. Second, the item must be registered via the LayoutControl.RegisterFixedItemType method.

The following example shows how to create a custom ‘fixed’ item, named MyFixedLabelItem , representing a link displaying a URL. The item will contain a LinkLabel control. The following methods have been overridden and added:

  • The TypeName property must return the name of the “fixed” item’s type. This property must always be overridden when creating custom layout items.

  • The MyFixedLabelItem constructor contains initialization code. This constructor is called when a layout item is registered within the Layout Control, the “fixed” item is dropped onto the control or when a layout is restored from a data store.

  • The Text property specifies the current link’s text. This property is overridden to support layout serialization. This property’s value is saved/restored when a layout is saved to/restored from a data store.

  • The new Link property specifies the current link’s text. It’s synchronized with the layout item’s Text property. This property will be displayed in the Property Grid in the Customization Form. See below.

  • The IFixedLayoutControlItem.OnCreateControl method. This method is called when an instance of the “fixed” layout item is about to be created (when the “fixed” item is dragged and dropped from the Customization Form onto the form or a layout is restored from a data store). Typically, this method must be overridden to create a control to be displayed in the layout item.

  • The IFixedLayoutControlItem.OnInitialize method. Typically, this method must be overridden to initialize the created item. This method is called after the OnCreateControl method.

  • The IFixedLayoutControlItem.OnDestroy method. In this method, destroy the control that has been previously created and release all allocated resources.

  • The IFixedLayoutControlItem.CustomizationName property must return the text representing the “fixed” item in the Customization Form.

  • The IFixedLayoutControlItem.CustomizationImage property must specify an image that will be displayed next to the text specified by the CustomizationName property.

  • The IFixedLayoutControlItem.AllowChangeTextLocation property must return a value that specifies whether a specific menu item is available via the Context Menu, that allows an end-user to change the item’s text location.

  • The IFixedLayoutControlItem.AllowChangeTextVisibility property must return a value that specifies whether a specific menu item is available via the Context Menu, allowing an end-user to hide/show the item’s text.

  • The IFixedLayoutControlItem.AllowClipText property must return a value that specifies whether the item’s caption can be clipped, or it’s always displayed in its entirety.

Properties of layout items are displayed in the Customization Form’s Property Grid. The Layout Control allows only specific properties to be displayed for specific types of layout items. To do this, a BasePropertyGridObjectWrapper descendant must be created. Public properties that this class introduces will be displayed in the Property Grid. Other properties will not be available.

A custom BasePropertyGridObjectWrapper descendant must be associated with a specific layout item’s type via the LayoutControl.RegisterCustomPropertyGridWrapper method. As a result, when selecting a layout item of this type, a corresponding BasePropertyGridObjectWrapper object will be used, that will specify which properties to display.

In the example, the MyFixedLabelPropertiesWrapper class is created and associated with the MyFixedLabelItem class. The MyFixedLabelPropertiesWrapper class contains only one public property - Link. When any layout item of the MyFixedLabelItem type is selected, the Property Grid will display only the Link property.

The following image shows the result:

csharp
layoutControl1.RegisterCustomPropertyGridWrapper(typeof(MyFixedLabelItem),
            typeof(MyFixedLabelPropertiesWrapper));
        layoutControl1.RegisterFixedItemType(typeof(MyFixedLabelItem));
// The custom 'fixed' item.
public class MyFixedLabelItem : LayoutControlItem, IFixedLayoutControlItem {
    // Must return the name of the item's type
    public override string TypeName { get { return "MyFixedLabelItem"; } }
    string linkCore;
    Control controlCore = null;

    public string Link {
        get { return linkCore; }
        set {
            if (Link == value) return;
            this.linkCore = value;
            OnLinkChanged();
        }
    }
    void label_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
        //...
    }
    public override string Text {
        get { return Link; }
        set { Link = value; }
    }
    // This method is called when the Link property is changed.
    // It assigns the new link to the embedded LinkLabel control.
    protected void OnLinkChanged() {
        if (controlCore is null) return;
        controlCore.Text = Link;
    }

    // Initialize the item.
    void IFixedLayoutControlItem.OnInitialize() {
        this.linkCore = "www.devexpress.com";
        OnLinkChanged();
        TextVisible = false;
    }
    // Create and return the item's control.
    Control IFixedLayoutControlItem.OnCreateControl() {
        this.controlCore = new LinkLabel();
        ((LinkLabel)controlCore).LinkClicked += label_LinkClicked;
        return controlCore;
    }
    // Destroy the item's control.
    void IFixedLayoutControlItem.OnDestroy() {
        if (controlCore != null) {
            ((LinkLabel)controlCore).LinkClicked -= label_LinkClicked;
            controlCore.Dispose();
            controlCore = null;
        }
    }
    string IFixedLayoutControlItem.CustomizationName { get { return "DevExpress Link"; } }
    Image IFixedLayoutControlItem.CustomizationImage { get { return null; } }
    bool IFixedLayoutControlItem.AllowChangeTextLocation { get { return false; } }
    bool IFixedLayoutControlItem.AllowChangeTextVisibility { get { return false; } }
    bool IFixedLayoutControlItem.AllowClipText { get { return false; } }
    ILayoutControl IFixedLayoutControlItem.Owner { get { return base.Owner; } set { base.Owner = value; } }
}

// Specifies which properties to display in the Property Grid
public class MyFixedLabelPropertiesWrapper : BasePropertyGridObjectWrapper {
    protected MyFixedLabelItem Label { get { return WrappedObject as MyFixedLabelItem; } }
    [Description("The link's text")]
    public string Link { get { return Label.Link; } set { Label.Link = value; } }
    public override BasePropertyGridObjectWrapper Clone() {
        return new MyFixedLabelPropertiesWrapper();
    }
}
vb
layoutControl1.RegisterCustomPropertyGridWrapper(GetType(MyFixedLabelItem), GetType(MyFixedLabelPropertiesWrapper))
        layoutControl1.RegisterFixedItemType(GetType(MyFixedLabelItem))
' The custom 'fixed' item.
Public Class MyFixedLabelItem
    Inherits LayoutControlItem
    Implements IFixedLayoutControlItem
    ' Must return the name of the item's type
    Public Overrides ReadOnly Property TypeName() As String Implements IFixedLayoutControlItem.TypeName
        Get
            Return "MyFixedLabelItem"
        End Get
    End Property
    Private linkCore As String
    Private controlCore As Control = Nothing

    Public Property Link() As String
        Get
            Return linkCore
        End Get
        Set(ByVal value As String)
            If Link = value Then
                Return
            End If
            Me.linkCore = value
            OnLinkChanged()
        End Set
    End Property
    Private Sub label_LinkClicked(ByVal sender As Object, ByVal e As LinkLabelLinkClickedEventArgs)
        '...
    End Sub
    Public Overrides Property Text() As String
        Get
            Return Link
        End Get
        Set(ByVal value As String)
            Link = value
        End Set
    End Property
    ' This method is called when the Link property is changed.
    ' It assigns the new link to the embedded LinkLabel control.
    Protected Sub OnLinkChanged()
        If controlCore Is Nothing Then
            Return
        End If
        controlCore.Text = Link
    End Sub

    ' Initialize the item.
    Private Sub OnInitialize() Implements IFixedLayoutControlItem.OnInitialize
        Me.linkCore = "www.devexpress.com"
        OnLinkChanged()
        TextVisible = False
    End Sub
    ' Create and return the item's control.
    Private Function OnCreateControl() As Control Implements IFixedLayoutControlItem.OnCreateControl
        Me.controlCore = New LinkLabel()
        AddHandler (CType(controlCore, LinkLabel)).LinkClicked, AddressOf label_LinkClicked
        Return controlCore
    End Function
    ' Destroy the item's control.
    Private Sub OnDestroy() Implements IFixedLayoutControlItem.OnDestroy
        If controlCore IsNot Nothing Then
            RemoveHandler (CType(controlCore, LinkLabel)).LinkClicked, AddressOf label_LinkClicked
            controlCore.Dispose()
            controlCore = Nothing
        End If
    End Sub
    Private ReadOnly Property CustomizationName() As String Implements IFixedLayoutControlItem.CustomizationName
        Get
            Return "DevExpress Link"
        End Get
    End Property
    Private ReadOnly Property CustomizationImage() As Image Implements IFixedLayoutControlItem.CustomizationImage
        Get
            Return Nothing
        End Get
    End Property
    Private ReadOnly Property AllowChangeTextLocation() As Boolean Implements IFixedLayoutControlItem.AllowChangeTextLocation
        Get
            Return False
        End Get
    End Property
    Private ReadOnly Property AllowChangeTextVisibility() As Boolean Implements IFixedLayoutControlItem.AllowChangeTextVisibility
        Get
            Return False
        End Get
    End Property
    Private ReadOnly Property AllowClipText() As Boolean Implements IFixedLayoutControlItem.AllowClipText
        Get
            Return False
        End Get
    End Property
    Private Property Owner() As ILayoutControl Implements IFixedLayoutControlItem.Owner
        Get
            Return MyBase.Owner
        End Get
        Set(ByVal value As ILayoutControl)
            MyBase.Owner = value
        End Set
    End Property
End Class

' Specifies which properties to display in the Property Grid
Public Class MyFixedLabelPropertiesWrapper
    Inherits BasePropertyGridObjectWrapper
    Protected ReadOnly Property Label() As MyFixedLabelItem
        Get
            Return TryCast(WrappedObject, MyFixedLabelItem)
        End Get
    End Property
    <Description("The link's text")> _
    Public Property Link() As String
        Get
            Return Label.Link
        End Get
        Set(ByVal value As String)
            Label.Link = value
        End Set
    End Property
    Public Overrides Function Clone() As BasePropertyGridObjectWrapper
        Return New MyFixedLabelPropertiesWrapper()
    End Function
End Class