Search code examples
delphidevexpressvcldelphi-xe4

TableView not updating while pasting a row in Delphi XE4 and Devexpress VCL 13.1.2


Following is the code snippet on which I am working:

var
myTableView: TcxGridDBBandedTableView
rowcount : integer;
.....
.....
procedure ExecutePaste;
begin
    ....
    ....
    ....
    ....
    rowcount := myTableView.DataController.RowCount; //rowcount is 3 here
    myTableView.DataController.Post; //Post the changes into database
    rowcount := myTableView.DataController.RowCount; //rowcount becomes 2 here
    ....
end;

When I right click on any row in this myTableView and select copy row option from context menu, CopyRow function is called which copies the row in the clipboard. Now when I again right click on another row and select paste option in context menu, the ExecutePaste function is called. The ExecutePaste method pushes the clipboard data to the database by using following statement:

myTableView.DataController.Post;

Data is posted well in the database but the row which I am trying to paste disappears and I have to refresh the screen to see that updated/pasted row. While debugging I noticed that myTableView.DataController.Rowcount was 3 (three rows in my tableview, that is correct), but as soon as my debugger passes the myTableView.DataController.Post; line, it remains 2. I don't know why my table view is not refreshing? My table view also has some hidden columns. Any clue, idea, suggestion on this would be very much helpful for me.


Solution

  • I'm assuming that you're using the cxGrid's built-in pasting facility and that the code you originally showed in your ExecutePaste is simply handling the event for that, and that the problem isn't being caused by code of yours that you haven't shown. There seem to be a number of possible causes of the problem you're having, which I'll discuss in decreasing order of likelihood.

    In one of your comments, you said "So when I select 2nd row and copy it, it is copied on the clipboard. Now I select 3rd row and execute paste there." mentioned that your grid section has some hidden columns.

    Devex grids usually need you to set a KeyField (or similarly named) property which the grid's code uses to uniquely identify rows in the underlying dataset, so it should be set to the dataset's PK if it has one or some other row-unique value - in some situations the grid will still behave sensibly even if you don't specify a value for this property, but in others it won't, ime.

    Now, if the grid columns which are copied in the pasting operation happen to include the dataset column which the grid is using to uniquely identify rows, then after your .Post in your ExecutePaste, the grid is likely to think that the DataController's nodes contain one fewer unique values than it did beforehand, and if that's how it calculates its RowCount, that's why its value goes down from 3 to 2, with whatever consequences for the on-screen display of the data the reduction in apparent number of unique rows that has. QED

    It should be simple to verify if this is the cause of your problem, just by observing the KeyField values for the rows before and after your .Post. If it is the cause, simply record the KeyField value of the row you're pasting into before you do the PasteExecute and restore it just before you do the .Post.

    What bothers me about that explanation is the fact that the dataset seemingly isn't complaining about a PK key violation. Possible reasons might include the dataset not having a PK/Unique constraint on the relevant column, OR, what the grid is using as the row-unique column isn't actually the dataset's PK column.

    If the above doesn't allow you to find and fix the cause then it seems to me that unless you get lucky and your q is seen by a cxGrid user who has had your problem and knows how to fix it, you're unlikely to get a full answer to it here on SO.

    What nobody can tell you from afar, unless they've encountered it themselves) is whether it's caused by a configuration problem (mainly, are all the grid's properties correctly set?) or a quirk inside the cxGrid's code. Frankly, the least likely cause is a bug in the grid's code, because Devex grids get soak-tested by dint of their large user base and Devex know what they're doing writing code.

    The cxGrid is a very complex component which IIRCC bypasses Delphi's usual mechanisms (I mean the use of TDataSources, etc) for getting data from the related dataset(s) into the grid nodes, and your problem suffers from an acute case of "we can't see your screen" syndrome. So, I think you're going to have to investigate this yourself and if you can't find the solution or a satisfactory work-around, your best bet may be to see if you can boil it down to something Devex could reproduce and help you with.

    To investigate, I'd start from the configuration end. Check that all the cxGrid's properties are appropriately set. Apart from the KeyField property(ies) Devex grids also tend to have properties which enable you to specify how the grid synchronizes with the dataset's data (e.g. using the dataset's .Locate() method). Look those up in the grid's OLH and try experimenting with them.

    Your problem may be being caused by a "state error" that your cxGrid is getting into in the course of the pasting operation. That's why, in one of my comments earlier, I suggested moving the dataset's cursor - the grid's code should notice this change and force the grid to refresh itself by re-synching with the dataset in a way which will hopefully correct the RowCount and what the grid displays. The ways I suggested of doing it (Next + Prior) or two MoveBy()s don't have the overhead of closing and re-opening the dataset. Actually, depending on how the cxGrid is coded, just doing a DisableControls immediately followed by an EnableControls might be sufficient to force a refresh. However, if my suggested explanation that the problem is caused by pasting the KeyField value from one row to another is correct, I wouldn't expect any of these ways of forcing the grid to update to work, only closing and re-opening the dataset.

    If none of the above found the cause, next I'd start investigating the problem from the other end, so to speak. Find the implementation of .DataController.RowCount in the Devex source, put a breakpoint inside it and a watch on its return value, then keep a very close eye on it while performing your paste operation. When you get to it changing value to 2, you should be able look upwards up the stack from there (using View | Debug Windows | Call stack) and find out why it's changing to that value, which will I imagine get you 90% of the way to a solution or work-around.

    Good luck!