Current filter:
                                You should refresh the page.
                                Support Center
                                0
                                  • Hi All,

                                    I have just been informed today of some required functionality that must remain, that if I cannot replicate using the Quantum Grid means I will have to revert all of the grids back to the woll2woll wwDBGrid that I was currently upgrading from and dislike (part of the complete system refactoring and look and feel update I am doing, which is why I ordered your excellent grid in the first place).

                                    I need to have the ability to select multiple rows and then edit one of the fields in the last selected record, either by editing data directly in a cell or selecting a value from a drop down list - and then when posting the changes made, to have the grid ask me is I would like to:
                                    "Apply column changes to all selected records?" Clicking yes then updates the value in the field of all the selected rows.

                                    I can currently do this with the code I inherited with a woll2woll wwDBGrid - please see images wwDBGrid1.jpg, wwDBGrid2.jpg & wwDBGrid3.jpg in the attached zip.

                                    I cannot however do this with the cxGrid it seems, as when I select one of the drop down lists after multi-selecting some records/rows it unselects them all and only edits the one record/row left highlighted. Please see images cxGrid1.jpg & cxGrid2.jpg in the attached zip.

                                    Is there any way I can get this important functionality to work with your grid please?

                                    I have fingers crossed that there is a way I can get this to work.

                                    Many thanks and kind regards as always,

                                    Giles.

                                0

                                Hi Giles,

                                By design, the selection is cleared, once the end user clicks a record without holding the Ctrl or Shift key.

                                As a workaround, there are two different ways to keep the GridView's selection.

                                1) So, you can deactivate the OptionsSelection.MultiSelect option. Set the unbound CheckBox column in your GridView (please refer to the Knowledge Base article "How to set up an unbound item in a data-aware View" A1095 (http://www.devexpress.com/kb=A1095). Handle the OnGetContentStyle event, and select records according to the value of this column in the currently processed record. You can access it via the ARecord parameter. Use the AStyle parameter to draw your selection.
                                 
                                2) You can handle the OnCanSelectRecord event and save your selection somewhere (for example in the TList storage). Then, edit the cell's contents and restore your selection in the OnMouseUp event handler. You also need to programmatically track the selection changes. This method requires much more code and we can't guarantee that it will work properly in all cases.

                                To change the field values of the focused column in the selected records, handle the OnDataChanged event and send "Apply column changes to all selected records?" message to the end user. If he clicks yes, update the field's value in the cell's column for all selected records using the DataController.ForEachRow method.

                                Let me know if my suggestion helps.

                                Thanks,
                                Eugene

                                0

                                Hi Eugene :)

                                Thanks for your help so far with this.

                                Have been attempting to tackle the second option rather than adding in a new field and changing the way the application currently works for the end user.

                                Having searched around and looking at the help you provided in http://www.devexpress.com/Support/Center/p/Q103213.aspx I have managed to save my selection in a TList in the OnCanSelectRecord event which I was already using...

                                [Delphi]
                                procedure TDBeditDlg.BandedTableViewCanSelectRecord(Sender: TcxCustomGridTableView; ARecord: TcxCustomGridRecord; var AAllow: Boolean); begin AAllow := (ARecord.Level >= BandedTableView.Controller.FocusedRecord.Level) or (not ARecord.Expanded); if BandedTableView.Controller.SelectedRowCount >= 1 then ASelectionOrder.Add(pointer(ARecord.RecordIndex)) else begin ASelectionOrder.Clear; ASelectionOrder.Add(pointer(ARecord.RecordIndex)); end; end;

                                Now in the OnMouseUp event I have the following code...

                                [Delphi]
                                procedure TDBeditDlg.BandedTableViewMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var I: Integer; begin with BandedTableView.DataController do begin for I := 0 to ASelectionOrder.Count - 1 do begin ChangeRowSelection(integer(ASelectionOrder.Items[I]), True); end; end; end;

                                Which works fine when just clicking around on the grid and selecting rows etc.

                                However my saved selection list is forgotten as soon as I edit an individual cell and replaced with that one rows' info only and therefore I cannot seem to programatically reselect the rows I had selected in the first place :(

                                Am I missing something? Do I need to modify the OnCanSelectRecord code further to only remember multiselected rows?

                                Once I have this cracked, then I can start work on the OnDataChanged event code asking if the end user wants to apply changes to all records.

                                Many thanks for your help in advance and kind regards as ever,

                                Giles.

                                0

                                Hi Eugene,

                                I have now uploaded a demo for you based up the demo I created for Serge for my other outstanding query...
                                http://www.devexpress.com/Support/Center/p/Q103225.aspx

                                Now I have two issues with the demo at this point...

                                Firstly, I am unable to unselect a row once the MultiEdit button is down and once the row is in the ASelection list.

                                Secondly, I can now have multiple rows selected when I drop down the combobox in the RATE column but when I do drop the combobox down, it always unselects one row from the visible selected rows.
                                To emulate this, have the MultiEdit button down and then select rows 2 to 9 and click the RATE combobox in row 5 - row 2 becomes unselected strangely.

                                I am so close to a solution and really want to keep the Quantum Grid and not go back to the older rubbish grids.

                                Can you please see if there is a way to get the two issues above to work and to see if my code is working correctly. :)

                                Many thanks and kind regards as ever,

                                Giles.

                                0

                                Hi Giles,

                                When you try to edit cell's contents, the record is focused (the OnCanFocuseRecord event occurs), the OnMouseDown event occurs (it is point where selection is cleared), the record is selected (at this point the OnCanSelectRecord event occurs) and the OnMouseUp event is invoked.

                                So, to solve your problem in this way, you need to handle the OnCanFocuseRecord event, and set a a global variable to indicate that you need to repair a stored selection in the OnMouseUp event handler after it would be cleared in handling of the OnMouseDown event. You need also check this variable in the OnCanSelectRecord event to prevent clearing your stored selection list.

                                Note that when you partially clear your selection by holding down the Ctrl key, the OnCanSelectRecord event isn't called. So, you need to handle the partially clearing your selection in the OnSelectionChanged event.
                                Also, in this case, your global variable must indicate that the selection need not be restored. So, you need to handle the OnMouseDown event, and prevent this situation.

                                This solution is difficult and may not work correctly in some cases. I've attached a sample illustrating this solution.

                                Thanks,
                                Eugene

                                0

                                Hi Eugene :)

                                Thanks ever so much for your reply. I am looking at the code now and will let you know how I get on.

                                One question I have, is the "ApplyFieldChanges" procedure the proc to be used with the ForEachMethod procedure in the OnDataChanged event?

                                Many thanks and kind regards,

                                Giles.

                                0

                                Ok...

                                To help out further, I have updated your example to try to set the OnDataChanged Event correctly.

                                However the code will not let me even get to the Messagedlg to ask the question as it comes up with an access violation first.

                                Is my approach correct using the "ApplyFieldChanges" procedure and do you know what is causing the issue that is stopping me answer the question?

                                Many thanks and kind regards as ever,

                                Giles.

                                0

                                Hi Giles,

                                You try to change data in the OnDataChanged event handler, so it leads to AV's because this event is fired for each data chang and the event handler recurses to itself. Also, the ApplyFieldChanges procedure must be modified, because it changes data only in the DataController without posting them to the underlying dataset.

                                I suggest you use the dataset's AfterPost event handler, and change data directly in the dataset. It is necessary to change data after the end of this procedure to prevent AV's. In this case, create the ApplyFieldChanges message handler and use the PostMessage command to send it from the end of the message queue (after the AfterPost event handler ends).

                                Use the DataSet.Locate method to locate the currently processed record in the underlying dataset. But note that this method changes the focus in your dataset, and you need to store the original focused record and then restore it (just use the DataSet.GetBookmark and DataSet.GotoBookmark methods for this purpose). Use the DataSet.Lookup method to access the value you need posted in the corresponding fields of the selected records of the underlying dataset.

                                The other issue is that you need to disable your AfterPost event handler after it starts, to prevent recursing of this handler (because this event is fired after a modification or insertion is made to an active record). Note, that it does not prevent recursing of the inherited event handler. So, you can disable your AfterPost event by setting the Dataset.AfterPost property to nil at the beginning of the AfterPost event handler. Then, create a new message handler that restores the original Dataset.AfterPost property value. Use the PostMessage command to send this message from the end of the message queue (after all data will be changed).

                                Determine if the GridView's DataController.Options property is set to dcoImmediatePost. In this case, the changes to a field value (edit value) are immediately posted to a dataset. Otherwise, they are posted after the focus moves to another record.

                                Please refer to the "Using Locate", "Using Lookup", "TDataSet.AfterPost Event", "Using Messages and Message Queues" and "Creating New Message Handlers" topics of the Delphi help, for detailed information. See the "TcxDataControllerOption type" topics of the ExpressQuantumGrid help.

                                I've attached a sample. Please try it and let me know how it works for you.

                                Thanks,
                                Eugene

                                0

                                Hi Eugene :)

                                First off, a million thanks for your help with this so far.

                                I have been adapting your code into my large application and it seems to be going well. I am building it all into my generic event handlers for all my grids so they share the code and I dont have to replicate a hundred times :)

                                I only have 2 issues left it appears now...

                                If you have the indicator visible and click on it, it causes an AV (can be reproduced in your demo) and also clicking a checkbox for a boolean field unselects all the rows too. Is there an easy way to enhance the code to fix these two issues?

                                Many thanks and kind regards as ever,

                                Giles.

                                0

                                Sorry Eugene that should have read...

                                If you have the indicator visible and CTRL click on it

                                0

                                Hi Giles,

                                1) This issue also occurs when you Ctrl click on an item in your GridView, except cells. Just see the code of the <AGridView>MouseDown procedure. The code I've provided is only a common solution to prevent selection clearing when you deselect rows in your GridView by Ctrl clicking on them. Modify the if...then clause as you need to handle the Ctrl click correctly.

                                To solve this problem, modify the OnMouseDown event handler as follows:

                                [Delphi]
                                procedure TForm1.<AGridView>MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var ACellTest : TcxGridRecordCellHitTest; begin with <AGridView> do begin if (GetHitTest(X, Y) is TcxGridRecordCellHitTest) then begin ACellTest := GetHitTest(X, Y) as TcxGridRecordCellHitTest; if (Shift * [ssCtrl, ssShift] <> []) and ACellTest.GridRecord.Selected then AKeepSelection := false; end; end; end;

                                2) Your selection is cleared, because the OnMouseUp event doesn't fire when you are clicking on a cell in a column with CheckBox properties. I've found an alternative way to restore a selection after it has been cleared. You can use the OnSelectionChanged event handler for this purpose and add the code from your OnMouseUp event handler to it.

                                Here is a sample of the modified OnSelectionChanged event handler:

                                [Delphi]
                                procedure TForm1.<AGridView>SelectionChanged( Sender: TcxCustomGridTableView); var I : integer; begin with Sender.ViewData, Sender.Controller do if AKeepSelection then begin for I := 0 to ASelection.Count - 1 do begin GetRecordByRecordIndex(integer(ASelection.Items[I])).Selected := True; end; AKeepSelection := false; end else if (SelectedRecordCount > 1) and (SelectedRecordCount <> ASelection.Count) then ASelection.Remove(pointer(FocusedRecordIndex)); end;

                                Don't forget to clear the OnMouseUp event handler.

                                Thanks,
                                Eugene

                                0

                                Hi Eugene,

                                Thanks again for you reply :)

                                I have just checked however and the code in the MouseDown event you have just sent is the same as was in the demo you sent...

                                [Delphi]
                                procedure TForm1.<AGridView>MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var ACellTest : TcxGridRecordCellHitTest; begin with <AGridView> do begin if (GetHitTest(X, Y) is TcxGridRecordCellHitTest) then begin ACellTest := GetHitTest(X, Y) as TcxGridRecordCellHitTest; if (Shift * [ssCtrl, ssShift] <> []) and ACellTest.GridRecord.Selected then AKeepSelection := false; end; end; end;

                                So I cannot modify the OnMouseDown event handler as it is the same. Is it meant to be?

                                Will modify the OnSelectionChanged event handler now and remove the mouse up one and let you know how I get on in the meantime.

                                Many thanks and kind regards as ever,

                                Giles.

                                0

                                Hi Giles,

                                It is really strange, because you can find the code of the OnMouseDown event in dxSample_Q103514:

                                [Delphi]
                                procedure TForm1.<AGridView>MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var ACellTest : TcxGridRecordCellHitTest; begin with <AGridView> do begin if (GetHitTest(X, Y) is TcxGridRecordCellHitTest) then ACellTest := GetHitTest(X, Y) as TcxGridRecordCellHitTest; if (Shift * [ssCtrl, ssShift] <> []) and ACellTest.GridRecord.Selected then AKeepSelection := false; end; end;

                                The correct code is the following:

                                [Delphi]
                                procedure TForm1.<AGridView>MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var ACellTest : TcxGridRecordCellHitTest; begin with <AGridView> do begin if (GetHitTest(X, Y) is TcxGridRecordCellHitTest) then begin ACellTest := GetHitTest(X, Y) as TcxGridRecordCellHitTest; if (Shift * [ssCtrl, ssShift] <> []) and ACellTest.GridRecord.Selected then AKeepSelection := false; end; end; end;

                                As you see, these fragments are not the same. Please check once again that the OnMouseDown event handler code is the correct code.

                                Thanks,
                                Eugene

                                0

                                Sorry Eugene my mistake - you are quite correct the code is slightly different.

                                I am very happy to say now that with the new MouseDown procedure and with the OnSelectionChanged event handler code, that the desired and required functionality is working as wanted by the end user.

                                Thank you so much for your help with this issue.

                                I have so far replaced 14 of the 71 grids in the application and apart from the outstanding issue with Serge, all has gone really well.

                                Thank you once again and kind regards,

                                Giles.

                                0

                                Thanks to Eugene for helping me out.

                                0

                                Hi Giles,

                                Would you mind if we made this report public, so that other customers could learn from it?

                                Thanks,
                                Alex

                                0

                                Hi Alex,

                                No probs :)

                                Knid regards,

                                Giles.

                                0

                                Thanks!

                                If you need additional product information, write to us at info@devexpress.com or call us at +1 (818) 844-3383

                                FOLLOW US

                                DevExpress engineers feature-complete Presentation Controls, IDE Productivity Tools, Business Application Frameworks, and Reporting Systems for Visual Studio, along with high-performance HTML JS Mobile Frameworks for developers targeting iOS, Android and Windows Phone. Whether using WPF, Silverlight, ASP.NET, WinForms, HTML5 or Windows 8, DevExpress tools help you build and deliver your best in the shortest time possible.

                                Copyright © 1998-2014 Developer Express Inc.
                                All trademarks or registered trademarks are property of their respective owners