controlMaintainTable
controlMaintainCacheableTable
windowEdit
windowMaintainTable
windowMaintainCacheableTable
windowEditWebConnectorMasterDetail
[/list:u]
These tables have been modified because they are the ones that have a details panel.
I have made quite substantial changes to the two event handlers that deal with the grid (FocusedRowLeaving and FocusedRowChanged). I believe the duplicate event detection is improved. I have also changed the code that acts upon these events. FocusedRowLeaving now ONLY deals with validation (on non-duplicate events) and FocusedRowChanged now ONLY deals with showing the current details in the details panel. With this new code the events are entirely managed within the generated code file. It is never necessary to 'invoke' an event manually. There are no longer form-level variables that you need to know about as a manual code author. Even the variable that we had before named FCurrentRow has gone. FPreviouslySelectedDetailRow is still there but this is automatically handled by the call to show the details in the details panel. It should never really be necessary for you to set FPreviouslySelectedDetailRow as a manual code author, as you will see in a moment.
This has meant that I have been able to simplify the code in places and I have added a couple of new methods/over-rides to make life easier for the manual code author.
All the most commonly used generated code methods now have full intellisense comments, so now you get help when using them in manual code. Please have a look at these comments as you browse the new generated code for the screens that you are familiar with.
Here is a description of the most common methods you will need to use.
Methods for Showing Details
The basic method to ShowDetails(YourTypedRow ARow) is unchanged. This shows the details for a specified row. Please note that it contains enough smart logic to enable/disable the panel depending on whether ARow is NULL or if the data is in DetailProtectMode.
I have added a new overload, which is simply ShowDetails(). This shows the details for the currently highlighted row. It turns out that this is the commonest way of wanting the details to be shown. Internally this is just the following.
private void ShowDetails()
{
ShowDetails(GetSelectedDetailRow());
}
(ShowDetails() is just easier to write and remember!!)
Remember: ShowDetails methods work equally well when the current row is null or the grid has no row data.
The two ShowDetails methods set up the FPreviouslySelectedDetailRow variable. So once you have shown the details for a row you are free to use it as a means of accessing column data.
Row Selection Methods
There are two main row selection methods – again, one old and one new.
private void SelectDetailRowByDataTableIndex(Int32 ARowNumberInTable, bool AAndShowDetails = false)
This is the method that we have had all along. Typically it is used to select the row that has just been created using the New button. But now it has an optional parameter that defaults to false (to keep existing behaviour). When the additional parameter is true the method calls ShowDetails() so that the details panel is automatically updated to reflect the newly selected data.
The new method is:
private void SelectRowInGrid(int ARowIndex, bool AAndShowDetails = false)
{
grdDetails.SelectRowInGrid(ARowIndex, TSgrdDataGrid.TInvokeGridFocusEventEnum.NoFocusEvent);
if (AAndShowDetails) ShowDetails();
}
This new method is another convenience. It wraps up the call that Chris Thomas wrote in the grid wrapper to select a row in the grid without causing any events. It means that as an author you no longer need to remember that some methods are associated with the grid object while others are internal to the generated code.
You will see that this method has the same optional parameter that means that you can select a row AND show its details all in one line.
You need to understand that this method is particularly powerful because the row index that you supply does not even have to be within the range 1..DataRowCount. If the grid has no rows, no row is highlighted. If the specified row index is less than 1, the first row is highlighted. If the row index is more than DataRowCount, the last row is highlighted. So you can appreciate that this is a useful method even when deleting rows. Simply call the method passing the index of the deleted row and the relevant row will be selected, the correct details will be shown for that row and FPreviouslySelectedDetailRow will automatically be updated!
If you are writing manual code that needs to select a specific row, you will almost always find that
SelectRowInGrid(rowIndex, true)
is all you need.
Finally it is worth mentioning that SelectRowInGrid is inexpensive in computing terms – it simply highlights the specified row. In contrast SelectDetailRowByDataTableIndex() does potentially involve looping through all the records in the grid.
Getting the Selected Row
These methods have not changed.
GetSelectedDetailRow() returns the selected row as a reference to a typed data row in the grid. This call is a call to the grid object and is not expensive in terms of computation.
GetDetailGridRowDataTableIndex() returns the index in the data table for the data in the current grid row. This method is more expensive in terms of computation because it goes round a loop.
More About Events
The FocusedRow Events are triggered by the user as he interacts with the GUI. Cursor keys trigger events as does an initial load of data into the grid. These events are entirely transparent to the manual code author, so it should never be necessary to invoke these events or access the form-level variables that they use.
As I have just explained, none of the SelectRow… methods cause events to be fired. So this results in a good separation between the code that runs in the auto-generated section and the code that runs in the manual section.
If you look at the event code you will see that we detect duplicate row leaving events AND duplicate row changed events. While duplicate leaving events only ever give rise to one changed event, it is possible to get a changed event without a leaving event. This happens each time you tab round the controls past the grid. So the current code automatically disregards these duplicate changed events.
Although these grid events are managed to occur singly, the data validation event is fired many times as the user tabs from control to control. This is, of course, by design.
More About Template Changes
This comment is particularly for Christian! If you look at the differences in the templates, please do not be alarmed at the way the ValidateAllData section seems to have changed. There is actually very little difference to the output. I have slightly re-arranged the nesting of multiple {IFDEF’s with a view to the changes that will come later to do with exception handling of duplicate records. So actually there should really only be one additional line in the generated c# code that ensures that the correct row is still highlighted after validating on a sorted grid. I thought that, since we were going to give our code a very thorough testing before this release, it would be an opportunity to slip this change in. Then in the future I can add the exception handling very easily, rather than have to make these re-arrangements to the template at that time.
I hope that is ok.
And, yes, my famous ’10 lines’ of code that handles the tracking of the highlighted row after validation has collapsed to just one line, by using the new methods for selecting a row in the grid.
These Screens Have Had Their Manual Code Files Modified
The following screens have all had MANUAL.CS files modified by me because of the changes to method calls in the generated code. I suggest that you look at the changes that have been made using Diff in the Bazaar Log, and then confirm that the screens still behave correctly.
In Finance:
UC_GLBatches
UC_GLJournals
UC_GLTransactions
UC_GiftBatches
UC_GiftTransactions
UC_RecurringGiftBatches
UC_RecurringGiftTransactions
SetupCorporateExchangeRate
SetupDailyExchangeRate (I will be changing this one anyway, hopefully soon)
[/list:u]
(Sorry Chris that you have the most to check – but at least it is all code that you have recently worked on so it shouldn’t take too long for you to confirm it is ok)
In MCommon