Search code examples
gridviewdelete-rowfoxpro

Visual FoxPro: Delete row in grid


I have a grid that have 3 columns, column 1 and 2 are textbox, button in the 3rd (for delete).

What I wanted to achieve is when the grid have records, and I click the button in the 3rd column, the row will marked as deleted. Unfortunately it's not working for me and it deletes the last row only.

This is my code for table updating:

SELE descCur2
thisform.item_grid.RecordSourceType = 4
thisform.item_grid.RecordSource = "select * from descCur2 into table descCur2a"
GO top
thisform.item_grid.Refresh

Some codes inside delete button:

this.setfocus
*thisform.item_grid.DeleteMark = .T.
Delete
thisform.item_grid.Refresh()
thisform.item_grid.SetFocus

Solution

  • You are saying you have been searching this for hours including popular sites and cannot find the answer. FWIW, most popular sites for VFP are foxite.com and levelextreme.com. Levelextreme.com doesn't support internet searches AFAIK and have a paid subscription option, besides free subscription. Both sites have the answer to this problem many times as I was one of those who posted sample code for this many times on both of those sites.

    What you need is a "DELETE" command, either xBase DELETE or SQL-delete. ie: Assuming grid's record source is 'myCursor':

    select myCursor
    * locate the row to delete - by default it is current row in grid
    delete
    

    Or SQL-Delete:

    *Get the ID of current row - assuming ID is the primary key field name
    local id
    id = myCursor.Id
    Delete from myCursor where Id = m.Id
    

    In both cases, the record would be marked for deletion. If:

    Set deleted OFF
    

    is the current setting (default), then the deleted record would continue to show in the grid, with a black mark on "DeletedMark".

    For it to go away you need 2 things: 1) Set deleted setting should be set. It is scoped to current data session. So it is better to set it in dataenvironemt.BeforeOpenTables or Form.Load.

    Set deleted ON
    

    2) You should select grid's record source and then refresh.

    Here is a working, tested code that shows how to do that:

    Public oForm
    oForm = Createobject('SampleForm')
    oForm.Show()
    
    Define Class sampleForm As Form
        Height=600
        Width=800
        Add Object myGrid As Grid With Height=600,Width=800, Anchor=15, RecordSource='myCursor'
    
        Procedure Init
            With This.myGrid
                .ColumnCount=3
                With .Columns(.ColumnCount)
                    .Newobject('myButton','myButton')
                    .CurrentControl = 'myButton'
                    .MyButton.Visible = .T.
                    .Sparse = .F.
                Endwith
            Endwith
        Endproc
    
        Procedure Load
            Local ix
            Create Cursor myCursor (Id Int, dummy c(10))
            For ix=1 To 100
                Insert Into myCursor (Id, dummy) Values (m.ix, Sys(2015))
            Endfor
            Locate
            Set Deleted On
        Endproc
    Enddefine
    
    
    Define Class MyButton As CommandButton
        Caption = "Delete Me"
        Procedure Click
            Select myCursor
            Delete
            With this.Parent.Parent
                .Refresh
            endwith
        Endproc
    Enddefine
    

    Some notes: Do not use grid properties and methods, like RemoveObject for cases like these. Remember, in most cases, you do the operation on grid's record source cursor itself, not the grid object. DeleteMark though useful sometimes (just to delete a row by clicking it), doesn't have an importance IMHO. Personally, I remove it in my grids. DeleteMark = .f..T. just sets that special column's visibility.

    Again, do not use RemoveObject on operations like this. Thisform.Grid.RemoveObject(thisform.Grid.ActiveRow) is a meaningless command in fact. .ActiveRow would return an integer (in case there is an ActiveRow), and removeObject expects an object 'name' as string. Suppose you had it, what would it really remove? A grid is just a visual layout on top of a record source, you would be removing something from the visual layout (like a view window to underlying data).

    Append blank, replace is totally obscure to me in this case. Actually, in real life, I would list that 'Append blank\Replace' in 'never to use commands'. That is something buried in ancient Foxpro 2.x days (over 20+ years have passed). It is prone to errors in multiuser scenarios, hard to showcase, but you may end up doing a replace on a different row than you think. As simple and safe alternative is doing an SQL-Insert. ie:

    Instead of doing this: (assuming current alias is myCursor)

    Append blank
    replace name with 'Cetin', Surname with 'Basoz'
    

    Do this:

    insert into myCursor (name, surname) values ('Cetin', 'Basoz')
    

    Despite xBase version (append\replace), this SQL version is a single command and atomic (and much more readable IMHO).

    HTH