Skip to main content

Asynchronous Image Load in Data Grid

  • 8 minutes to read

The load of multiple large images from a data source may take quite a lot of time. The Asynchronous Image Load feature in WinExplorerView, TileView, GridView and their descendants allows you to:

  • Improve the Data Grid’s performance when showing large images on the initial Data Grid load and on scrolling through records.
  • Automatically create and cache image thumbnails (in WinExplorerView and TileView).
  • Manually create thumbnails, using a dedicated event, even if there are no images in the source.

When you enable the async image load, the View displays textual data for the currently visible records immediately. Images are loaded for these records one by one, asynchronously, in a background non-UI thread.

WinExplorerView - Async Image Loading

Note

The async image load feature is not supported when the Data Grid is bound to a BindingSource component. This component may fail when one tries to obtain its data from a different thread.

Source Images and Their Thumbnails

Every time a source image needs to be displayed within a certain viewport, this image is scaled first to create a thumbnail. If the source image is large, scaling this image down requires some time. Thus, it is best to create thumbnails once and then re-use these thumbnails on re-displaying the records.

Generating and caching thumbnails is only supported by the Data Grid when the async image load is enabled. When this feature is disabled, a thumbnail is generated for a source image every time a record needs to be displayed and re-displayed. No thumbnail caching is available in this mode.

Tip

Besides images provided by a data source, you can provide images for the Data Grid Views using unbound columns.

Asynchronous Image Load Support in Views

WinExplorer View

The View supports async image loading for all images displayed in the View’s items (records). Use the following properties to specify display images:

Tile View

The View supports the async image load feature for tile background images. Use the following property to specify the data source column that contain these background images.

Grid View and Descendants

Asynchronous image load is supported for columns that have Picture Edit inplace editors (RepositoryItemPictureEdit). Use the GridColumn.ColumnEdit property to assign an in-place editor to a column.

Important

In Grid Views, the Auto Filter Row does not work if the Asynchronous Image Load and Auto Row Height options are enabled. Disable the Auto Row Height option.

Scenario 1: You need to generate thumbnails automatically for existing source images

Applicable to: WinExplorerView and TileView.

It is assumed that the View is aware of an image column that contains source images.

Do the following:

  • Enable async image load with the OptionsImageLoad.AsyncLoad setting.
  • Set the View’s OptionsImageLoad.LoadThumbnailImagesFromDataSource property to false.
  • Optionally, set the required thumbnail size using the OptionsImageLoad.DesiredThumbnailSize property.

When the LoadThumbnailImagesFromDataSource property is set to false, the Data Grid assumes that the source image column contains large images (not small thumbnails). The Data Grid then automatically generates thumbnails of the size specified by the DesiredThumbnailSize setting, and caches them, provided that caching is enabled (the OptionsImageLoad.CacheThumbnails setting). The next time a record is re-displayed, the View shows the previously generated thumbnail.

winExplorerView1.OptionsImageLoad.AsyncLoad = true;
winExplorerView1.OptionsImageLoad.LoadThumbnailImagesFromDataSource = false;
winExplorerView1.OptionsImageLoad.DesiredThumbnailSize = new Size(48, 48);

WinExplorer View API:

Tile View API:

Scenario 2: You need to generate thumbnails manually (a source image column is known).

Applicable to: WinExplorerView, TileView, and GridView.

It is assumed that the View is aware of an image column that can contain source images. The target image column can contain images or links to images in all, none or only several records.

Do the following:

  • Enable async image load with the OptionsImageLoad.AsyncLoad setting.
  • Set the View’s OptionsImageLoad.LoadThumbnailImagesFromDataSource property to false (for WinExplorerView and TileView)
  • Handle the View’s GetThumbnailImage event to supply custom thumbnail images.

    The GetThumbnailImage event fires for each record, regardless of whether it contains an image in the source image column or not.

Views cache the supplied thumbnails. The next time a record is re-displayed, a View shows the previously generated thumbnail. You can use the View’s OptionsImageLoad.CacheThumbnails setting to disable image caching in WinExplorerView and TileView

