New to Telerik UI for WinForms? Download free 30-day trial

Custom Items

By default, RadDropDownList displays text and image in its drop-down items. However, the default layout might not be suitable for you, and in this case you can use the flexible mechanism it features for creating visual items with custom content elements, functionality and properties.

This article demonstrates how to display detailed information for each employee from the Northwind.Employees table which is used as data source.

Figure 1: Custom visual items

WinForms RadDropDownList Custom Visual Items

1. Create a class that inherits from RadListVisualItem. Override its CreateChildElements method where you can add the desired content elements. The custom item will have no styles, because there are no defined styles for its type in the themes. You can apply the RadListVisualItem’s styles to it by defining its ThemeEffectiveType.

2. Override the Synchronize method in order to match the displayed data in the content elements with the respective DataBoundItem. As the “Photo” column in the Northwind.Employees table contains a byte array, we should convert it to Image:

Custom RadListVisualItem


public class CustomVisualItem : RadListVisualItem
{
    Font boldFont = new Font("Arial",10f, FontStyle.Bold);
    Font italicFont = new Font("Arial",10f, FontStyle.Italic);
    DockLayoutPanel mainContainer;
    StackLayoutElement leftColumn;
    StackLayoutElement rightColumn;
    LightVisualElement titleElement;
    LightVisualElement photoElement;
    LightVisualElement nameElement;
    LightVisualElement addressElement;
    LightVisualElement phoneElement;

    protected override Type ThemeEffectiveType     
    { 
        get    
        { 
            return typeof(RadListVisualItem);     
        }
    }

    protected override void CreateChildElements()
    {
        base.CreateChildElements(); 

        mainContainer = new DockLayoutPanel();
        leftColumn = new StackLayoutElement();
        rightColumn = new StackLayoutElement();
        titleElement = new LightVisualElement();
        photoElement = new LightVisualElement();
        nameElement = new LightVisualElement();
        addressElement = new LightVisualElement();
        phoneElement = new LightVisualElement();

        this.Children.Add(mainContainer);
        mainContainer.LastChildFill = true;

        leftColumn.Orientation = Orientation.Vertical;
        leftColumn.Children.Add(photoElement);
        photoElement.DrawBorder = true;

        rightColumn.Orientation = Orientation.Vertical;
        rightColumn.Children.Add(nameElement);
        nameElement.Font = boldFont;
        rightColumn.Children.Add(addressElement);
        rightColumn.Children.Add(phoneElement);
        rightColumn.Children.Add(titleElement);
        titleElement.DrawBorder = true;
        titleElement.Font = italicFont;
        titleElement.BorderBoxStyle = Telerik.WinControls.BorderBoxStyle.FourBorders;
        titleElement.BorderLeftWidth = 0;
        titleElement.BorderTopWidth = 1;
        titleElement.BorderRightWidth = 0;
        titleElement.BorderBottomWidth = 0;

        mainContainer.Children.Add(leftColumn);
        mainContainer.Children.Add(rightColumn);  
        DockLayoutPanel.SetDock(leftColumn, Telerik.WinControls.Layouts.Dock.Left);
        DockLayoutPanel.SetDock(rightColumn, Telerik.WinControls.Layouts.Dock.Right);
        leftColumn.NotifyParentOnMouseInput = true;
        rightColumn.NotifyParentOnMouseInput = true;
        titleElement.NotifyParentOnMouseInput = true;
        photoElement.NotifyParentOnMouseInput = true;
        nameElement.NotifyParentOnMouseInput = true;
        addressElement.NotifyParentOnMouseInput = true;
        phoneElement.NotifyParentOnMouseInput = true;
    }

    public override void Synchronize()
    {
        base.Synchronize();
        this.Text = string.Empty;
        DataRowView rowView = this.Data.DataBoundItem as DataRowView;
        if (rowView != null)
        {
            this.photoElement.Image = GetImageFromData(rowView.Row["Photo"] as byte[]);
            this.titleElement.Text = rowView.Row["Title"].ToString();
            this.nameElement.Text = rowView.Row["FirstName"].ToString() + " " + rowView.Row["LastName"].ToString();
            this.addressElement.Text = "Address: " + rowView.Row["Address"].ToString().Replace(System.Environment.NewLine, " ");
            this.phoneElement.Text = "Phone: " + rowView.Row["HomePhone"].ToString();
        }
    }

    private Image GetImageFromData(byte[] imageData)
    {
        const int OleHeaderLength = 78;
        MemoryStream memoryStream = new MemoryStream();
        if (HasOleContainerHeader(imageData))
        {
            memoryStream.Write(imageData, OleHeaderLength, imageData.Length - OleHeaderLength);
        }
        else
        {
            memoryStream.Write(imageData, 0, imageData.Length);
        }
        Bitmap bitmap = new Bitmap(memoryStream);
        return bitmap.GetThumbnailImage(55, 65, null, new IntPtr());
    }

    private bool HasOleContainerHeader(byte[] imageByteArray)
    {
        const byte OleByte0 = 21;
        const byte OleByte1 = 28;
        return (imageByteArray[0] == OleByte0) && (imageByteArray[1] == OleByte1);
    }
}

3. Subscribe to the CreatingVisualListItem event before populating the RadDropDownList with data and replace the default item with your custom one:

Custom RadListVisualItem


private void radDropDownList1_CreatingVisualListItem(object sender, Telerik.WinControls.UI.CreatingVisualListItemEventArgs args)
{
    args.VisualItem = new CustomVisualItem();
}

4. The last thing we need to do is to set the RadDropDownList.AutoSizeItems property to false and specify the ItemHeight:

Custom RadListVisualItem


this.radDropDownList1.AutoSizeItems = false;
this.radDropDownList1.DropDownListElement.ListElement.ItemHeight = 90;
In this article