Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display user control in DatagridViewCell

Tags:

c#

winforms

Winforms .NET 3.5 (C#)

I have a DataGridView (DGView) and I created CustomColumn and CustomCell to be displayed in the DGView. I created a CustomUserControl which I want to display in the CustomCell.

Problem: I don't see the user control in the column. I think I need to override Paint() method in CustomCell - Any points how can I do that ?

Note - MSDN example of hosting user control is for editing the cell value - where you make your user control visible right where you are editing your cell. I want my user control to render as a normal winform control. This user control shows notifications for the row .. and each row can have different notifications. I want users to be able to click on notification and get more details about it. .. but for now I am stuck at "how do I display this user control"

Any pointers will be highly appreciated.

 public class CustomColumn : DataGridViewColumn {
    public CustomColumn() : base(new CustomeCell()) { }
    public override DataGridViewCell CellTemplate
    {
        get
        {
            return base.CellTemplate;
        }
        set
        {
            // Ensure that the cell used for the template is a CalendarCell.
            if (value != null &&
                !value.GetType().IsAssignableFrom(typeof(CustomeCell)))
            {
                throw new InvalidCastException("It should be a custom Cell");
            }
            base.CellTemplate = value;
        }
    }
}
public class CustomeCell : DataGridViewTextBoxCell
{
    public CustomeCell() : base() { }
    public override Type ValueType
    {
        get
        {
            return typeof(CustomUserControl);
        }
    }
    public override Type FormattedValueType
    {
        get
        {
            return typeof(CustomUserControl);
        }
    }
}
like image 460
karephul Avatar asked Jun 06 '12 19:06

karephul


2 Answers

First Try: I tried to place a user control on the grid where I needed. Problem: Scrolling the data grid view requires re arranging all those user controls. Result - Rejected.

Second Try: I constructed a user control and painted it in the appropriate cell. Result - works so far.

I just overrode Paint and OnClick methods of DataGridViewCell in the CustomCell class.

public class CustomeCell : DataGridViewCell
{
    public override Type ValueType
    {
        get { return typeof(CustomUserControl); } 
    }

    protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
    {
        var ctrl = (CustomUserControl) value;
        var img = new Bitmap(cellBounds.Width, cellBounds.Height);
        ctrl.DrawToBitmap(img, new Rectangle(0, 0, ctrl.Width, ctrl.Height));
        graphics.DrawImage(img, cellBounds.Location);
    }

    protected override void OnClick(DataGridViewCellEventArgs e)
    {
        List<InfoObject> objs = DataGridView.DataSource as List<InfoObject>;
        if (objs == null)
            return;
        if (e.RowIndex < 0 || e.RowIndex >= objs.Count)
            return;

        CustomUserControl ctrl = objs[e.RowIndex].Ctrl;
        // Take any action - I will just change the color for now.
        ctrl.BackColor = Color.Red;
        ctrl.Refresh();
        DataGridView.InvalidateCell(e.ColumnIndex, e.RowIndex);
    }
}

The example renders the CustomControl in the CustomCell of CustomColumn ;). When user clicks on the cell, CustomCell's OnClick handles the click. Ideally, I would like to delegate that click to the custom user control CustomControl - which should handle the event as if it was a click on itself (custom user control can internally host multiple controls) - so its little complex there.

public class CustomColumn : DataGridViewColumn
{
    public CustomColumn() : base(new CustomeCell()) { }

    public override DataGridViewCell CellTemplate
    {
        get { return base.CellTemplate; }
        set
        {
            if (value != null && !value.GetType()
                .IsAssignableFrom(typeof (CustomeCell)))
                throw new InvalidCastException("It should be a custom Cell");
            base.CellTemplate = value;
        }
    }
}
like image 77
karephul Avatar answered Sep 19 '22 22:09

karephul


The DataGridView control only supports displaying an actual control when a cell is in edit mode. The DataGridView control is not designed to display multiple controls or repeat a set of controls per row. The DataGridView control draws a representation of the control when the cell is not being edited. This representation can be a detailed as you want. For example, the DataGridViewButtonCell draws a button regardless of the cell being in edit or not.

However, you can add controls through DataGridView.Controls.Add() method, and set their location and size to make them hosted in the cells, but showing controls in all cells regardless of editing make no sense.

Read here

[Update - From MS DataGridView Team's Prog Mgr]

http://social.msdn.microsoft.com/Forums/en-US/winformsdatacontrols/thread/394e04a8-d918-4fdd-be03-dfa13f6a1e66?persist=True

like image 42
Angshuman Agarwal Avatar answered Sep 19 '22 22:09

Angshuman Agarwal