Question .NET DataGridView Custom Column

David Williams

New Member
Hi

I'm trying to create a custom column in a DataGridView by sub-classing the DataGridViewColumn and DataGridViewTextBoxCell classes. Can anyone please help me with a few issues that I've encountered?

I'm relatively new to this so started by replicating a VB/C# example I found online. But even when I reduce this to it's most basic - a column and cell which just replicates the standard behaviour - I still hit issues.

My code looks like this (OE11.3). The new cell:

Code:
CLASS DataGridViewBarGraphCell INHERITS System.Windows.Forms.DataGridViewCell :
    METHOD OVERRIDE PROTECTED VOID Paint( INPUT graphics AS System.Drawing.Graphics,
                                          INPUT clipBounds AS System.Drawing.Rectangle,
                                          INPUT cellBounds AS System.Drawing.Rectangle,
                                          INPUT rowIndex AS INTEGER,
                                          INPUT cellState AS System.Windows.Forms.DataGridViewElementStates,
                                          INPUT value0 AS System.Object,
                                          INPUT formattedValue AS System.Object,
                                          INPUT errorText AS CHARACTER,
                                          INPUT cellStyle AS System.Windows.Forms.DataGridViewCellStyle,
                                          INPUT advancedBorderStyle AS System.Windows.Forms.DataGridViewAdvancedBorderStyle,
                                          INPUT paintParts AS System.Windows.Forms.DataGridViewPaintParts ):

        MESSAGE "In Paint" VIEW-AS ALERT-BOX.
       
        SUPER:Paint(INPUT graphics,
                    INPUT clipBounds,
                    INPUT cellBounds,
                    INPUT rowIndex,
                    INPUT cellState,
                    INPUT value0,
                    INPUT formattedValue,
                    INPUT errorText,
                    INPUT cellStyle,
                    INPUT advancedBorderStyle,
                    INPUT paintParts).
                   
        RETURN.
   
    END METHOD.

END CLASS.

The new column:

Code:
CLASS DataGridViewBarGraphColumn INHERITS DataGridViewColumn:

    CONSTRUCTOR PUBLIC DataGridViewBarGraphColumn (  ):
        SUPER ().
        THIS-OBJECT:CellTemplate = NEW DataGridViewBarGraphCell().
        THIS-OBJECT:ReadOnly = TRUE.
    END CONSTRUCTOR.

END CLASS.

I then have a simple form with a DataGridView connected to a datasource.

My issues are:

1) I can't consistently see the new column type in the DataGridView designer. It did appear on one occasion but I can't get it back.

2) If I manually change the column type (not ideal), adding one to the grid fails in InitializeComponent() at:

THIS-OBJECT:dataGridView1:Columns:AddRange(arrayvar0).

with error - System.InvalidOperationException: Column cannot be added because its CellType property is null.

This doesn't seem to be the case. If I add each column individually using DataGridView:Add it doesn't complain.

3) When I run it up now, all the standard columns display correctly. But for my custom column I get this error:

A .NET object is attempting to access a method or property of an ABL/.NET hybrid class that has already been DELETED (14791)

It never gets as far as the message in the Paint method. If I remove the Paint override method it all works as expected (standard text cell behaviour).



Any help with these problem would be greatly appreciated.



Thanks

Dave
 

oli

Member
Hi Dave,

I'm not sure you really have to subclass.

For instance, we've made this for pictures (in an Infragistics' UltraGrid control).
The temp-table has a field that contains the picture's file-name (<img src="path&filename" />).
In the "InitializeLayout" method, we create an unbound column with a "System.Drawing.Bitmap" DataType:
Code:
ASSIGN min_band = mcl_column:Band:Index
       mch_key = mcl_column:Key + "_IMG":U
       mcl_imageColumn = ccl_DisplayLayout:Bands[min_band]:Columns:Add(mch_key)
       mcl_imageColumn:DataType = TypeHelper:GetType("System.Drawing.Bitmap":U)
       mcl_imageColumn:Header:VisiblePosition = mcl_column:Header:VisiblePosition

In the "InitalizeRow" method, we load the image into the unbound column:
Code:
mcl_image = NEW System.Drawing.Bitmap(mch_fileName).
IF VALID-OBJECT(mcl_image)
THEN DO:
  ASSIGN mch_key = ipcl_args:Row:Band:Columns[min_column]:Key + "_IMG":U.

  IF ipcl_args:Row:Cells:Exists(mch_key)
  THEN ASSIGN ipcl_args:Row:Cells[mch_key]:Value = mcl_image.
 

David Williams

New Member
Thanks for that, Oli.

I haven't looked at the UltraGrid yet, but I'll give it a try.

I tried the subclassing method as this is what I'm used to in other languages and it seemed the best approach to what I was trying to do as the painting could be quite complex.

Regardless of whether or not this is the best approach, shouldn't the subclassing work?


Dave
 

oli

Member
It should, indeed.
But subclassing is touchy and has many implications, so I would consider this in last instance.
 
Top