Adding Delete Functionality to a Screen or Control
Overview
Nearly all the code to delete a specific record from a table can be auto-generated by Open Petra's code generation applications. A small amount of code is generated on the client and a larger amount is generated in the server. You can activate all this code by adding a few simple lines to the YAML file that defines the behaviour of the screen or user control. When you do this you will get
- a delete button with a label of your choice - but Delete by default
- code that enables or disables the button depending on the circumstances. Some records in Open Petra are specifically marked as being non-deletable.
- code that checks whether the row is referenced by another table or tables as a foreign key. If it is, a message box is displayed giving helpful information about which table(s) reference the data, and the delete action is abandoned.
- code to ask for pre-confirmation of the action.
- code to delete the relevant record.
- code to confirm a successful outcome.
In addition there are optional manual code file extensions that can be made before, during and after the delete action.
This auto-generated code only applies to screens that have a grid capable of displaying multiple selectable records.
Coding the YAML File
There are a few simple steps to code the YAML file to include standard deletion. You just need one line in the Actions section and some simple lines in the Controls section.
A typical Actions section will look like this
Actions: actNew: {Label=&New, ActionClick=NewRecord} actDelete: {Label=&Delete, ActionClick=DeleteRecord}
This has one action for the New button and one action for the Delete button
The equivalent Controls section would look like this
pnlButtons: Dock: Right Controls: [btnNew, btnDelete] btnNew: Action: actNew Stretch: horizontally btnDelete: Action: actDelete Stretch: horizontally
This has a panel containing the two buttons docked to the right. Each button specifies the associated action and, in order to make the buttons have the same size, they are both stretched horizontally.
It is as simple as that! The only rules are that the button must be named btnDelete and the action must be called actDelete. The label does not have to be Delete. The ActionClick does not have to be DeleteRecord but there is normally no reason to change these internal names.
Generating the C# Code
Normally you can make changes to a YAML file and it is a simple matter to create the C# code for the equivalent client screen and re-compile the client. But a YAML file with a delete button may require you to do more than this.
The critical occasions are
- when you edit a YAML file and add a new Delete button
- or when you create a new YAML file that contains a Delete button
If either of these cases apply then you will need to do the following
- save the YAML file(s)
- run generateORMReferenceCounts either using nant or the Developer's Assistant
- run generateGlue either using nant or the Developer's Assistant
- run generateWinform on the YAML file(s) (or generateWinforms for all forms) - again using nant or the Developer's Assistant
- compile both the server and the client
Please understand that once you have done these actions once on the YAML file there is no need to repeat them again because you now have generated all the code on the server that you need. Any subsequent changes to the YAML file that you make (for example laying out the controls so that they look nice) can be compiled to C# and/or previewed in the normal way because the server code will not change when you do that.
Auto-generated Client Code
So what code gets generated on the client? There are three snippets of code that we generate on the client.
First there is a click event handler that simply calls a standard method. This code example deletes a record from the p_business table.
private void DeleteRecord(Object sender, EventArgs e) { DeletePBusiness(); }
Second there is a line of code that handles the enable/disable state of the button
FPetraUtilsObject.EnableAction("actDelete", ((ARow != null) && (ARow.Deletable == true) && !FPetraUtilsObject.DetailProtectedMode));
Finally there is the deletion code itself - in this example in the method DeletePBusiness()
private void DeletePBusiness() { bool AllowDeletion = true; bool DeletionPerformed = false; string DeletionQuestion = Catalog.GetString("Are you sure you want to delete the current row?"); string CompletionMessage = string.Empty; TVerificationResultCollection VerificationResults = null; if (FPreviouslySelectedDetailRow == null) { return; } this.Cursor = Cursors.WaitCursor; TRemote.MPartner.ReferenceCount.WebConnectors.GetCacheableRecordReferenceCount( "BusinessCodeList", DataUtilities.GetPKValuesFromDataRow(FPreviouslySelectedDetailRow), out VerificationResults); this.Cursor = Cursors.Default; if ((VerificationResults != null) && (VerificationResults.Count > 0)) { MessageBox.Show(Messages.BuildMessageFromVerificationResult( Catalog.GetString("Record cannot be deleted!") + Environment.NewLine + Catalog.GetPluralString("Reason:", "Reasons:", VerificationResults.Count), VerificationResults), Catalog.GetString("Record Deletion")); return; } if(AllowDeletion) { if ((MessageBox.Show(DeletionQuestion, Catalog.GetString("Confirm Delete"), MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == System.Windows.Forms.DialogResult.Yes)) { int SelectedRow = grdDetails.SelectedRowIndex(); FPreviouslySelectedDetailRow.Delete(); DeletionPerformed = true; if (DeletionPerformed) { FPetraUtilsObject.SetChangedFlag(); // Select and display the details of the nearest row to the one previously selected SelectRowInGrid(SelectedRow); } } } if(DeletionPerformed && CompletionMessage.Length > 0) { MessageBox.Show(CompletionMessage, Catalog.GetString("Deletion Completed")); } }
This snippet of code does the following.
- It checks that the row is not empty
- It queries the server to find out of the row is currently referenced by another table or tables. If it is it displays a helpful message and exits the function.
- It asks the user to confirm deletion. The user can abandon deletion at this point.
- It deletes the record
- It displays a 'success' message
The reference count message is something like: You cannot delete this record. It is used by 3 records in the XXX table and 19 records in the YYY table. An example of a record that uses this record is found in Partner with a key of 43005009.
You can modify the behaviour of the deletion process by including any or all of the following methods in your manual code file.
private bool PreDeleteManual(PInternationalPostalTypeRow ARowToDelete, ref string ADeletionQuestion) private bool DeleteRowManual(PInternationalPostalTypeRow ARowToDelete, out string ACompletionMessage) private void PostDeleteManual(PInternationalPostalTypeRow ARowToDelete, bool AAllowDeletion, bool ADeletionPerformed, string ACompletionMessage)
- If the first method returns false the deletion will be abandoned. You can use this method to modify the deletion question.
- The second method can be used to replace the standard record deletion code with more complex code of your choice. You can modify the completion message. You return true or false depending on whether the deletion succeeded.
- The third optional manual method can be used to do manual clean-up after deletion has occurred. The parameters tell you if deletion was initially allowed/disallowed, whether deletion actually succeeded and what the recommended message is that should be shown.
Auto-generated Server Code
You will notice from the client code above that the client calls a method on the server named
TRemote.MPartner.ReferenceCount.WebConnectors.GetCacheableRecordReferenceCount
using a web connector method. (There is an equivalent non-cacheable table method too). All the code to implement the connectors, interfaces and implementations of these methods is auto-generated for the server.
The implementations are all found in the web folder beneath Server/lib/ModuleName in a file named ReferenceCount-generated.cs. So, for example, there is a file csharp/ICT/Petra/Server/lib/MPartner/ReferenceCount-generated.cs. These implementations all call standard Data Access methods to determine the reference counts and construct a Verification Result Collection that should be returned to the client.
Delete Button Implementation
Analysis run at 18:05 on 11/04/2013.
All the files listed below have either a 'New' button or an 'Add' button with a name containing btnNew or btnAdd
Screens Based on Template: WindowEdit (7 files use this template. The following have Add/Delete functionality)
Filename | DetailTable | Has New Button | Has Delete Button | Has Auto-delete | Has ReferenceCount | Has Deletable Flag | Calls .Delete() | Manual Calls Auto |
---|---|---|---|---|---|---|---|---|
MSysMan\Gui\MaintainUsers.yaml | SUser | Yes | No | n/a | ||||
MPartner\Gui\PersonnelStaffData.yaml | PmStaffData | Yes | Yes | No | Yes | |||
MFinance\Gui\Setup\GiftMotivationSetup.yaml | AMotivationDetail | Yes | Yes | Yes | Yes | |||
MFinance\Gui\Setup\MotivationGroupSetup.yaml | AMotivationGroup | Yes | Yes | Yes | ||||
MFinance\Gui\Setup\SetupAnalysisTypes.yaml | AAnalysisType | Yes | Yes | No | Yes | |||
MFinance\Gui\Common\BankStatementImport.yaml | Yes | Yes | No | No | Yes |
Screens Based on Template: WindowTDS (6 files use this template. The following have Add/Delete functionality)
Filename | DetailTable | Has New Button | Has Delete Button | Has Auto-delete | Has ReferenceCount | Has Deletable Flag | Calls .Delete() | Manual Calls Auto |
---|
Screens Based on Template: WindowMaintainTable (8 files use this template. The following have Add/Delete functionality)
Filename | DetailTable | Has New Button | Has Delete Button | Has Auto-delete | Has ReferenceCount | Has Deletable Flag | Calls .Delete() | Manual Calls Auto |
---|---|---|---|---|---|---|---|---|
MSysMan\Gui\Setup\SecurityGroupSetup.yaml | SGroup | Yes | Yes | Yes | ||||
MPersonnel\Gui\Setup\ApplicationTypeSetup.yaml | PtApplicationType | Yes | Yes | Yes | Yes | |||
MPartner\Gui\Setup\MailingSetup.yaml | PMailing | Yes | Yes | Yes | ||||
MFinance\Gui\Setup\CurrencyLanguageSetup.yaml | ACurrencyLanguage | Yes | Yes | Yes | ||||
MFinance\Gui\Setup\SetupCorporateExchangeRate.yaml | ACorporateExchangeRate | Yes | No | n/a | ||||
MFinance\Gui\Setup\SetupDailyExchangeRate.yaml | ADailyExchangeRate | Yes | Yes | No | Yes | |||
MCommon\Gui\Setup\InternationalPostalTypeSetup.yaml | PInternationalPostalType | Yes | Yes | No | Yes | Yes | ||
MCommon\Gui\Setup\SetupCurrency.yaml | ACurrency | Yes | Yes | No | Yes |
Screens Based on Template: WindowMaintainCacheableTable (57 files use this template. The following have Add/Delete functionality)
Filename | DetailTable | CacheableTable | Has New Button | Has Delete Button | Has Auto-delete | Has ReferenceCount | Has Deletable Flag | Calls .Delete() | Manual Calls Auto |
---|---|---|---|---|---|---|---|---|---|
MSysMan\Gui\Setup\LanguageSpecificSetup.yaml | SLanguageSpecific | LanguageSpecificList | Yes | Yes | Yes | ||||
MPersonnel\Gui\Setup\AbilityAreaSetup.yaml | PtAbilityArea | AbilityAreaList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\AbilityLevelSetup.yaml | PtAbilityLevel | AbilityLevelList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\ApplicantStatusSetup.yaml | PtApplicantStatus | ApplicantStatusList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\ArrivalDeparturePointSetup.yaml | PtArrivalPoint | ArrivalDeparturePointList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\Country_EventLevelSetup.yaml | PtOutreachPreferenceLevel | OutreachPreferenceLevelList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\DocumentTypeCategorySetup.yaml | PmDocumentCategory | DocumentTypeCategoryList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\DocumentTypeSetup.yaml | PmDocumentType | DocumentTypeList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\DriverStatusSetup.yaml | PtDriverStatus | DriverStatusList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\EventRoleSetup.yaml | PtCongressCode | EventRoleList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\JobAssignmentTypeSetup.yaml | PtAssignmentType | JobAssignmentTypeList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\LanguageLevelSetup.yaml | PtLanguageLevel | LanguageLevelList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\LeadershipRatingSetup.yaml | PtLeadershipRating | LeadershipRatingList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\LeavingCodeSetup.yaml | PtLeavingCode | LeavingCodeList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\OrganisationContactSetup.yaml | PtContact | ContactList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\PassportTypeSetup.yaml | PtPassportType | PassportTypeList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\PositionSetup.yaml | PtPosition | PositionList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\ProfessionalAreaSetup.yaml | PtQualificationArea | QualificationAreaList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\QualificationLevelSetup.yaml | PtQualificationLevel | QualificationLevelList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\SkillCategorySetup.yaml | PtSkillCategory | SkillCategoryList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\SkillLevelSetup.yaml | PtSkillLevel | SkillLevelList | Yes | Yes | Yes | Yes | |||
MPersonnel\Gui\Setup\TransportTypeSetup.yaml | PtTravelType | TransportTypeList | Yes | Yes | Yes | Yes | |||
MPartner\Gui\Setup\AcquisitionCodeSetup.yaml | PAcquisition | AcquisitionCodeList | Yes | Yes | Yes | Yes | |||
MPartner\Gui\Setup\AddresseeTypeSetup.yaml | PAddresseeType | AddresseeTypeList | Yes | Yes | Yes | Yes | |||
MPartner\Gui\Setup\BusinessCodeSetup.yaml | PBusiness | BusinessCodeList | Yes | Yes | Yes | Yes | |||
MPartner\Gui\Setup\ContactAttributeSetup.yaml | PContactAttribute | ContactAttributeList | Yes | Yes | No | Yes | |||
MPartner\Gui\Setup\ContactMethodSetup.yaml | PMethodOfContact | MethodOfContactList | Yes | Yes | Yes | Yes | |||
MPartner\Gui\Setup\DenominationCodeSetup.yaml | PDenomination | DenominationList | Yes | Yes | Yes | Yes | |||
MPartner\Gui\Setup\InterestCategorySetup.yaml | PInterestCategory | InterestCategoryList | Yes | Yes | Yes | ||||
MPartner\Gui\Setup\InterestSetup.yaml | InterestList | Yes | Yes | Yes | |||||
MPartner\Gui\Setup\LocalDataOptionListNameSetup.yaml | PDataLabelLookupCategory | DataLabelLookupCategoryList | Yes | Yes | Yes | ||||
MPartner\Gui\Setup\LocalDataOptionsSetup.yaml | PDataLabelLookup | DataLabelLookupList | Yes | Yes | Yes | ||||
MPartner\Gui\Setup\LocationTypeSetup.yaml | PLocationType | LocationTypeList | Yes | Yes | Yes | Yes | |||
MPartner\Gui\Setup\MaritalStatusSetup.yaml | PtMaritalStatus | MaritalStatusList | Yes | Yes | Yes | Yes | |||
MPartner\Gui\Setup\OccupationCodeSetup.yaml | POccupation | OccupationList | Yes | Yes | Yes | Yes | |||
MPartner\Gui\Setup\PartnerStatusSetup.yaml | PPartnerStatus | PartnerStatusList | Yes | Yes | Yes | Yes | |||
MPartner\Gui\Setup\PartnerTypeSetup.yaml | PType | PartnerTypeList | Yes | Yes | Yes | Yes | |||
MPartner\Gui\Setup\PublicationCostSetup.yaml | PPublicationCost | PublicationCostList | Yes | Yes | Yes | ||||
MPartner\Gui\Setup\PublicationSetup.yaml | PPublication | PublicationList | Yes | Yes | Yes | ||||
MPartner\Gui\Setup\ReasonSubscriptionCancelledSetup.yaml | PReasonSubscriptionCancelled | ReasonSubscriptionCancelledList | Yes | Yes | Yes | ||||
MPartner\Gui\Setup\ReasonSubscriptionGivenSetup.yaml | PReasonSubscriptionGiven | ReasonSubscriptionGivenList | Yes | Yes | Yes | ||||
MPartner\Gui\Setup\RelationCategorySetup.yaml | PRelationCategory | RelationCategoryList | Yes | Yes | Yes | Yes | |||
MPartner\Gui\Setup\RelationshipSetup.yaml | PRelation | RelationList | Yes | Yes | Yes | Yes | |||
MFinance\Gui\Setup\EmailDestinationSetup.yaml | AEmailDestination | EmailDestinationList | Yes | Yes | Yes | ||||
MFinance\Gui\Setup\SetupAdminGrantsPayable.yaml | AFeesPayable | FeesPayableList | Yes | Yes | Yes | ||||
MFinance\Gui\Setup\SetupAdminGrantsReceivable.yaml | AFeesReceivable | FeesReceivableList | Yes | Yes | Yes | ||||
MFinance\Gui\Setup\SetupCostCentreTypes.yaml | ACostCentreTypes | CostCentreTypesList | Yes | Yes | Yes | Yes | |||
MFinance\Gui\Setup\SetupMethodOfGiving.yaml | AMethodOfGiving | MethodOfGivingList | Yes | Yes | No | Yes | |||
MFinance\Gui\Setup\SetupMethodOfPayment.yaml | AMethodOfPayment | MethodOfPaymentList | Yes | Yes | Yes | ||||
MFinance\Gui\Setup\SetupSuspenseAccount.yaml | ASuspenseAccount | SuspenseAccountList | Yes | Yes | No | Yes | |||
MConference\Gui\Setup\ConferenceCostTypeSetup.yaml | PcCostType | ConferenceCostTypeList | Yes | Yes | Yes | Yes | |||
MCommon\Gui\Setup\CountrySetup.yaml | PCountry | CountryList | Yes | Yes | Yes | Yes | |||
MCommon\Gui\Setup\FrequencySetup.yaml | AFrequency | FrequencyList | Yes | Yes | Yes | ||||
MCommon\Gui\Setup\LanguageCodeSetup.yaml | PLanguage | LanguageCodeList | Yes | Yes | Yes | Yes | |||
MCommon\Gui\Setup\LocalDataFieldSetup.yaml | PDataLabel | DataLabelList | Yes | Yes | Yes | Yes |
Screens Based on Template: WindowEditUIConnector (3 files use this template. The following have Add/Delete functionality)
Filename | DetailTable | Has New Button | Has Delete Button | Has Auto-delete | Has ReferenceCount | Has Deletable Flag | Calls .Delete() | Manual Calls Auto |
---|---|---|---|---|---|---|---|---|
MFinance\Gui\Budget\MaintainBudget.yaml | ABudget | Yes | Yes | No | Yes |
Screens Based on Template: WindowEditWebConnectorMasterDetail (1 files use this template. The following have Add/Delete functionality)
Filename | DetailTable | Has New Button | Has Delete Button | Has Auto-delete | Has ReferenceCount | Has Deletable Flag | Calls .Delete() | Manual Calls Auto |
---|---|---|---|---|---|---|---|---|
MFinance\Gui\AP\APEditDocument.yaml | AApDocumentDetail | Yes | Yes | No | No | Yes |
Screens Based on Template: ControlMaintainTable (29 files use this template. The following have Add/Delete functionality)
Filename | DetailTable | Has New Button | Has Delete Button | Has Auto-delete | Has ReferenceCount | Has Deletable Flag | Calls .Delete() | Manual Calls Auto |
---|---|---|---|---|---|---|---|---|
MPartner\Gui\UC_Applications.yaml | PmGeneralApplication | Yes | Yes | No | Yes | |||
MPartner\Gui\UC_FinanceDetails.yaml | PBankingDetails | Yes | Yes | No | Yes | |||
MPartner\Gui\UC_IndividualData_Abilities.yaml | PmPersonAbility | Yes | Yes | No | Yes | |||
MPartner\Gui\UC_IndividualData_CommitmentPeriods.yaml | PmStaffData | Yes | Yes | No | Yes | |||
MPartner\Gui\UC_IndividualData_JobAssignments.yaml | PmJobAssignment | Yes | Yes | No | Yes | |||
MPartner\Gui\UC_IndividualData_Passport.yaml | PmPassportDetails | Yes | Yes | No | Yes | |||
MPartner\Gui\UC_IndividualData_PersonalDocuments.yaml | PmDocument | Yes | Yes | No | Yes | |||
MPartner\Gui\UC_IndividualData_PersonalLanguages.yaml | PmPersonLanguage | Yes | Yes | No | Yes | |||
MPartner\Gui\UC_IndividualData_PersonSkills.yaml | PmPersonSkill | Yes | Yes | No | Yes | |||
MPartner\Gui\UC_IndividualData_PreviousExperience.yaml | PmPastExperience | Yes | Yes | No | Yes | |||
MPartner\Gui\UC_IndividualData_ProgressReports.yaml | PmPersonEvaluation | Yes | Yes | No | Yes | |||
MPartner\Gui\UC_PartnerRelationships.yaml | PPartnerRelationship | Yes | Yes | No | Yes | |||
MPartner\Gui\UC_Subscriptions.yaml | PSubscription | Yes | Yes | No | Yes | |||
MPartner\Gui\Extracts\UC_ExtractMaintain.yaml | MExtract | Yes | Yes | Yes | Yes | |||
MPartner\Gui\Extracts\UC_ExtractMasterList.yaml | MExtractMaster | No | Yes | No | Yes | |||
MFinance\Gui\Setup\UC_AccountAnalysisAttributes.yaml | AAnalysisAttribute | Yes | Yes | No | Yes | |||
MFinance\Gui\Setup\UC_SetupAnalysisValues.yaml | AFreeformAnalysis | Yes | Yes | No | Yes | |||
MFinance\Gui\GL\UC_GLBatches.yaml | ABatch | Yes | No | n/a | Yes | |||
MFinance\Gui\GL\UC_GLJournals.yaml | AJournal | Yes | No | n/a | Yes | |||
MFinance\Gui\GL\UC_GLTransactions.yaml | ATransaction | Yes | Yes | No | No | Yes | ||
MFinance\Gui\GL\UC_RecurringGLBatches.yaml | ARecurringBatch | Yes | Yes | No | Yes | |||
MFinance\Gui\GL\UC_RecurringGLJournals.yaml | ARecurringJournal | Yes | Yes | No | Yes | |||
MFinance\Gui\GL\UC_RecurringGLTransactions.yaml | ARecurringTransaction | Yes | Yes | No | Yes | |||
MFinance\Gui\Gift\UC_GiftBatches.yaml | AGiftBatch | Yes | Yes | Yes | Yes | |||
MFinance\Gui\Gift\UC_GiftTransactions.yaml | AGiftDetail | Yes | Yes | No | Yes | |||
MFinance\Gui\Gift\UC_RecurringGiftBatches.yaml | ARecurringGiftBatch | Yes | Yes | No | Yes | |||
MFinance\Gui\Gift\UC_RecurringGiftTransactions.yaml | ARecurringGiftDetail | Yes | Yes | No | Yes |
Screens Based on Template: ControlMaintainCacheableTable (1 files use this template. The following have Add/Delete functionality)
Filename | DetailTable | CacheableTable | Has New Button | Has Delete Button | Has Auto-delete | Has ReferenceCount | Has Deletable Flag | Calls .Delete() | Manual Calls Auto |
---|---|---|---|---|---|---|---|---|---|
MPartner\Gui\Setup\UC_ContactAttributeDetail.yaml | PContactAttributeDetail | ContactAttributeDetailList | Yes | Yes | No | Yes |
Summary
83 potential issues found in 43 files There are 98 New/Add buttons in the application There are 95 Delete/Remove buttons in the application 60 of these call the auto-delete function 35 of these call a manual delete function 5 of these call the auto-delete function from manual code