C1FlexGrid control is a powerful, full-featured grid and provides all the basic and advanced features. It also exposes a certain method SetCellImage(), that gives users the ability to display an image in a grid cell. SetCellImage() method however, lets the user display only one image in a cell. There are occasions though, when one might need to display more than a single image in a particular cell/column. This article provides us with a way to implement this. Also, should the user somehow, become successful in displaying multiple images in a single cell, what if he needs to implement some logic in the event of a particular image being clicked? Say, there are three images A, B and C; and user needs a notification when any of those images is clicked. Here, we'll talk about this as well. Considering there's no other property/method to display multiple images in a cell, the only alternative is to draw them manually. And, there's no other event than 'OwnerDrawCell' that we may employ for this purpose. Take a look at the code given below :
c1FlexGrid1.DrawMode = C1.Win.C1FlexGrid.DrawModeEnum.OwnerDraw;
c1FlexGrid1.OwnerDrawCell += (s1, e1) =>
{
if (e1.Col == 1 && e1.Row == 1)
{
//let the grid paint the background and border for the cell
e1.DrawCell(C1.Win.C1FlexGrid.DrawCellFlags.Background | C1.Win.C1FlexGrid.DrawCellFlags.Border);
//find text width
var width = (int)e1.Graphics.MeasureString(e1.Text, e1.Style.Font).Width;
//x-coordinate for each image
var img1_x = e1.Bounds.X + width - 10;
var img2\_x = img1\_x + img1.Width + 5;
var img3\_x = img2\_x + img2.Width + 5;
//location for each image
var img1\_loc = new Point(img1\_x, e1.Bounds.Y + img1.Height - 18);
var img2\_loc = new Point(img2\_x, e1.Bounds.Y + img1.Height - 18);
var img3\_loc = new Point(img3\_x, e1.Bounds.Y + img1.Height - 18);
//draw images at aforementioned points
e1.Graphics.DrawImage(img1, img1_loc);
e1.Graphics.DrawImage(img2, img2_loc);
e1.Graphics.DrawImage(img3, img3_loc);
//draw text
e1.Graphics.DrawString(e1.Text, e1.Style.Font, Brushes.Black, e1.Bounds.Location);
e1.Handled = true;
}
};
Here, I should point out that the user needs to set the column's width manually as per the total space occupied by the cell text and the images. AutoSizeRow()/AutoSizeColumn() methods won't help here because they'd simply set the column/row width as per cell text, ignoring the space needed by images. Now that we have the images displayed in a cell, how does the user get to know if any of those images is clicked ? Moreover, how does he know specifically which image was clicked? Simple - we handle the BeforeMouseDown event of the grid, find the image rectangles and see if the mouse pointer is in any of those rectangles. Here's the code:
c1FlexGrid1.BeforeMouseDown += (s1, e1) =>
{
var hti = this.c1FlexGrid1.HitTest(new Point(e1.X, e1.Y));
if (hti.Row == 1 && hti.Column == 1)
{
var _row = hti.Row;
var _col = hti.Column;
if (this.c1FlexGrid1.GetDataDisplay(\_row, \_col).ToString() != null)
{
//cell rectangle
var \_cellRect = c1FlexGrid1.GetCellRect(\_row, _col);
//graphics object
var graphics = c1FlexGrid1.CreateGraphics();
//cell text
var \_text = c1FlexGrid1.GetDataDisplay(\_row, _col).ToString();
//text Font
var \_font = c1FlexGrid1.GetCellStyleDisplay(\_row, _col).Font;
//Text width
var text\_width = (int)graphics.MeasureString(\_text, _font).Width;
//Cursor location
var cursor_loc = new Point(e1.X, e1.Y);
//find x-coordinate for each image
var img1\_X = \_cellRect.Location.X + text_width - 10;
var img2\_X = img1\_X + img1.Width + 5;
var img3\_X = img2\_X + img2.Width + 5;
//find rectangle for each image
var img1\_Rect = new Rectangle(new Point(img1\_X, e1.Y), img1.Size);
var img2\_Rect = new Rectangle(new Point(img2\_X, e1.Y), img2.Size);
var img3\_Rect = new Rectangle(new Point(img3\_X, e1.Y), img3.Size);
//find which image-rectangle contains mouse-pointer
if (img1\_Rect.Contains(cursor\_loc))
c1FlexGrid1[\_row, \_col + 1] = "Left Image";
else if (img2\_Rect.Contains(cursor\_loc))
c1FlexGrid1[\_row, \_col + 1] = "Middle Image";
else if (img3\_Rect.Contains(cursor\_loc))
c1FlexGrid1[\_row, \_col + 1] = "Right Image";
}
}
};
Since it's a demo, I've displayed the name of the image being clicked, in the adjacent cell of C1Flexgrid. Certainly, you may implement your own logic depending on the image. Here's a GIF that shows all three images being clicked and their positions getting updated in the adjacent cell. Download C# Sample Download VB.Net Sample