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

How to add image icons to RadAutoCompleteBox

Environment

Product Version Product Author
2019.2.618 RadAutoCompleteBox for WinForms Desislava Yordanova

Description

RadAutoCompleteBox allows the end-user to easily fill-in text thanks to the auto-complete functionality and tokens of text. This behavior is similar to the "To" field of Outlook and Facebook where you are filling-in the recipients to which you are going to send a message.

A common requirement is to add an image next to text in the editable part and autocomplete popup.

autocompletebox-with-icons

The following solution will demonstrate how to use the Northwind.Customers table and show the contact's image next to the name.

Solution

The easiest way to insert an image next to text in each token is to create a custom TokenizedTextBlockElement and add an ImagePritimive to it. You can assign images to the popup's items as well. For this purpose, it is necessary to subscribe to the RadAutoCompleteBox.ListElement.VisualItemFormatting event and set the image to the VisualItemFormattingEventArgs.VisualItem.Image property. You can find below a sample solution which result is illustrated in the above screenshot:

Add image icons to RadAutoCompleteBox


        Size imageSize = new Size(18, 18);

        private void RadForm1_Load(object sender, EventArgs e)
        {
            this.customersTableAdapter.Fill(this.nwindDataSet.Customers);

            this.radAutoCompleteBox1.CreateTextBlock += radAutoCompleteBox1_CreateTextBlock;
            this.radAutoCompleteBox1.TextBlockFormatting += radAutoCompleteBox1_TextBlockFormatting;
            this.radAutoCompleteBox1.ListElement.VisualItemFormatting += ListElement_VisualItemFormatting;
            this.radAutoCompleteBox1.ListElement.ItemHeight = imageSize.Height;

            this.radAutoCompleteBox1.AutoCompleteDataSource = this.customersBindingSource;
            this.radAutoCompleteBox1.AutoCompleteDisplayMember = "ContactName";
            this.radAutoCompleteBox1.AutoCompleteValueMember = "Photo";
        }

        private void radAutoCompleteBox1_TextBlockFormatting(object sender, TextBlockFormattingEventArgs e)
        {
            ImageTokenizedTextBlockElement imageToken = e.TextBlock as ImageTokenizedTextBlockElement;
            if (imageToken != null)
            {
                using (var ms = new MemoryStream(imageToken.Item.Value as byte[]))
                { 
                    imageToken.Image.Image = ResizeImage(Image.FromStream(ms), imageSize); 
                }
            }
        }

        private void radAutoCompleteBox1_CreateTextBlock(object sender, CreateTextBlockEventArgs e)
        {
            if (e.TextBlock is TokenizedTextBlockElement)
            {
                e.TextBlock = new ImageTokenizedTextBlockElement();
            }
        }

        //add an image to each contact in the autocomplete popup
        private void ListElement_VisualItemFormatting(object sender, VisualItemFormattingEventArgs args)
        {
            if (args.VisualItem.Data.Tag == null)
            {
                using (var ms = new MemoryStream(args.VisualItem.Data.Value as byte[]))
                {
                    args.VisualItem.Data.Tag = ResizeImage(Image.FromStream(ms), imageSize);
                }
            }
            args.VisualItem.Image = (Image)args.VisualItem.Data.Tag;
        }

        public static Bitmap ResizeImage(Image image, Size s)
        {
            int width = s.Width;
            int height = s.Height;
            var destRect = new Rectangle(0, 0, width, height);
            var destImage = new Bitmap(width, height);

            destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);

            using (var graphics = Graphics.FromImage(destImage))
            {
                graphics.CompositingMode = CompositingMode.SourceCopy;
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

                using (var wrapMode = new ImageAttributes())
                {
                    wrapMode.SetWrapMode(WrapMode.TileFlipXY);
                    graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
                }
            }

            return destImage;
        }


     Private imageSize As Size = New Size(18, 18)
    Private Sub RadForm1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        Me.CustomersTableAdapter.Fill(Me.NwindDataSet.Customers)
        AddHandler Me.RadAutoCompleteBox1.CreateTextBlock, AddressOf radAutoCompleteBox1_CreateTextBlock
        AddHandler Me.RadAutoCompleteBox1.TextBlockFormatting, AddressOf radAutoCompleteBox1_TextBlockFormatting
        AddHandler Me.RadAutoCompleteBox1.ListElement.VisualItemFormatting, AddressOf ListElement_VisualItemFormatting
        Me.RadAutoCompleteBox1.ListElement.ItemHeight = imageSize.Height
        Me.RadAutoCompleteBox1.AutoCompleteDataSource = Me.CustomersBindingSource
        Me.RadAutoCompleteBox1.AutoCompleteDisplayMember = "ContactName"
        Me.RadAutoCompleteBox1.AutoCompleteValueMember = "Photo"
    End Sub

    Private Sub radAutoCompleteBox1_TextBlockFormatting(ByVal sender As Object, ByVal e As TextBlockFormattingEventArgs)
        Dim imageToken As ImageTokenizedTextBlockElement = TryCast(e.TextBlock, ImageTokenizedTextBlockElement)

        If imageToken IsNot Nothing Then

            Using ms = New MemoryStream(TryCast(imageToken.Item.Value, Byte()))
                imageToken.Image.Image = ResizeImage(Image.FromStream(ms), imageSize)
            End Using
        End If
    End Sub

    Private Sub radAutoCompleteBox1_CreateTextBlock(ByVal sender As Object, ByVal e As CreateTextBlockEventArgs)
        If TypeOf e.TextBlock Is TokenizedTextBlockElement Then
            e.TextBlock = New ImageTokenizedTextBlockElement()
        End If
    End Sub

    Private Sub ListElement_VisualItemFormatting(ByVal sender As Object, ByVal args As VisualItemFormattingEventArgs)
        If args.VisualItem.Data.Tag Is Nothing Then

            Using ms = New MemoryStream(TryCast(args.VisualItem.Data.Value, Byte()))
                args.VisualItem.Data.Tag = ResizeImage(Image.FromStream(ms), imageSize)
            End Using
        End If

        args.VisualItem.Image = CType(args.VisualItem.Data.Tag, Image)
    End Sub

    Public Shared Function ResizeImage(ByVal image As Image, ByVal s As Size) As Bitmap
        Dim width As Integer = s.Width
        Dim height As Integer = s.Height
        Dim destRect = New Rectangle(0, 0, width, height)
        Dim destImage = New Bitmap(width, height)
        destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution)

        Using graphics As Graphics = graphics.FromImage(destImage)
            graphics.CompositingMode = CompositingMode.SourceCopy
            graphics.CompositingQuality = CompositingQuality.HighQuality
            graphics.InterpolationMode = InterpolationMode.HighQualityBicubic
            graphics.SmoothingMode = SmoothingMode.HighQuality
            graphics.PixelOffsetMode = PixelOffsetMode.HighQuality

            Using wrapMode As ImageAttributes = New ImageAttributes()
                wrapMode.SetWrapMode(Drawing2D.WrapMode.TileFlipXY)
                graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode)
            End Using
        End Using

        Return destImage
    End Function    