To clear the thumbnail cache, call the View’s ResetThumbnailCache method and then the grid control’s Invalidate method.

WinExplorer View API:

Tile View API:

Grid View API:

TileView Example

This example shows how to manually generate custom tile background images (thumbnails) in Tile View and display them asynchronously. The TileView is bound to a list that contains texture names. We need to create custom background thumbnails for all tiles based on corresponding texture names, and display these images asynchronously.Thumbnails are generated using the GetThumbnailImage event. The async image load is enabled with the AsyncLoad setting.

TileView-asyncbackgroundimages.png

View Example

using DevExpress.XtraGrid.Views.Tile;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TileView_ManualThumbs {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        List<Texture> textures;

        private void Form1_Load(object sender, EventArgs e) {
            InitData();

            gridControl1.DataSource = textures;
            tileView1.OptionsTiles.ItemSize = new Size(90, 40);
            tileView1.GetThumbnailImage += TileView1_GetThumbnailImage;
            // Specify a column that provides information on images to render.
            tileView1.ColumnSet.BackgroundImageColumn = colName;
            tileView1.OptionsImageLoad.RandomShow = true;
            tileView1.OptionsImageLoad.LoadThumbnailImagesFromDataSource = false;
            // Enable async image load.
            tileView1.OptionsImageLoad.AsyncLoad = true;
        }

        private void TileView1_GetThumbnailImage(object sender, DevExpress.Utils.ThumbnailImageEventArgs e) {
            string colorName = textures[e.DataSourceIndex].Name;
            //Generate a thumbnail for the current record.
            Bitmap image = new Bitmap(e.DesiredThumbnailSize.Width, e.DesiredThumbnailSize.Height);
            Graphics graphics = Graphics.FromImage(image);
            Color tileColor = Color.FromName(colorName);
            GraphicsUnit grUnit = GraphicsUnit.Pixel;
            RectangleF imageRect = image.GetBounds(ref grUnit);
            LinearGradientBrush brush =   new LinearGradientBrush(imageRect, Color.White, Color.White, 45, false);
            ColorBlend cblend = new ColorBlend(4);
            cblend.Colors = new Color[4] { Color.White, tileColor, tileColor, Color.White};
            cblend.Positions = new float[4] { 0f, 0.5f, 0.7f, 1f };
            brush.InterpolationColors = cblend;
            graphics.FillRectangle(brush, imageRect);
            e.ThumbnailImage = image;
            brush.Dispose();
        }

        private void InitData() {
            textures = new List<Texture>();
            System.Array colorsArray = Enum.GetNames(typeof(KnownColor));
            foreach(var colorName in colorsArray ) {
                textures.Add(new Texture(colorName.ToString()));
            }
        }
    }

    public class Texture { 
        public Texture(string name) {
            this.Name = name;
        }
        public string Name { get; set; }
    }
}

Scenario 3: You need to generate thumbnails manually (a source image column is not specified)

Applicable to: WinExplorerView.

It is assumed that the View is not aware of any image column that may contain source images.

Do the following:

  • Enable async image load with the OptionsImageLoad.AsyncLoad setting.
  • Handle the GetThumbnailImage event to create thumbnails manually and supply them to the View.

    This event will fire on demand, so you can create and supply a thumbnail for each record.

The View caches the supplied thumbnails, provided that caching is enabled (the OptionsImageLoad.CacheThumbnails setting). The next time a record is re-displayed, the View shows the previously generated thumbnail.

WinExplorer View API:

Additional Settings and Events

  • AnimationType - Specifies the animation effect for displaying thumbs. By default, it equals AnimationType.None, which means thumbs will instantly appear when ready. You can select other animation types, such as segmented fade (in the animation below) or push.

    WinExplorerView - Loading Indicator

  • RandomShow - Specifies whether or not grid records load their thumbs in random order.
  • GetLoadingImage event - Allows you to set a custom loading indicator, displayed while the thumbnail image is being created. The default loading indicator depends on the currently applied application skin. The following image demonstrates a custom loading indicator.

    WinExplorerView - Custom Loading Indicator

See Also