Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations dencom on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Grid - control source being ignored.

bs6600

Programmer
Sep 23, 2005
59
GB
I have a table with 4 columns and a grid showing the first 3 columns. I specified the control source in columns 1,2, and 3. this has been in use for years.

I've added a fifth field to the table and a fourth column in the grid with the control source defined for the new field 5

It now shows 4 columns with the correct headings but column4 contains the data from field 4 instead of field 5.

VFP Help suggests if the control source is not present the next unused field will be shown

Please advise me
 
At designtime, set the grid recordsource to the table all the columns controlsources to the fields to display. I guess you already have that.

At runtime ensure the table to display is open before the grid displays, i.e. open the table in the forms data environment or the Load event of the form. Form init already runs after all control inits - reason is you can access all form controls in init, that would not be available if form init was first.

Form init is the very last moment to have the table available for the grid. Otherwise it goes blank and when you then set the recordsource you recreate new grid columns that don't know anything about what you set at designtime in the form designer.

Respect that, and you won't have problems. Also later at runtime of the form, don't touch the recordsource.
 
Just check every single grid control for Control Source. Finally, you can set all this up programmatically on the Form.INIT() before DEFAULT()
 
One possible cause is that you may not be using the textbox within the column.

To confirm this, drill down from the column to get to the underlying textbox and check the control source for that specific box.
 
You better set the column controlsource property, the text1.conrtrolsource within the column (and any other alternative control you may switch to with dynamiccurrentcontrol) will take the controlsource of the column automatically.

The problem still is grid reconstruction, if the grid doesn't get at the table and fields its columns/controls and its recordsource is configured for. If you want to bind the grid later, while the form already runs, you can't design this pre running the form. You can't start with an empty grid and query into an alias after the form already has started, when the grid is configured for that alias at designtime. If the alias doesn't exist at grid.init, you may get away, but when the form gets displayed and the grid is drawn, that has to be available. Because when the grid doesn't find the alias at first, it'll just detroy it's columns objects and go blank. Ideally, the alias is made available at Load already, latest, or within the DE. All that is before Form init.

What you can do to start with an empty grid is have a grid cursor or table empty to which you then append at form runtime and ZAP it to empty it again and then APPEND to show other data. And the best alternative is to feed a grid with a view, then requery() of the view will not destruct the grids columns. But, again, the view alias has to exist prior to the grid being displayed first, already. If you set the recordsource to a DBF of the database, you obviously display all data and filter it with SET FILTER and change the filter to display other records, and obviously then do not ZAP and APPEND.

There's one way of late binding, but you can only do that once in the form life: You can set Form.BindControls property to .F. in design and then switch that to .T. once you're ready to let controls actually bind to their controlsources, recordsources, and rowsources. That's not only delaying the data binding for the grid, but for all controls. Then you still won't do this as late as after a user interaction of choosing a filter for data, for example, but you'd switch the BindControls in form. init, perhaps in activate, but not much later or within a button.click, that would leave everything blank until that click happens. So it's not all that useful, but can help in some cases where the grid even misbehaves tough you do have the alias for it available in form init, I think everyone struggled with that, at some point when first using the grid.

Other controls, by the way, are not that sensitive, you can also easily switch their controlsources at runtime without breaking them. The grid is very brittle about this. But once you have the alias available and don't touch that and the grid.recordsource, everything is stable.
 
Last edited:
... or simply hide the column(s) you don't want to be displayed (demo code below)

Code:
**************************************************
PUBLIC oForm

oForm = NEWOBJECT("form1")
oForm.Show

Read Events
Close all
Clear All
RETURN

**************************************************

