*!* Hi Spyros, *!* "Therefore as stated by various articles of the forum the way to eliminate *!* the problem is to create a class grid for every grid and remove it,refresh *!* data,add it to the form again" *!* I think I either never had a chance to see these articles or you are *!* misinterpreting them. This is not a good idea IMHO. I use grids a lot too *!* and total of my grid classes are almost under 10. Classes differ in their *!* behaviour, properties and methods and not built specific to a dataset. *!* To change the data of a grid anytime is staright forward : *!* -Want to keep grid formatting (existing columncount, controls etc) but *!* change data *!* .RecordSource = '' *!* * cursor/table specific operations *!* .Recordsource = 'recordsource' *!* -Completely rebuild (besides formatting reset to default controls) *!* .Recordsource = '' *!* .ColumnCount = -1 *!* * cursor/table specific operations *!* .Recordsource = 'recordsource' *!* To have custom code for header click/dblclick I think best is to use your *!* own header classes in place of default header. Roughly : *!* with this.Columns(x) *!* If type(".Header1") = "O" *!* .removeobject("Header1") *!* .newobject("MyHeader","myHeaderClass","myHeaders.prg") *!* endif *!* endwith *!* If you coded it like this it'd work : *!* *gridfromcode.prg *!* *... *!* Procedure Init *!* Local oCol *!* For Each oCol In This.Columns *!* If Type('oCol.Header1')='O' *!* oCol.RemoveObject('Header1') *!* oCol.Newobject('Header1','myHeader','gridfromcode.prg') *!* Endif *!* oCol = .Null. *!* Endfor *!* This.Column1.Header1.Caption = 'Item ID' *!* This.Column2.Header1.Caption = 'Category ID' *!* Endproc *!* Enddefine *!* Define Class myHeader As Header *!* Procedure Click *!* Wait Window This.Parent.ControlSource *!* Endproc *!* Enddefine *!* If you want a dynamic grid subclass all controls (header, column, textbox *!* etc). Below is such a sample (what it does is not important - just to show *!* totally code driven grid) : oForm = CREATEOBJECT('myForm') WITH oForm .ADDOBJECT('myGrid' , 'myGrid') .ADDOBJECT('myButton', 'myButton') .MyButton.VISIBLE = .T. WITH .myGrid .TOP = oForm.MyButton.HEIGHT + 10 .LEFT = 10 .HEIGHT = oForm.HEIGHT - (.TOP + 20) .WIDTH = oForm.WIDTH - 20 .SetSource('products') .VISIBLE = .T. ENDWITH .SHOW ENDWITH READ EVENTS DEFINE CLASS myForm AS FORM HEIGHT = 400 WIDTH = 600 SHOWTIPS = .T. DATASESSION = 2 PROCEDURE LOAD USE products IN 0 USE employee IN 0 ENDPROC PROCEDURE QUERYUNLOAD CLEAR EVENTS ENDPROC ENDDEFINE DEFINE CLASS MyButton AS COMMANDBUTTON CAPTION = 'Switch source' PROCEDURE CLICK WITH THISFORM.myGrid .SetSource(IIF(UPPER(.RECORDSOURCE) = 'EMPLOYEE', 'products', 'employee')) ENDWITH ENDPROC ENDDEFINE DEFINE CLASS myGrid AS GRID DELETEMARK = .F. READONLY = .T. RECORDMARK = .F. SCROLLBARS = 3 SPLITBAR = .F. HIGHLIGHT = .F. HighlightRow = .F. NAME = "grdMyGrid" PROCEDURE ADDCOLUMN LPARAMETERS nIndex, cAlias, cField, cCaption NODEFAULT THIS.ADDOBJECT("clm" + cField, "myColumn", cAlias + "." + cField, nIndex) ENDPROC PROCEDURE SetSource LPARAMETERS tcRecordsource WITH THIS .RECORDSOURCE = '' .RECORDSOURCE = tcRecordsource .COLUMNCOUNT = -1 FOR ix = 1 TO FCOUNT(tcRecordsource) .ADDCOLUMN(ix, tcRecordsource, FIELD(ix, tcRecordsource)) ENDFOR .SETALL('Visible',.T.) .SETFOCUS() ENDWITH ENDPROC ENDDEFINE DEFINE CLASS myColumn AS COLUMN RESIZABLE = .F. MOVABLE = .F. PROCEDURE INIT LPARAMETERS cControlSource, nIndex WITH THIS .CONTROLSOURCE = cControlSource .COLUMNORDER = nIndex .REMOVEOBJECT('Header1') .ADDOBJECT('myHeader', 'myHeader', JUSTEXT(cControlSource)) IF TYPE(cControlSource) = 'L' .ADDOBJECT("myControl", "myGridChkBox") ELSE .ADDOBJECT("myControl", "myGridTxtBox") ENDIF .CURRENTCONTROL = "myControl" .SPARSE = .F. ENDWITH ENDPROC PROCEDURE RESIZE THIS.myControl.RESIZE ENDPROC PROCEDURE MOUSEMOVE LPARAMETERS nButton, nShift, nXCoord, nYCoord WITH THIS.PARENT lnActiveRow = CEILING((nYCoord - (.TOP + .HEADERHEIGHT)) / .ROWHEIGHT) lnActivecol = THIS.COLUMNORDER - THIS.PARENT.LEFTCOLUMN + 1 .ACTIVATECELL(lnActiveRow, lnActivecol) ENDWITH WITH THIS IF TYPE(.CONTROLSOURCE) $ 'CM' .myControl.TOOLTIPTEXT = IIF(TYPE(.CONTROLSOURCE) = 'C', ; EVAL(.CONTROLSOURCE), ; IIF(TYPE(.CONTROLSOURCE) = 'M', ; MLINE(EVAL(.CONTROLSOURCE), 1), '')) ENDIF ENDWITH ENDPROC ENDDEFINE DEFINE CLASS myGridChkBox AS CONTAINER WIDTH = 14 HEIGHT = 17 BACKSTYLE = 0 BORDERWIDTH = 0 NAME = "grdcheckbox" ADD OBJECT check1 AS CHECKBOX WITH ; TOP = 0, ; LEFT = 0, ; HEIGHT = 17, ; WIDTH = 13, ; BACKSTYLE = 0, ; CAPTION = "", ; NAME = "Check1" PROCEDURE INIT WITH THIS .check1.CONTROLSOURCE = .PARENT.CONTROLSOURCE .RESIZE() ENDWITH ENDPROC PROCEDURE RESIZE WITH THIS.check1 .LEFT = (THIS.PARENT.WIDTH - .WIDTH) / 2 ENDWITH ENDPROC ENDDEFINE DEFINE CLASS myGridTxtBox AS TEXTBOX NAME = "Text1" BORDERSTYLE = 0 MOUSEPOINTER = 1 ENDDEFINE DEFINE CLASS myHeader AS HEADER BACKCOLOR = 0 FORECOLOR = RGB(255,255,0) PROCEDURE INIT LPARAMETERS tcCaption THIS.CAPTION = tcCaption ENDPROC PROCEDURE CLICK * Go top WITH THIS.PARENT.PARENT GO TOP IN (.RECORDSOURCE) .REFRESH ENDWITH ENDPROC PROCEDURE DBLCLICK * Go bottom WITH THIS.PARENT.PARENT GO BOTTOM IN (.RECORDSOURCE) .REFRESH ENDWITH ENDPROC PROCEDURE RIGHTCLICK * Scroll pagedown WITH THIS.PARENT.PARENT .DOSCROLL(3) .REFRESH ENDWITH ENDPROC ENDDEFINE *!* You can also check samples from FoxyClasses how a single grid class could *!* serve to different datasets and formatting. *!* Cetin