The custom TokenizedTextBlockElement's implementation is illustrated below:


    public class ImageTokenizedTextBlockElement : TokenizedTextBlockElement
    {
        private ImagePrimitive image;

        public ImagePrimitive Image
        {
            get
            {
                return this.image;
            }
        }

        protected override void CreateChildElements()
        {
            base.CreateChildElements();
            this.image = new ImagePrimitive();
            this.image.ImageLayout = System.Windows.Forms.ImageLayout.Zoom;
            this.image.StretchVertically = false;
            this.image.StretchHorizontally = false;
            this.image.MaxSize = new Size(0, 20);
            this.Children.Insert(0, this.image);
        }

        protected override RadTokenizedTextItem CreateTokenizedTextItem(string text, object value)
        {
            RadTokenizedTextItem item = base.CreateTokenizedTextItem(text, value);
            return item;
        }

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


Public Class ImageTokenizedTextBlockElement
    Inherits TokenizedTextBlockElement

    Private _image As ImagePrimitive

    Public ReadOnly Property Image As ImagePrimitive
        Get
            Return Me._image
        End Get
    End Property

    Protected Overrides Sub CreateChildElements()
        MyBase.CreateChildElements()
        Me._image = New ImagePrimitive()
        Me._image.ImageLayout = System.Windows.Forms.ImageLayout.Zoom
        Me._image.StretchVertically = False
        Me._image.StretchHorizontally = False
        Me._image.MaxSize = New Size(0, 20)
        Me.Children.Insert(0, Me._image)
    End Sub

    Protected Overrides Function CreateTokenizedTextItem(ByVal text As String, ByVal value As Object) As RadTokenizedTextItem
        Dim item As RadTokenizedTextItem = MyBase.CreateTokenizedTextItem(text, value)
        Return item
    End Function

    Protected Overrides ReadOnly Property ThemeEffectiveType As Type
        Get
            Return GetType(TokenizedTextBlockElement)
        End Get
    End Property
End Class

In this article