DEFINE CLASS form1 AS Form
    DIMENSION laValues[1]
    
    AutoCenter = .T.
    Caption = "Sales"
    ShowTips = .T.
    Height = 480
    Width = 648
    MinHeight = This.Height
    MinWidth = This.Width
    MaxWidth = This.Width
    
    ADD OBJECT lblSpinner as Label WITH ;
        Left = 12, Top = 12, Autosize = .T., Caption = "Column to hide :"

    ADD OBJECT spnColumns as Spinner WITH ;
        Left = 12 + 120, ;
        Top = 12, ;
        SpinnerLowValue = 1
        
        PROCEDURE spnColumns.LostFocus()
            LOCAL li_Columns, li_ColNumber
            
            li_ColNumber = This.Value
            
            ThisForm.grdSales.DeleteColumn(li_ColNumber)

            li_Columns = ThisForm.grdSales.ColumnCount
            
            This.SpinnerHighValue = li_Columns
            
            ThisForm.Refresh()
        ENDPROC

    ADD OBJECT cmdShowAll as CommandButton WITH ;
        Left = 12 + 240, ;
        Top = 12, ;
        Height = 24, ;
        Width  = 120, ;
        Caption = "Show all columns"
        
        PROCEDURE cmdShowAll.Click()
            WITH ThisForm.grdSales
                .ColumnCount = -1
                .RecordSource = "curSales"
                .Refresh()
            ENDWITH 

            ThisForm.spnColumns.SpinnerHighValue = ThisForm.grdSales.ColumnCount
            
        ENDPROC 

    ADD OBJECT grdSales AS Grid WITH ;
        Left = 12, ;
        Top = 48, ;
        Width = 624, ;
        Height = 420, ;
        Anchor = 1 + 2 + 4 + 8, ;
        Visible = .T., ;
        ReadOnly = .T., ;
        ColumnCount = -1, ;
        RecordSource = "curSales"
        
    PROCEDURE Destroy
        CLOSE ALL
        Clear Events

    ENDPROC

    PROCEDURE Load

        CREATE CURSOR curSales (C_CID C(4), C_Descri C(20), N_Price N(10,2), L_Paid L)
        
        INSERT INTO curSales (C_CID, C_Descri, N_Price, L_Paid) VALUES ("CI01", "A" + SYS(2015), 41.25, .F.)
        INSERT INTO curSales (C_CID, C_Descri, N_Price, L_Paid) VALUES ("CI02", "A" + SYS(2015), 468.26, .T.)
        INSERT INTO curSales (C_CID, C_Descri, N_Price, L_Paid) VALUES ("CI03", "A" + SYS(2015), 44.24, .F.)
        INSERT INTO curSales (C_CID, C_Descri, N_Price, L_Paid) VALUES ("CI04", "A" + SYS(2015), 3.27, .T.)
        INSERT INTO curSales (C_CID, C_Descri, N_Price, L_Paid) VALUES ("CI08", "A" + SYS(2015), 14.25, .F.)
        INSERT INTO curSales (C_CID, C_Descri, N_Price, L_Paid) VALUES ("CI09", "A" + SYS(2015), 1054.25, .T.)
        INSERT INTO curSales (C_CID, C_Descri, N_Price, L_Paid) VALUES ("CI10", "A" + SYS(2015), 384.27, .F.)
        INSERT INTO curSales (C_CID, C_Descri, N_Price, L_Paid) VALUES ("CI07", "A" + SYS(2015), 164.25, .T.)
        INSERT INTO curSales (C_CID, C_Descri, N_Price, L_Paid) VALUES ("CI06", "A" + SYS(2015), 10884.25, .F.)
        INSERT INTO curSales (C_CID, C_Descri, N_Price, L_Paid) VALUES ("CI05", "A" + SYS(2015), 384.27, .T.)

        LOCATE 
        
    ENDPROC

ENDDEFINE
*********************************************

hth

MarK
 
Last edited:
Thank you all for your suggestions.

I have checked and found there was nothing in the grid.recordsource.

Filled that in (i just put the alias?) and it blanked all the column.controlsources. Put them back - didn't fix the problem.

All columns show identical non default properties apart from contolsource.

I'm working at design time with no runtime operations

To recap and clarify

I have fields A,B,C,D,E. Grid has columns 1,2,3,4 with control source A,B.C.E respectively

Grid shows correct headings but data from A,B,C,D

It seems to be ignoring the controlsources and taking the fields in natural order.

I have found that by modifying the table structure to make the unwanted field last I get the correct results so I've got a working version but it would be nice to know why.
 
A grid with your design will show field E in column 4.

What are you doing in code? If you set the recordsource at runtime, you are resetting the grid columns, overriding your design. That's what you have to avoid. If you design a grid in the form designer, all you need to make sure at runtime is to open the table before the grid displays. The recordsource already knows what alias to use, the columns know their controlsource and display that way. If you don't make the alias available for the grid, before it displays, it will go blank, have no columns, the column objects don't just remain empty, get unbound, they are removed. And if you then set recordsource you get as many columns as fields and display a table 1:1 as is.

I don't know what's going on with your form without hands on it, for sake of making sure you have no side effects from anything else, just create a new test form, put the table in the data environment, put a grid on it, set its recordsource first, then the 4 column controlsources, and start the form. What happens?
 
Last edited:

Part and Inventory Search

Sponsor

Back
Top