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;
        }

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);
            }
        }
    }
In this article