How-To: Creating a Maintain Table screen: Difference between revisions
No edit summary |
|||
(26 intermediate revisions by 3 users not shown) | |||
Line 42: | Line 42: | ||
*** that there is a similar number of data fields in the details section below the grid. | *** that there is a similar number of data fields in the details section below the grid. | ||
** Should one or two columns in the grid or one or two data fields in the details section be different, this screen is still suitable for a 'similar screen' that we can start off with. | ** Should one or two columns in the grid or one or two data fields in the details section be different, this screen is still suitable for a 'similar screen' that we can start off with. | ||
==Step 2: Copying existing screen definition file to new screen== | ==Step 2: Copying existing screen definition file to new screen== | ||
Line 54: | Line 55: | ||
* Recall what Module, Sub-Module and Area you chose, and which Task you chose from the Task List to bring up the existing, similar Maintain Table screen. | * Recall what Module, Sub-Module and Area you chose, and which Task you chose from the Task List to bring up the existing, similar Maintain Table screen. | ||
* Open the following file in a text editor (e.g. Notepad, Notepad++) | * Open the following file in a text editor (e.g. Notepad, Notepad++) | ||
U:\openpetraorg\csharp\ICT\Petra\Definitions\UINavigation.yml | U:\openpetraorg\''NameOfYourFeatureBranch''\csharp\ICT\Petra\Definitions\UINavigation.yml | ||
* ''NameOfYourFeatureBranch'' is the name of the Feature Branch on which you are currently working. There will be one Feature Branch for each new Maintain Table Screen (or one Feature Branch for several Maintain Table screens if you are doing a batch of new Maintain Table screens). (Your mentor will have created that Feature Branch for you and you will need to have it checked out already.) | |||
* This file contains a structure that is used for builing the Navigation structure which you see in the Main Menu's Navigation Panel of openPETRA. | * This file contains a structure that is used for builing the Navigation structure which you see in the Main Menu's Navigation Panel of openPETRA. | ||
* Scroll through the file until you find the Module, Sub-Module, Area and Task that describes the Task that you clicked to bring up the existing, similar Maintain Table screen (the hierarchy is created by indentation!). | * Scroll through the file until you find the Module, Sub-Module, Area and Task that describes the Task that you clicked to bring up the existing, similar Maintain Table screen (the hierarchy is created by indentation!). | ||
Line 63: | Line 65: | ||
====Determining full file path of the existing screen's screen definitions file==== | ====Determining full file path of the existing screen's screen definitions file==== | ||
* The line that describes the exact Task, or more likely the Elements who are one or two steps higher in the hierarchy (=one or two steps less indented), will contain the text 'Namespace='. It is followed by a text that ends in '.Setup', e.g. 'Ict.Petra.Client.MPartner.Gui.Setup'. | * The line that describes the exact Task, or more likely the Elements who are one or two steps higher in the hierarchy (=one or two steps less indented), will contain the text 'Namespace='. It is followed by a text that ends in '.Setup', e.g. 'Ict.Petra.Client.MPartner.Gui.Setup'. | ||
* This tells you the last part of the folder where the screen definition file can be found: replace the dots ('.') with backslashes ('\'), | * This tells you the last part of the folder where the screen definition file can be found: replace the dots ('.') with backslashes ('\'), precede this with 'U:\openpetraorg\''NameOfYourFeatureBranch''\csharp\', and add the File Name to get the full file path: '<code>U:\openpetraorg\''NameOfYourFeatureBranch''\csharp\ICT\Petra\Client\MPartner\gui\setup\PartnerTypeSetup.yaml</code>'. | ||
===Copying the screen definitions file=== | ===Copying the screen definitions file=== | ||
* Make a copy of the screen definitions file (whose full file name you just determined) in the same directory. | * Make a copy of the screen definitions file (whose full file name you just determined) in the same directory. | ||
** Should your new Maintain Table screen need to go into a different namespace, choose the appropriate directory (ending in 'gui\setup') and place the copied file there! | ** Should your new Maintain Table screen need to go into a different namespace, choose the appropriate directory (ending in 'gui\setup') and place the copied file there! | ||
*** Example: If your Maintain Table screen should go into the Ict.Petra.Client.MFinance.Gui.Setup namespace, the appropriate directory would be 'Ict\Petra\Client | *** Example: If your Maintain Table screen should go into the Ict.Petra.Client.MFinance.Gui.Setup namespace, the appropriate directory would be 'Ict\Petra\Client\''MFinance\gui\setup''.) | ||
* Name the file according to ''what'' the screen will maintain | * Name the file according to ''what'' the screen will maintain | ||
** Example: if the screen will maintain Partner Types, name the file 'PartnerTypeSetup.yaml' (please use the singular, not the plural form). | ** Example: if the screen will maintain Partner Types, name the file 'PartnerTypeSetup.yaml' (please use the singular, not the plural form). | ||
** The name of the file should end with 'Setup.yaml'. | ** The name of the file should end with 'Setup.yaml'. | ||
==Step 3: Modifying screen definition file to suit the new screen's data and layout== | ==Step 3: Modifying screen definition file to suit the new screen's data and layout== | ||
Each YAML file has two distinct sections: 'Header information' and 'Data Fields and Layout'. | |||
===Header Information=== | |||
The Header Information contains a few Elements. The ones that are particularly important for Maintain Table screens are explained in the following sections. A general overview of all the Elements can be found on page [[Documentation_YAML_for_OpenPetra_Forms]], in the 'Attributes of the root node' section. | |||
====FormTitle Element==== | |||
The value of the 'FormTitle' Element is constructed as follows: take the file name of the YAML file, leave out the 'Setup' string and the '.yaml' extension, change it to plural form, put space characters between the words and prepend the string with 'Maintain '. | |||
Example: | |||
If the screen's YAML file is named 'MaritalStatusSetup.yaml', the 'FormTitle' will be 'Maintain Marital Statuses'. | |||
====DetailTable Element==== | |||
The value of the 'DetailTable Element' is the 'Class Name' of the openPETRA Database Table whose records your Maintain Table screen maintains. It can be constructed from the name of the openPETRA Database Table as follows: capitalise the first character, capitalise the first character after all underscore characters ('_'), and then remove all underscore characters. | |||
Examples: | |||
p_partner becomes <code>PPartner</code>, pt_marital_status becomes <code>PtMaritalStatus</code>. | |||
Technical detail: the Class that you specify with the 'Class Name' represents a 'Typed DataTable', which is a C# object representation of the openPETRA Database Table. | |||
====CacheableTable Element==== | |||
The 'CacheableTable' Element must be present for Maintain Table screens which are based on 'Cacheable DataTables'. For all other screens (be it regular screens or Maintain Table screens which aren't based on 'Cacheable DataTables'), the Element must be omitted. | |||
The value of the 'CacheableTable' Element must be set to the name of the Cacheable DataTable whose records the screen will maintain. You will either been given the correct name, or you should know it because you are a more advanced openPETRA developer. | |||
====Namespace and UsingNamespace Elements==== | |||
The values of the 'Namespace' and 'UsingNamespace' Elements will likely ''not need to be changed'' if the YAML file which was used as a template for the new YAML file was copied within the same directory. | |||
=====Namespace Element===== | |||
The value of the 'Namespace' Element can be constructed by replacing 'xxx' with the name of the openPETRA Module in which the Maintain Table screen needs to go in the following string: 'Ict.Petra.Client.Mxxx.Gui.Setup'. | |||
Example: for the Partner Module, the 'Namespace' Element would be 'Ict.Petra.Client.MPartner.Gui.Setup'. | |||
Technical detail: The 'Namespace' Element specifies the C# Namespace that the generated Maintain Table screen will be placed into. The Generator uses it to put the screen's Class into the C# Namespace in the generated *.cs and *.Designer.cs files. | |||
=====UsingNamespace Element===== | |||
To get the value of the 'UsingNamespace' Element, check the values of 'UsingNamespace' Elements of other YAML files that are found in the directory where your YAML file is placed. | |||
* Find an existing YAML file that references an openPETRA Database Table that is in the same 'area' in the openPETRA DB documentation (the 'area' is denoted by the top-left selection box in the openPETRA DB documentation) than the openPETRA DataBase Table which you specified in the 'DetailTable Element'. | |||
* Copy the value of 'UsingNamespace' over into your YAML file. | |||
* If you can't find an appropriate existing YAML file, or if you are not sure what to put into the 'UsingNamespace' Element, seek help from other openPETRA developers in the [http://apps.sourceforge.net/phpbb/openpetraorg/viewforum.php?f=3 openPETRA Developer Forum]. | |||
Technical detail: The 'UsingNamespace' Element specifies a C# Namespace that needs to be referenced in order to get the definition of the Class that is specified in the 'DetailTable' Element (the Class represents a 'Typed DataTable'). The Generator uses the 'UsingNamespace' Element to put a 'using' clause in the generated *.cs and *.Designer.cs files. | |||
Troubleshooting: Should you later run into compilation errors that mention that a Class that is named like the 'DetailTable' cannot be found, then the 'UsingNamespace' Element is not correct. | |||
===Layout and Data Fields=== | |||
This section of the YAML file is introduced by the Element 'Actions' or 'Controls'. From here onwards, the YAML file specifies the layout, the Controls on the screen and the database columns that they are bound to. | |||
====Layout==== | |||
Most 'Maintain Table' screens follow a ''standardised layout pattern''. Only more complicated Maintain Table screens (who have many or unusual controls or a different user interface concept altogether) should deviate from that layout. The purpose of the standardised layout is to create an easily understood and recognised layout pattern across the application. (A positive side effect is that it also simplifies and speeds up the creation of these screens, as you will see.) | |||
The standardised layout pattern describes the following: | |||
* Main Menu (File, Edit, Help) | |||
* ToolBar (Save and New ToolBarButtons) | |||
* Grid (List) Part | |||
* Details (Bottom) Part | |||
The following sections describe these parts of the user interface. | |||
=====Main Menu===== | |||
The usual MenuItems of Edit Screens (File, Edit and Help along with their sub-MenuItems) are automatically generated, and those are sufficient. ''You don't need to do anything in your YAML file for the Main Menus'' (unless you have a more complicated Maintain Table screens [who have many or unusual controls or a different user interface concept altogether] which may require additional MenuItems). | |||
=====ToolBar===== | |||
The ToolBar contains two ToolBarButtons - 'Save' and 'New xxx'. | |||
* The 'Save' Button lets the user save any changes to the database and is automatically generated, as this an Edit Screen. | |||
* The 'New xxx' Button lets the user create a new data row. This Button needs to be done by you, but there will be already a definition for it in the YAML file since you copied it from another Maintain Table screen, which will have the same Button. | |||
The definition for the ToolBar and the ToolBarButton looks like this: | |||
Toolbar: | |||
tbbNew: | |||
Label: New ''xxx'' | |||
Change the 'xxx' in the text 'New xxx' to reflect ''what'' will be created new - this is the singular form of the FormTitle without the word 'Maintain'. The singular form is used since the user is creating ''one'' new data row, and the FormTitle will be plural because it lets the user see and edit ''many'' data rows. | |||
Example: If the 'FormTitle' is 'Maintain Business Codes', the Label of the tbbNew button should be '<code>Label: New Business Code</code>'. | |||
Technical detail: Since the ToolBarButton is called tbb''New'', the Generator automatically 'wires' it up with the Action act''New''. The result is that if the user presses this ToolBarButton, the Action 'actNew' is executed (which creates a new data row that can be edited in the Details Part). | |||
=====Grid (List) Part===== | |||
The Grid part contains a list of data rows. These are the rows of data that come out of the database table which your particular screen is maintaining. The Grid has several Columns, which display data fields from the database table. | |||
As the database tables have different data fields, the Columns will be different on each Maintain Table screen. You need to specify the data fields that make up the Columns of the Grid of your screen. | |||
Note: next to the Grid part is a Panel with an 'New' Button. ''You don't need to do anything in your YAML file for this Panel, as it is standardised. The 'New' Button is automatically 'wired' up by the Generator.'' | |||
Here is an example that shows how the Grid is defined in the YAML file: | |||
grdDetails: | |||
Dock: Fill | |||
Columns: [DetailCode, DetailDescription, DetailDeletableFlag] | |||
ActionFocusRow: FocusedRowChanged | |||
The only thing that you need to change is the line that starts with '<code>Columns:</code>'. | |||
======Specifying the Columns of the Grid====== | |||
The line in the YAML file that that starts with '<code>Columns:</code>' defines | |||
* which data fields from the database table that your screen is maintaining are displayed in the Grid; | |||
* in which order the data fields are displayed. | |||
In order to identify the names of the data fields from the database table that your screen is maintaining, you need to look at the definition of the database table. | |||
You will find the database table definition in the [[http://openpetraorg.sourceforge.net/dbdoc/ Database Design of OpenPetra.org]]. | |||
* Locate the database table in the list on the left hand side and click on it to show its definition on the right hand side. | |||
** In case you can't see the database table that your screen is maintaining, you will need to change the 'area' of the database that is displayed in the list on the right. Click on one of the 'areas' that is listed in the box on the top left of the page, above the list of database tables, to show a different list of database tables. | |||
* Maintain Table screens usually display all fields of the underlying database table, except the following fields (which are system fields that track which user changed what record, and when): <code> s_date_created_d, s_created_by_c, s_date_modified_d, s_modified_by_c, s_modification_id_c</code>. | |||
* Note down the names of the individual data fields that are remaining. | |||
* Change the name of each data field as follows: | |||
** remove the 'prefix', which is the first letter (or first two letters) followed by an underscore character ('_'); | |||
** remove the 'suffix', which is the last underscore character in the name followed by a letter; | |||
** capitalise the first character, capitalise the first character after all underscore characters ('_'), and then remove all underscore characters. | |||
*** Examples: '<code>p_description_c</code>' becomes 'Description', '<code>p_deletable_l</code>' becomes 'Deletable', '<code>p_method_of_contact_code_c</code>' becomes 'MethodOfContactCode'. | |||
* Prefix the name of the data field with the word 'Detail'. | |||
** Example: 'DetailMethodOfContactCode' | |||
* Most of the times you will want to create Columns for all data fields in the Grid. | |||
** You might choose to not create Columns in the Grid for some of the data fields of the database table which your particular screen is maintaining, especially if this would result in creating more than four or five Columns. | |||
** Which Columns to show, and which ones not, really depends on what you deem to be important information that should be seen in the Grid, and not just the Detail part. | |||
Once you have got the names of the individual data fields and have decided which ones will be displayed in the Columns of the Grid, you can build the 'Columns:' Element as follows: | |||
* within the opening and closing brackets '[' and ']' | |||
** place the names of the data fields | |||
** in the order that they should appear in the Grid | |||
** and separate the names with ', '. | |||
Example: | |||
Columns: [DetailBusinessCode, DetailBusinessDescription, DetailDeletable] | |||
relates to the data columns <code>p_business_code_c</code>, <code>p_business_description_c</code> and <code>p_deletable_l</code> of the <code>p_business</code> database table. | |||
As for the order of the Columns, usually the data fields should be displayed in the order they appear in the database table. An exception to that is the 'deletable' data column, which should always go at the right hand of all the other columns, even if it is in the middle of other columns in the database table definition. | |||
Custom Headings for Columns | |||
The headings of the columns in the Grid are automatically derived from the names of the data fields. This is fine in many cases, but sometimes the name of the data field is 'technical' or doesn't reflect how it is usually named in the GUI. | |||
To change the heading of one or more columns, a '<code>CustomColumns</code>' Element needs to be present, following the '<code>Columns</code>' Element ''at the same indentation level''. After that, one or more column names can be listed on separate lines, indented by one indentation level. The column names are taken from the '<code>Columns</code>' Element and need to be given the '<code>Label</code>' attribute as shown in the following example: | |||
CustomColumns: | |||
DetailCode: {Label=Relationship Category Code} | |||
This renames the automatically derived column heading 'Code' to 'Relationship Category Code'. | |||
Custom Formatting of Data in Columns | |||
The data type of columns in the Grid is '<code>string</code>' by default. To display the content of any column as a different data type, list column names on separate lines as described in the section above, ''Custom Headings for Columns''. Instead (or in addition to) the '<code>Label</code>' Attribute, the Attribute '<code>Type</code>' needs to be used as in the following example: | |||
CustomColumns: | |||
DetailUnassignableDate: {Type=DateTime} | |||
This displays the 'UnassignableDate' column as a date instead of a string. | |||
Other commonly used '<code>Type</code>' values are: '<code>Boolean</code>', '<code>Decimal</code>' and '<code>PartnerKey</code>'. | |||
=====Details (Bottom) Part===== | |||
The Details part consists of a Panel, 'pnlDetails', on which several Controls are placed. Each of these Controls represents a data field of the database table which your particular screen is maintaining. | |||
As the database tables have different data fields, the Controls and the type of Controls (e.g. TextBoxes, CheckBoxes, ...) will be different on each Maintain Table screen. You need to specify the data fields that make up the Controls. These will be at least the data fields that are used for the Columns of the Grid of your screen, but possibly more, if you chose to leave out some Columns in the Grid for the data fields of the database table which your particular screen is maintaining. | |||
The next section describes the process of placing the controls in the Panel and how to influence the arrangement of the Controls on the Panel. | |||
====Data Fields==== | |||
The description of how to add the data fields can be broken down into two aspects: | |||
# overall arrangement and layout | |||
# layout of the individual data fields | |||
=====Overall Arrangement and Layout===== | |||
This is best explained by first showing some example lines of a yaml file: | |||
pnlDetails: | |||
Dock: Bottom | |||
Controls: | |||
Row0: [txtDetailAbilityAreaName, txtDetailAbilityAreaDescr] | |||
Row1: [chkDetailUnassignableFlag, dtpDetailUnassignableDate] | |||
Row2: [chkDetailDeletableFlag] | |||
* '<code>pnlDetails'</code> is the Panel that holds all the Controls below the Grid. | |||
* All the Controls are arranged in invisible rows and columns in an invisible layout table (much like a web page Table in HTML). | |||
** A new Row is started by having an Element '<code>Row''X''</code>' (where ''X'' is a number starting at 0 for row 1) one indentation level deeper than the '<code>Controls</code> Element. | |||
*** Most Maintain Table screens will have three to five Rows. There is a minimum of one Row. | |||
** The '<code>Row''X''</code>' Element is followed by an opening bracket '[', then by a list of Controls separated by commas ',' and is ended with a closing bracket ']' (see 'Row0' and 'Row1' specification in the above example). | |||
*** In case there is only one Control in a Row, no comma must be put after this Control (see 'Row2' specification in the above example) | |||
**** The Control '<code>chkDetailDeletable</code>' (or a Control that is named differently [e.g. '<code>chkDetailDeletableFlag</code>' in the example above]), which is bound to a DB Table column that designates whether a record is deletable by the user, ''should always be put on its own in a separate Row at the end of all the other Rows!'' This is in order to maintain a consistent layout across the many Maintain Table screens. | |||
** Controls which should appear next to each other in a line need to be in the same '<code>Row''X''</code>' Element. | |||
** The invisible layout table is auto-sizing the column widths and row heights, which results in a good automatic layout in many cases. | |||
More information can be found [[https://sourceforge.net/apps/mediawiki/openpetraorg/index.php?title=Screen_scaffolding:_controls#Arranging_Controls here]]. | |||
=====Layout of the Individual Data Fields===== | |||
Follwing the '<code>pnlDetail</code>' Element are the detail definitions of the Controls which were listed in the Row''X'' lines. | |||
This is again best explained by showing some example lines of a yaml file: | |||
txtDetailAbilityAreaName: {Label=Ability Area, CharacterCasing=Upper} | |||
txtDetailAbilityAreaDescr: {Label=Description, Width=250} | |||
chkDetailUnassignableFlag: {Label=Unassignable, OnChange=EnableDisableUnassignableDate} | |||
dtpDetailUnassignableDate: {Label=Unassignable Date, Enabled=false} | |||
chkDetailDeletableFlag: {Label=Deletable} | |||
It is necessary to list all the Controls which are mentioned in one of the Row''X'' lines! If there is a Control where you don't need to specify any Attributes (such as Label or Width) it still needs to be listed in a separate line in the following way: '<code>txtMyText:</code>' | |||
More information about the many layout options can be found [[https://sourceforge.net/apps/mediawiki/openpetraorg/index.php?title=Screen_scaffolding:_controls#Layout_of_Controls here]]. | |||
==Step 4: Generating the screen's source code with the WinForms Generator== | ==Step 4: Generating the screen's source code with the WinForms Generator== | ||
Line 80: | Line 279: | ||
* enter the following commands: | * enter the following commands: | ||
U: <ENTER> | U: <ENTER> | ||
cd \openpetraorg <ENTER> | cd \openpetraorg\''NameOfYourFeatureBranch'' <ENTER> | ||
* after that, verify that the 'nant' build system is working by entering | * after that, verify that the 'nant' build system is working by entering | ||
nant help <ENTER> | nant help <ENTER> | ||
* you should see a list of possible commands and their explanations on the screen | * you should see a list of possible commands and their explanations on the screen | ||
** if you get an error message, then the setup of the development environment is not fully completed, or at least not working, on your computer. Refer to [[Setup_of_Development_Environment_for_Windows#NAnt]] for instructions to set nant up correctly. | ** if you get an error message, then the setup of the development environment is not fully completed, or at least not working, on your computer. Refer to [[Setup_of_Development_Environment_for_Windows#NAnt]] for instructions to set nant up correctly. | ||
* enter the following command to go to the directory from which you can execute the WinForms Generator | |||
cd csharp\ICT\Petra\Client | |||
* enter the following command | * enter the following command | ||
nant | nant generateWinform -D:file=MPartner/gui/setup/YourYamlFileSetup.yaml | ||
- potentially replacing 'MPartner' with the name of another openPETRA Module, and replacing 'YourYamlFileSetup.yaml' with the actual name of your new yaml file. | - potentially replacing 'MPartner' with the name of another openPETRA Module, and replacing 'YourYamlFileSetup.yaml' with the actual name of your new yaml file. | ||
* the WinForms Generator will launch and process your new yaml file. | * the WinForms Generator will launch and process your new yaml file. | ||
Line 99: | Line 300: | ||
The generated files now need to be added to the C# Project in which they belong so they can get compiled. | The generated files now need to be added to the C# Project in which they belong so they can get compiled. | ||
Run <code>nant generateProjectFiles</code>, which will add all generated files for your new form to the project file. | |||
===Step 5b: Creation and adding of the *.ManualCode.cs file === | ===Step 5b: Creation and adding of the *.ManualCode.cs file === | ||
Line 124: | Line 309: | ||
** Copy that file (e.g. by using the Context Menu entries 'Copy' and 'Paste') and rename the resulting file (e.g. by using the Context Menu entry 'Rename'): | ** Copy that file (e.g. by using the Context Menu entries 'Copy' and 'Paste') and rename the resulting file (e.g. by using the Context Menu entry 'Rename'): | ||
*** The name of the file should be like the file name of your new yaml file, except that the file extension should be '.ManualCode.cs' instead of '.yaml'. | *** The name of the file should be like the file name of your new yaml file, except that the file extension should be '.ManualCode.cs' instead of '.yaml'. | ||
*** Example: if the new yaml file is called 'LocationTypeSetup.yaml', the new file name should be 'LocationTypeSetup.ManualCode.cs'. | **** Example: if the new yaml file is called 'LocationTypeSetup.yaml', the new file name should be 'LocationTypeSetup.ManualCode.cs'. | ||
*** Be very careful when renaming the file: the first part of the name needs to exactly match the name of the yaml file, and it needs to end 'exactly' in '.ManualCode.cs' - if it is named only slightly different, e.g. because of a spelling mistake or a space character that shouldn't be there, the WinForms Generator will not detect this file, which will lead to problems at compilation time or run time! | *** Be very careful when renaming the file: the first part of the name needs to exactly match the name of the yaml file, and it needs to end 'exactly' in '.ManualCode.cs' - if it is named only slightly different, e.g. because of a spelling mistake or a space character that shouldn't be there, the WinForms Generator will not detect this file, which will lead to problems at compilation time or run time! | ||
* Choose 'OK' to add the new '*.ManualCode.cs' file as a 'dependant item' to your form. | * Choose 'OK' to add the new '*.ManualCode.cs' file as a 'dependant item' to your form. | ||
===Step 5c: Modifying the new '*.ManualCode.cs' file === | ===Step 5c: Modifying the new '*.ManualCode.cs' file === | ||
In case the Maintain Table screen that you were copying from is nearly identical to the new screen that you are now working on, a modification of the '*.ManualCode.cs' file is likely to be unnecessary, '''except''' for replacing ''all occurrences'' of the DB Table Class Name of the existing Maintain Table screen with the DB Table Class Name of the new Maintain Table Screen (the DB Table Class Names are found in the DetailTable Element of the two YAML files!). | |||
However, if there are differences which affect more than the layout and the name of the DB Table Class there might well be the need to modify the '*.ManualCode.cs' file. As screens vary it is difficult to give general advice on what needs to be changed. | |||
Your best option in this case is to look through some other Maintain Table Screen's '*.ManualCode.cs' files to see what is in there and what particular things are addressed in them. Copy code lines or whole Methods which seem relevant to your screen as well and 'translate' those code lines into your situation (e.g. replacing the names of Controls). ''It is important to re-run the Generator after adding new Methods so it can 'wire them up' to the supporting framework of the screen, which ensures that they are actually called at runtime!'' | |||
====Explanation of Commonly Used Methods in the ManualCode.cs File==== | |||
* '<code>RunOnceOnActivationManual</code>' is necessary to prevent the user from changing the value of the Controls such as '<code>chkDetailDeletableFlag</code>'. The WinForms Generator does this automatically if a Control named '<code>chkDetailDeletable</code>' exists, but if the database field is named differently (for example if it ends with the suffix '<code>_flag_l</code>' then the Control would end with the suffix '<code>...Flag</code>'), the Generator cannot find it and therefore not deactivate it automatically. | |||
* '<code>EnableDisableUnassignableDate</code>' is enabling/disabling as well as clearing the content of Controls such as '<code>dtpDetailUnassignableDate</code>' if the user is changing the value of a related CheckBox Control such as '<code>chkDetailUnassignableFlag</code>'. | |||
* '<code>GetDetailDataFromControlsManual</code>': This method is needed ''only'' in case a column in a DB Table has the constraint 'NOT NULL' ''and'' if this column is not put on the Maintain Table screen. Under those circumstances an Exception would be thrown in case the user would try to save changed data using the 'Save' button. The reason for that is that openPETRA wouldn't assign a value to that DB Table column (not even empty string, "") as it is not used in the screen. '<code>GetDetailDataFromControlsManual</code>' gets around this problem by manually assigning an empty string value to such DB Table columns before the changed data is sent to the PetraServer for saving. | |||
If you don't get to where you think you need to get to or get errors at compile time or runtime, seek help from other openPETRA developers by posting your problem in the [http://apps.sourceforge.net/phpbb/openpetraorg/viewforum.php?f=3 Developer Area in the openPETRA Forum]. | |||
===Step 5d: Compile C# Project === | ===Step 5d: Compile C# Project === | ||
Line 136: | Line 331: | ||
** If no errors are shown, you can continue with the next step. | ** If no errors are shown, you can continue with the next step. | ||
** If errors are shown, try to solve them by going again over the list of things that need to be changed in the *.ManualCode.cs file (Step 5c) and by checking for any general C# syntax errors. If you still get errors after getting rid of any errors you were able to fix for yourself, seek help from other openPETRA developers by posting your problem in the [http://apps.sourceforge.net/phpbb/openpetraorg/viewforum.php?f=3 Developer Area in the openPETRA Forum]. | ** If errors are shown, try to solve them by going again over the list of things that need to be changed in the *.ManualCode.cs file (Step 5c) and by checking for any general C# syntax errors. If you still get errors after getting rid of any errors you were able to fix for yourself, seek help from other openPETRA developers by posting your problem in the [http://apps.sourceforge.net/phpbb/openpetraorg/viewforum.php?f=3 Developer Area in the openPETRA Forum]. | ||
==Step 6: Adding the new screen to the openPETRA main menu structure== | ==Step 6: Adding the new screen to the openPETRA main menu structure== | ||
* If you haven't got the following file still open, open it in a text editor (e.g. Notepad, Notepad++): | * If you haven't got the following file still open, open it in a text editor (e.g. Notepad, Notepad++): | ||
U:\openpetraorg\csharp\ICT\Petra\Definitions\UINavigation.yml | U:\openpetraorg\''NameOfYourFeatureBranch''\csharp\ICT\Petra\Definitions\UINavigation.yml | ||
* Decide where your new screen should show up in the Navigation in the openPETRA Main Window: | * Decide where your new screen should show up in the Navigation in the openPETRA Main Window: | ||
** We recommend that you start the openPETRA Client at that stage. | ** We recommend that you start the openPETRA Client at that stage. | ||
Line 159: | Line 355: | ||
*** Example: if your new Maintain Table screen is maintaining 'Location Types', the Class Name is most likely 'TFrmLocationTypeSetup'. | *** Example: if your new Maintain Table screen is maintaining 'Location Types', the Class Name is most likely 'TFrmLocationTypeSetup'. | ||
* Close the openPETRA Client, if you have it open. | * Close the openPETRA Client, if you have it open. | ||
==Step 7: Opening the new screen in openPETRA for the first time :-)== | ==Step 7: Opening the new screen in openPETRA for the first time :-)== | ||
Line 180: | Line 377: | ||
****** If you corrected the Namespace, save the <code>UINavigation.yaml</code> file and restart the openPETRA Client. Check whether the screen opens after this change. | ****** If you corrected the Namespace, save the <code>UINavigation.yaml</code> file and restart the openPETRA Client. Check whether the screen opens after this change. | ||
*** If the screen does not open after your modifications (or the Class Name and the Namespace declarations in the <code>UINavigation.yaml</code> file seem to be right), seek help from other openPETRA developers in the [http://apps.sourceforge.net/phpbb/openpetraorg/viewforum.php?f=3 Developer Forum in the openPETRA Forum]. | *** If the screen does not open after your modifications (or the Class Name and the Namespace declarations in the <code>UINavigation.yaml</code> file seem to be right), seek help from other openPETRA developers in the [http://apps.sourceforge.net/phpbb/openpetraorg/viewforum.php?f=3 Developer Forum in the openPETRA Forum]. | ||
==Step 8: Iterations: adjusting to needs, re-generate screen, re-open screen== | ==Step 8: Iterations: adjusting to needs, re-generate screen, re-open screen== | ||
Line 204: | Line 402: | ||
*** If the DB table has a flag that is named something like 'Deletable', e.g. 'p_deletable_l' or 'p_type_deletable_l': the CheckBox for the flag should automatically be disabled, and automatically be ticked for new records. This is because a 'set' flag indicates 'System Records' that must not be deleted by the user. On the other hand, user's must not be allowed to create 'System Records'. | *** If the DB table has a flag that is named something like 'Deletable', e.g. 'p_deletable_l' or 'p_type_deletable_l': the CheckBox for the flag should automatically be disabled, and automatically be ticked for new records. This is because a 'set' flag indicates 'System Records' that must not be deleted by the user. On the other hand, user's must not be allowed to create 'System Records'. | ||
**** If the flag is called 'p_deletable_l', the disabling of the CheckBox should happen automatically. Please verify that this is the case. | **** If the flag is called 'p_deletable_l', the disabling of the CheckBox should happen automatically. Please verify that this is the case. | ||
**** If the flag is called something else than 'p_deletable_l', the disabling of the CheckBox needs to be done | **** If the flag is called something else than 'p_deletable_l', the disabling of the CheckBox needs to be done manually: | ||
***** | ***** Add the following Attribute to the Control definition in the yaml file: | ||
Enabled=false | |||
'''or''' | |||
Enabled: false | |||
** Buttons | ** Buttons | ||
*** Check that the 'New' Button and the 'New xxx' ToolBarButton work - they both should create a new record that has a default code. | *** Check that the 'New' Button and the 'New xxx' ToolBarButton work - they both should create a new record that has a default code. | ||
Line 216: | Line 417: | ||
**** 2) closing and re-opening your new Maintain Table screen, | **** 2) closing and re-opening your new Maintain Table screen, | ||
**** 3) checking that the changed/added data is still there. | **** 3) checking that the changed/added data is still there. | ||
***** 4) make sure you check that every Control's data is saved and displayed again correctly! | |||
* If you noticed that something needs to change, go back to the screen's yaml file, make the necessary changes | * If you noticed that something needs to change, go back to the screen's yaml file, make the necessary changes, save the file and run the Generator. Then check whether the changes have the desired effect on the screen in the openPETRA Client. | ||
* If you need help with any necessary changes, seek help from other developers by posting your problem in the [http://apps.sourceforge.net/phpbb/openpetraorg/viewforum.php?f=3 Developer Area of the openPETRA Forum]. Provide as much detail as possible and attach the yaml file of your new Maintain Table screen. | * If you need help with any necessary changes, seek help from other developers by posting your problem in the [http://apps.sourceforge.net/phpbb/openpetraorg/viewforum.php?f=3 Developer Area of the openPETRA Forum]. Provide as much detail as possible and attach the yaml file of your new Maintain Table screen. | ||
* If you are not sure if the layout of the screen follows the standard that most Maintain Table screens follow, make a screenshot of your new screen and seek guidance from other developers by posting your problem in the [http://apps.sourceforge.net/phpbb/openpetraorg/viewforum.php?f=3 Developer Area of the openPETRA Forum]. Attach the screenshot and the yaml file of your new Maintain Table screen. | * If you are not sure if the layout of the screen follows the standard that most Maintain Table screens follow, make a screenshot of your new screen and seek guidance from other developers by posting your problem in the [http://apps.sourceforge.net/phpbb/openpetraorg/viewforum.php?f=3 Developer Area of the openPETRA Forum]. Attach the screenshot and the yaml file of your new Maintain Table screen. | ||
Line 224: | Line 426: | ||
Once you are happy with the appearance of the screen and how it works, you can move on to the next step! | Once you are happy with the appearance of the screen and how it works, you can move on to the next step! | ||
==Step 9: Commit new screen's files to your local | |||
==Step 9: Commit new screen's files to your local Bazaar repository== | |||
TODO | TODO | ||
''You can follow the instructions of 'Option B' only if you have write access to the official openPETRA | ==Step 10: Integration of new screen into official openPETRA Bazaar repository == | ||
There are two options, depending on whether you have or haven't write access to the official openPETRA Bazaar repository. | |||
''You can follow the instructions of 'Option B' only if you have write access to the official openPETRA Bazaar repository.'' If you don't, then you have to follow the instructions of 'Option A'. | |||
===Step 10, Option A: Creating a | ===Step 10, Option A: Creating a Patch and sending the Patch to the openPETRA core development team=== | ||
One option to do this would be using launchpad. Please see [[How_to_commit_to_launchpad]] for further information. | |||
===Step 10, Option B: | ===Step 10, Option B: Committing the new screen's files directly to the openPETRA Bazaar repository=== | ||
TODO | TODO |
Latest revision as of 06:13, 24 August 2012
Overview
A Maintain Table screen allows CRUD (Create, Read, Update, Delete [1]) operations for a specific system table/lookup table of openPETRA.
This tutorial outlines the basic steps that are involved in creating a Maintain Table screen, starting off with an existing Maintain Table screen which is then copied and modified.
Don't get intimidated by fact that are quite a few steps involved - once you have done them several times, you will remember them pretty quickly. (A developer who has already done a few Maintain Table Screens will be able to do a new, simple Maintain Table Screen that is based on an existing Maintain Table Screen in about an hour or less.)
Types of Maintain Table Screens
There are three types of Maintain Table screens:
- Maintain Table screens which are used for editing the values of a 'Cacheable DataTable'.
- A 'Cacheable DataTable' usually contains the data of a single database table which is transferred to the Client once and is saved to a local file which resides at the client computer's harddisk at the first client request of the Cacheable DataTable. These datatables are also held in memory (RAM) for quick access. The Cacheable DataTables are managed by a Cache Manager Class on both the client and server side, which make sure that all Cacheable DataTables of all clients are kept up-to-date and in sync, among other things.
- 'Candiates' for Cacheable DataTables, and therefore for Maintain Table screens which are editing the values of Cacheable DataTables, are database tables that are frequently accessed either by the server or the client or whose contents are frequently displayed, e.g. values of frequently displayed ComboBoxes or Lists.
- This type of Maintain Table screen is the easiest to do and needs the least programming because the Cache Manager Classes encapsulate most of the functionality that is needed. The person who creates such screens does not need know about the client-server architecture of openPETRA, and needs little programming know-how - therefore such Maintain Table screens are ideally suited for people who join the development of openPETRA.
- A 'Cacheable DataTable' usually contains the data of a single database table which is transferred to the Client once and is saved to a local file which resides at the client computer's harddisk at the first client request of the Cacheable DataTable. These datatables are also held in memory (RAM) for quick access. The Cacheable DataTables are managed by a Cache Manager Class on both the client and server side, which make sure that all Cacheable DataTables of all clients are kept up-to-date and in sync, among other things.
- Maintain Table screens which are used for editing the values of a single database table that is not a 'Cacheable DataTable'.
- This type of Maintain Table screen is somewhat more involved than the Maintain Table screens which are editing the values of Cacheable DataTables.
- More programming is needed, since such a screen uses a WebConnector Class for reading and writing of data from/to the database. One WebConnector Class needs to be created for every screen. These Classes aren't hard to do and follow a standard pattern, but in order for creating those Clases, the programmer needs to know more about the client-server architecture of openPETRA and needs to be a more experienced openPETRA programmer.
- Special Maintain Table screens
- which
- edit values of several database tables at once, or
- need to read in the values of several database tables in order to edit one database table, and/or
- don't follow the standard 'list/detail' format of the typical Maintain Table screens, and
- have custom loading/saving routines to update the database.
- are unique within openPETRA and don't resemble each other, so a custom GUI needs to be developed for each screen.
- Those screens' design and logic is usually similar to many Edit screens and therefore no general principle can be given how they are done. (Most likely a more involved WebConnector Class will be needed for such screens; some screens might even be better done with a UIConnector Class.)
- For those reasons, an experienced openPETRA developer needs to do those kind of screens.
- There are not that many Maintain Table screens which fall into this category.
- which
Creating a new Maintain Table screen
The following general instructions can help in creating a simple new Maintain Tables screen based on a similar, existing Maintain Tables screen. (Many Maintain Tables screens are rather simple and similar to existing ones. To start off with a completely new Maintain Tables screen that isn't based on an existing one is obviously more complicated. However, from Step 4 onwards, the same procedures would apply to such new screens as well.)
Step 1: Choosing a similar, existing Maintain Tables screen
- Start openPETRA.
- Using the Navigation Panel, go to the Module (and perhaps Sub-Module) that contains the Area 'Setup' where a Task for a similar screen exists (in the Task List on the right hand side).
- It is advisable to look for a similar screen in the Module where your new screen should end up as well - this makes it easier to copy the screen.
- Open the screen that you think is similar and check that it indeed is similar to the screen that you are about to do.
- Check for
- the overall appearance of the screen,
- that there is a similar number of data fields in the columns of the grid and
- that there is a similar number of data fields in the details section below the grid.
- Should one or two columns in the grid or one or two data fields in the details section be different, this screen is still suitable for a 'similar screen' that we can start off with.
- Check for
Step 2: Copying existing screen definition file to new screen
Overview
All Maintain Table screens are based on a 'screen definition file', which is passed to a Generator. The Generator generates the C# source code and the Resource File (contains e.g. Icons) which form the actual screen in openPETRA.
openPETRA's Screen Definition Files are plain text files which are structured in the [YAML] syntax.
By copying the screen definition file of the existing screen, we will get an exact copy of the layout and data of the existing screen - in a new file. This will be our starting point for the changes we need to make to change the data and layout into 'our' new Maintain Table screen.
Locating existing screen's screen definition file
- Recall what Module, Sub-Module and Area you chose, and which Task you chose from the Task List to bring up the existing, similar Maintain Table screen.
- Open the following file in a text editor (e.g. Notepad, Notepad++)
U:\openpetraorg\NameOfYourFeatureBranch\csharp\ICT\Petra\Definitions\UINavigation.yml
- NameOfYourFeatureBranch is the name of the Feature Branch on which you are currently working. There will be one Feature Branch for each new Maintain Table Screen (or one Feature Branch for several Maintain Table screens if you are doing a batch of new Maintain Table screens). (Your mentor will have created that Feature Branch for you and you will need to have it checked out already.)
- This file contains a structure that is used for builing the Navigation structure which you see in the Main Menu's Navigation Panel of openPETRA.
- Scroll through the file until you find the Module, Sub-Module, Area and Task that describes the Task that you clicked to bring up the existing, similar Maintain Table screen (the hierarchy is created by indentation!).
- The line that describes the exact Task contains the text 'ActionOpenScreen=', followed by text. That text, usually starting with 'TFrm...', is the Class Name of the existing, similar Form.
- To find out the File Name of its 'screen definition file', leave out the 'TFrm' and take only the remainder of the text. Example: if the text is 'ActionOpenScreen=TFrmPartnerTypeSetup', the Class Name is 'TFrmPartnerTypeSetup' and the File Name is 'PartnerTypeSetup'.
- append ".yaml" to get the full File Name including File Extension. Example: 'PartnerTypeSetup' becomes 'PartnerTypeSetup.yaml'.
Determining full file path of the existing screen's screen definitions file
- The line that describes the exact Task, or more likely the Elements who are one or two steps higher in the hierarchy (=one or two steps less indented), will contain the text 'Namespace='. It is followed by a text that ends in '.Setup', e.g. 'Ict.Petra.Client.MPartner.Gui.Setup'.
- This tells you the last part of the folder where the screen definition file can be found: replace the dots ('.') with backslashes ('\'), precede this with 'U:\openpetraorg\NameOfYourFeatureBranch\csharp\', and add the File Name to get the full file path: '
U:\openpetraorg\NameOfYourFeatureBranch\csharp\ICT\Petra\Client\MPartner\gui\setup\PartnerTypeSetup.yaml
'.
Copying the screen definitions file
- Make a copy of the screen definitions file (whose full file name you just determined) in the same directory.
- Should your new Maintain Table screen need to go into a different namespace, choose the appropriate directory (ending in 'gui\setup') and place the copied file there!
- Example: If your Maintain Table screen should go into the Ict.Petra.Client.MFinance.Gui.Setup namespace, the appropriate directory would be 'Ict\Petra\Client\MFinance\gui\setup.)
- Should your new Maintain Table screen need to go into a different namespace, choose the appropriate directory (ending in 'gui\setup') and place the copied file there!
- Name the file according to what the screen will maintain
- Example: if the screen will maintain Partner Types, name the file 'PartnerTypeSetup.yaml' (please use the singular, not the plural form).
- The name of the file should end with 'Setup.yaml'.
Step 3: Modifying screen definition file to suit the new screen's data and layout
Each YAML file has two distinct sections: 'Header information' and 'Data Fields and Layout'.
Header Information
The Header Information contains a few Elements. The ones that are particularly important for Maintain Table screens are explained in the following sections. A general overview of all the Elements can be found on page Documentation_YAML_for_OpenPetra_Forms, in the 'Attributes of the root node' section.
FormTitle Element
The value of the 'FormTitle' Element is constructed as follows: take the file name of the YAML file, leave out the 'Setup' string and the '.yaml' extension, change it to plural form, put space characters between the words and prepend the string with 'Maintain '.
Example: If the screen's YAML file is named 'MaritalStatusSetup.yaml', the 'FormTitle' will be 'Maintain Marital Statuses'.
DetailTable Element
The value of the 'DetailTable Element' is the 'Class Name' of the openPETRA Database Table whose records your Maintain Table screen maintains. It can be constructed from the name of the openPETRA Database Table as follows: capitalise the first character, capitalise the first character after all underscore characters ('_'), and then remove all underscore characters.
Examples:
p_partner becomes PPartner
, pt_marital_status becomes PtMaritalStatus
.
Technical detail: the Class that you specify with the 'Class Name' represents a 'Typed DataTable', which is a C# object representation of the openPETRA Database Table.
CacheableTable Element
The 'CacheableTable' Element must be present for Maintain Table screens which are based on 'Cacheable DataTables'. For all other screens (be it regular screens or Maintain Table screens which aren't based on 'Cacheable DataTables'), the Element must be omitted.
The value of the 'CacheableTable' Element must be set to the name of the Cacheable DataTable whose records the screen will maintain. You will either been given the correct name, or you should know it because you are a more advanced openPETRA developer.
Namespace and UsingNamespace Elements
The values of the 'Namespace' and 'UsingNamespace' Elements will likely not need to be changed if the YAML file which was used as a template for the new YAML file was copied within the same directory.
Namespace Element
The value of the 'Namespace' Element can be constructed by replacing 'xxx' with the name of the openPETRA Module in which the Maintain Table screen needs to go in the following string: 'Ict.Petra.Client.Mxxx.Gui.Setup'. Example: for the Partner Module, the 'Namespace' Element would be 'Ict.Petra.Client.MPartner.Gui.Setup'.
Technical detail: The 'Namespace' Element specifies the C# Namespace that the generated Maintain Table screen will be placed into. The Generator uses it to put the screen's Class into the C# Namespace in the generated *.cs and *.Designer.cs files.
UsingNamespace Element
To get the value of the 'UsingNamespace' Element, check the values of 'UsingNamespace' Elements of other YAML files that are found in the directory where your YAML file is placed.
- Find an existing YAML file that references an openPETRA Database Table that is in the same 'area' in the openPETRA DB documentation (the 'area' is denoted by the top-left selection box in the openPETRA DB documentation) than the openPETRA DataBase Table which you specified in the 'DetailTable Element'.
- Copy the value of 'UsingNamespace' over into your YAML file.
- If you can't find an appropriate existing YAML file, or if you are not sure what to put into the 'UsingNamespace' Element, seek help from other openPETRA developers in the openPETRA Developer Forum.
Technical detail: The 'UsingNamespace' Element specifies a C# Namespace that needs to be referenced in order to get the definition of the Class that is specified in the 'DetailTable' Element (the Class represents a 'Typed DataTable'). The Generator uses the 'UsingNamespace' Element to put a 'using' clause in the generated *.cs and *.Designer.cs files.
Troubleshooting: Should you later run into compilation errors that mention that a Class that is named like the 'DetailTable' cannot be found, then the 'UsingNamespace' Element is not correct.
Layout and Data Fields
This section of the YAML file is introduced by the Element 'Actions' or 'Controls'. From here onwards, the YAML file specifies the layout, the Controls on the screen and the database columns that they are bound to.
Layout
Most 'Maintain Table' screens follow a standardised layout pattern. Only more complicated Maintain Table screens (who have many or unusual controls or a different user interface concept altogether) should deviate from that layout. The purpose of the standardised layout is to create an easily understood and recognised layout pattern across the application. (A positive side effect is that it also simplifies and speeds up the creation of these screens, as you will see.)
The standardised layout pattern describes the following:
- Main Menu (File, Edit, Help)
- ToolBar (Save and New ToolBarButtons)
- Grid (List) Part
- Details (Bottom) Part
The following sections describe these parts of the user interface.
Main Menu
The usual MenuItems of Edit Screens (File, Edit and Help along with their sub-MenuItems) are automatically generated, and those are sufficient. You don't need to do anything in your YAML file for the Main Menus (unless you have a more complicated Maintain Table screens [who have many or unusual controls or a different user interface concept altogether] which may require additional MenuItems).
ToolBar
The ToolBar contains two ToolBarButtons - 'Save' and 'New xxx'.
- The 'Save' Button lets the user save any changes to the database and is automatically generated, as this an Edit Screen.
- The 'New xxx' Button lets the user create a new data row. This Button needs to be done by you, but there will be already a definition for it in the YAML file since you copied it from another Maintain Table screen, which will have the same Button.
The definition for the ToolBar and the ToolBarButton looks like this:
Toolbar: tbbNew: Label: New xxx
Change the 'xxx' in the text 'New xxx' to reflect what will be created new - this is the singular form of the FormTitle without the word 'Maintain'. The singular form is used since the user is creating one new data row, and the FormTitle will be plural because it lets the user see and edit many data rows.
Example: If the 'FormTitle' is 'Maintain Business Codes', the Label of the tbbNew button should be 'Label: New Business Code
'.
Technical detail: Since the ToolBarButton is called tbbNew, the Generator automatically 'wires' it up with the Action actNew. The result is that if the user presses this ToolBarButton, the Action 'actNew' is executed (which creates a new data row that can be edited in the Details Part).
Grid (List) Part
The Grid part contains a list of data rows. These are the rows of data that come out of the database table which your particular screen is maintaining. The Grid has several Columns, which display data fields from the database table.
As the database tables have different data fields, the Columns will be different on each Maintain Table screen. You need to specify the data fields that make up the Columns of the Grid of your screen.
Note: next to the Grid part is a Panel with an 'New' Button. You don't need to do anything in your YAML file for this Panel, as it is standardised. The 'New' Button is automatically 'wired' up by the Generator.
Here is an example that shows how the Grid is defined in the YAML file:
grdDetails: Dock: Fill Columns: [DetailCode, DetailDescription, DetailDeletableFlag] ActionFocusRow: FocusedRowChanged
The only thing that you need to change is the line that starts with 'Columns:
'.
Specifying the Columns of the Grid
The line in the YAML file that that starts with 'Columns:
' defines
- which data fields from the database table that your screen is maintaining are displayed in the Grid;
- in which order the data fields are displayed.
In order to identify the names of the data fields from the database table that your screen is maintaining, you need to look at the definition of the database table.
You will find the database table definition in the [Database Design of OpenPetra.org].
- Locate the database table in the list on the left hand side and click on it to show its definition on the right hand side.
- In case you can't see the database table that your screen is maintaining, you will need to change the 'area' of the database that is displayed in the list on the right. Click on one of the 'areas' that is listed in the box on the top left of the page, above the list of database tables, to show a different list of database tables.
- Maintain Table screens usually display all fields of the underlying database table, except the following fields (which are system fields that track which user changed what record, and when):
s_date_created_d, s_created_by_c, s_date_modified_d, s_modified_by_c, s_modification_id_c
. - Note down the names of the individual data fields that are remaining.
- Change the name of each data field as follows:
- remove the 'prefix', which is the first letter (or first two letters) followed by an underscore character ('_');
- remove the 'suffix', which is the last underscore character in the name followed by a letter;
- capitalise the first character, capitalise the first character after all underscore characters ('_'), and then remove all underscore characters.
- Examples: '
p_description_c
' becomes 'Description', 'p_deletable_l
' becomes 'Deletable', 'p_method_of_contact_code_c
' becomes 'MethodOfContactCode'.
- Examples: '
- Prefix the name of the data field with the word 'Detail'.
- Example: 'DetailMethodOfContactCode'
- Most of the times you will want to create Columns for all data fields in the Grid.
- You might choose to not create Columns in the Grid for some of the data fields of the database table which your particular screen is maintaining, especially if this would result in creating more than four or five Columns.
- Which Columns to show, and which ones not, really depends on what you deem to be important information that should be seen in the Grid, and not just the Detail part.
Once you have got the names of the individual data fields and have decided which ones will be displayed in the Columns of the Grid, you can build the 'Columns:' Element as follows:
- within the opening and closing brackets '[' and ']'
- place the names of the data fields
- in the order that they should appear in the Grid
- and separate the names with ', '.
Example:
Columns: [DetailBusinessCode, DetailBusinessDescription, DetailDeletable]
relates to the data columns p_business_code_c
, p_business_description_c
and p_deletable_l
of the p_business
database table.
As for the order of the Columns, usually the data fields should be displayed in the order they appear in the database table. An exception to that is the 'deletable' data column, which should always go at the right hand of all the other columns, even if it is in the middle of other columns in the database table definition.
Custom Headings for Columns
The headings of the columns in the Grid are automatically derived from the names of the data fields. This is fine in many cases, but sometimes the name of the data field is 'technical' or doesn't reflect how it is usually named in the GUI.
To change the heading of one or more columns, a 'CustomColumns
' Element needs to be present, following the 'Columns
' Element at the same indentation level. After that, one or more column names can be listed on separate lines, indented by one indentation level. The column names are taken from the 'Columns
' Element and need to be given the 'Label
' attribute as shown in the following example:
CustomColumns: DetailCode: {Label=Relationship Category Code}
This renames the automatically derived column heading 'Code' to 'Relationship Category Code'.
Custom Formatting of Data in Columns
The data type of columns in the Grid is 'string
' by default. To display the content of any column as a different data type, list column names on separate lines as described in the section above, Custom Headings for Columns. Instead (or in addition to) the 'Label
' Attribute, the Attribute 'Type
' needs to be used as in the following example:
CustomColumns: DetailUnassignableDate: {Type=DateTime}
This displays the 'UnassignableDate' column as a date instead of a string.
Other commonly used 'Type
' values are: 'Boolean
', 'Decimal
' and 'PartnerKey
'.
Details (Bottom) Part
The Details part consists of a Panel, 'pnlDetails', on which several Controls are placed. Each of these Controls represents a data field of the database table which your particular screen is maintaining.
As the database tables have different data fields, the Controls and the type of Controls (e.g. TextBoxes, CheckBoxes, ...) will be different on each Maintain Table screen. You need to specify the data fields that make up the Controls. These will be at least the data fields that are used for the Columns of the Grid of your screen, but possibly more, if you chose to leave out some Columns in the Grid for the data fields of the database table which your particular screen is maintaining.
The next section describes the process of placing the controls in the Panel and how to influence the arrangement of the Controls on the Panel.
Data Fields
The description of how to add the data fields can be broken down into two aspects:
- overall arrangement and layout
- layout of the individual data fields
Overall Arrangement and Layout
This is best explained by first showing some example lines of a yaml file:
pnlDetails: Dock: Bottom Controls: Row0: [txtDetailAbilityAreaName, txtDetailAbilityAreaDescr] Row1: [chkDetailUnassignableFlag, dtpDetailUnassignableDate] Row2: [chkDetailDeletableFlag]
- '
pnlDetails'
is the Panel that holds all the Controls below the Grid. - All the Controls are arranged in invisible rows and columns in an invisible layout table (much like a web page Table in HTML).
- A new Row is started by having an Element '
RowX
' (where X is a number starting at 0 for row 1) one indentation level deeper than the 'Controls
Element.- Most Maintain Table screens will have three to five Rows. There is a minimum of one Row.
- The '
RowX
' Element is followed by an opening bracket '[', then by a list of Controls separated by commas ',' and is ended with a closing bracket ']' (see 'Row0' and 'Row1' specification in the above example).- In case there is only one Control in a Row, no comma must be put after this Control (see 'Row2' specification in the above example)
- The Control '
chkDetailDeletable
' (or a Control that is named differently [e.g. 'chkDetailDeletableFlag
' in the example above]), which is bound to a DB Table column that designates whether a record is deletable by the user, should always be put on its own in a separate Row at the end of all the other Rows! This is in order to maintain a consistent layout across the many Maintain Table screens.
- The Control '
- In case there is only one Control in a Row, no comma must be put after this Control (see 'Row2' specification in the above example)
- Controls which should appear next to each other in a line need to be in the same '
RowX
' Element. - The invisible layout table is auto-sizing the column widths and row heights, which results in a good automatic layout in many cases.
- A new Row is started by having an Element '
More information can be found [here].
Layout of the Individual Data Fields
Follwing the 'pnlDetail
' Element are the detail definitions of the Controls which were listed in the RowX lines.
This is again best explained by showing some example lines of a yaml file:
txtDetailAbilityAreaName: {Label=Ability Area, CharacterCasing=Upper} txtDetailAbilityAreaDescr: {Label=Description, Width=250} chkDetailUnassignableFlag: {Label=Unassignable, OnChange=EnableDisableUnassignableDate} dtpDetailUnassignableDate: {Label=Unassignable Date, Enabled=false} chkDetailDeletableFlag: {Label=Deletable}
It is necessary to list all the Controls which are mentioned in one of the RowX lines! If there is a Control where you don't need to specify any Attributes (such as Label or Width) it still needs to be listed in a separate line in the following way: 'txtMyText:
'
More information about the many layout options can be found [here].
Step 4: Generating the screen's source code with the WinForms Generator
- Open a Command Prompt (a.k.a. 'DOS Window').
- enter the following commands:
U: <ENTER> cd \openpetraorg\NameOfYourFeatureBranch <ENTER>
- after that, verify that the 'nant' build system is working by entering
nant help <ENTER>
- you should see a list of possible commands and their explanations on the screen
- if you get an error message, then the setup of the development environment is not fully completed, or at least not working, on your computer. Refer to Setup_of_Development_Environment_for_Windows#NAnt for instructions to set nant up correctly.
- enter the following command to go to the directory from which you can execute the WinForms Generator
cd csharp\ICT\Petra\Client
- enter the following command
nant generateWinform -D:file=MPartner/gui/setup/YourYamlFileSetup.yaml
- potentially replacing 'MPartner' with the name of another openPETRA Module, and replacing 'YourYamlFileSetup.yaml' with the actual name of your new yaml file.
- the WinForms Generator will launch and process your new yaml file.
- if the Generator continues to build a C# project and then launches the openPETRA Client, your yaml file doesn't contain any 'bad' errors.
- if the Generator stops and issues an error message: try to find out and fix what is wrong, according to the text of the error message.
- in case the Generator stops with an Exception, check the overall structure of your yaml file for any potential errors, such as: missing or misplaced brackets ('[' and ']') or curly braces ('{' or '}'), wrong indentation, missing colons (':') or missing or superfluous commas (',') or space characters (' ').
- fix what you think is wrong and run the Generator again, until the Generator continues to build a C# project.
- if you are 'stuck', seek help from other developers in the Developer area in the openPETRA Forums.
Step 5: Adding new source code files to corresponding C# Project
Step 5a: Adding the generated files
The generated files now need to be added to the C# Project in which they belong so they can get compiled.
Run nant generateProjectFiles
, which will add all generated files for your new form to the project file.
Step 5b: Creation and adding of the *.ManualCode.cs file
- Right-click on the node that represents your Maintain Table's C# file (this is the one you just expanded) and choose 'Add' -> 'Existing Item as Dependent Item...'.
- In the 'Add existing files' dialog you will make a copy of an existing file before adding it:
- Locate a file that is called like the yaml file of the existing, similar screen that you started off with, except that its file extension is '.ManualCode.cs' instead of '.yaml'.
- Example: if the yaml file of the existing, similar screen is called 'PartnerTypeSetup.yaml', the file that you should copy will be called 'PartnerTypeSetup.ManualCode.cs'.
- Copy that file (e.g. by using the Context Menu entries 'Copy' and 'Paste') and rename the resulting file (e.g. by using the Context Menu entry 'Rename'):
- The name of the file should be like the file name of your new yaml file, except that the file extension should be '.ManualCode.cs' instead of '.yaml'.
- Example: if the new yaml file is called 'LocationTypeSetup.yaml', the new file name should be 'LocationTypeSetup.ManualCode.cs'.
- Be very careful when renaming the file: the first part of the name needs to exactly match the name of the yaml file, and it needs to end 'exactly' in '.ManualCode.cs' - if it is named only slightly different, e.g. because of a spelling mistake or a space character that shouldn't be there, the WinForms Generator will not detect this file, which will lead to problems at compilation time or run time!
- The name of the file should be like the file name of your new yaml file, except that the file extension should be '.ManualCode.cs' instead of '.yaml'.
- Locate a file that is called like the yaml file of the existing, similar screen that you started off with, except that its file extension is '.ManualCode.cs' instead of '.yaml'.
- Choose 'OK' to add the new '*.ManualCode.cs' file as a 'dependant item' to your form.
Step 5c: Modifying the new '*.ManualCode.cs' file
In case the Maintain Table screen that you were copying from is nearly identical to the new screen that you are now working on, a modification of the '*.ManualCode.cs' file is likely to be unnecessary, except for replacing all occurrences of the DB Table Class Name of the existing Maintain Table screen with the DB Table Class Name of the new Maintain Table Screen (the DB Table Class Names are found in the DetailTable Element of the two YAML files!).
However, if there are differences which affect more than the layout and the name of the DB Table Class there might well be the need to modify the '*.ManualCode.cs' file. As screens vary it is difficult to give general advice on what needs to be changed. Your best option in this case is to look through some other Maintain Table Screen's '*.ManualCode.cs' files to see what is in there and what particular things are addressed in them. Copy code lines or whole Methods which seem relevant to your screen as well and 'translate' those code lines into your situation (e.g. replacing the names of Controls). It is important to re-run the Generator after adding new Methods so it can 'wire them up' to the supporting framework of the screen, which ensures that they are actually called at runtime!
Explanation of Commonly Used Methods in the ManualCode.cs File
- '
RunOnceOnActivationManual
' is necessary to prevent the user from changing the value of the Controls such as 'chkDetailDeletableFlag
'. The WinForms Generator does this automatically if a Control named 'chkDetailDeletable
' exists, but if the database field is named differently (for example if it ends with the suffix '_flag_l
' then the Control would end with the suffix '...Flag
'), the Generator cannot find it and therefore not deactivate it automatically. - '
EnableDisableUnassignableDate
' is enabling/disabling as well as clearing the content of Controls such as 'dtpDetailUnassignableDate
' if the user is changing the value of a related CheckBox Control such as 'chkDetailUnassignableFlag
'. - '
GetDetailDataFromControlsManual
': This method is needed only in case a column in a DB Table has the constraint 'NOT NULL' and if this column is not put on the Maintain Table screen. Under those circumstances an Exception would be thrown in case the user would try to save changed data using the 'Save' button. The reason for that is that openPETRA wouldn't assign a value to that DB Table column (not even empty string, "") as it is not used in the screen. 'GetDetailDataFromControlsManual
' gets around this problem by manually assigning an empty string value to such DB Table columns before the changed data is sent to the PetraServer for saving.
If you don't get to where you think you need to get to or get errors at compile time or runtime, seek help from other openPETRA developers by posting your problem in the Developer Area in the openPETRA Forum.
Step 5d: Compile C# Project
- Right-click on the C# Project you are working with and choose 'Build'.
- The IDE will compile any dependent projects and finally the C# Project you are working with.
- If no errors are shown, you can continue with the next step.
- If errors are shown, try to solve them by going again over the list of things that need to be changed in the *.ManualCode.cs file (Step 5c) and by checking for any general C# syntax errors. If you still get errors after getting rid of any errors you were able to fix for yourself, seek help from other openPETRA developers by posting your problem in the Developer Area in the openPETRA Forum.
- If you haven't got the following file still open, open it in a text editor (e.g. Notepad, Notepad++):
U:\openpetraorg\NameOfYourFeatureBranch\csharp\ICT\Petra\Definitions\UINavigation.yml
- Decide where your new screen should show up in the Navigation in the openPETRA Main Window:
- We recommend that you start the openPETRA Client at that stage.
- Have a look at the Module, Sub-Module, Setup Area and Tasks that you might have already in mind. Check what Tasks are already there and decide whether your new screen should be listed among the existing Tasks, or not. If not, keep on looking for a more suitable place in the menu structure, or, if you can't find one, decide on the name of a new Task Grouping in an existing 'Setup Area' that fits best.
- Your new screen should usually be listed among Tasks of a fitting Setup Area. If you think it should not go in a 'Setup Area', it is best to ask in the Developer Area of the openPETRA Forum for guidance.
- We recommend that you start the openPETRA Client at that stage.
- Scroll through the
UINavigation.yml
file until you find the Module, Sub-Module, Area, Task Group where your new screen should be listed. - Choose any existing Task's text line in that Task Group and copy the whole text line.
- Paste the copied text line in the place where you want your new screen to show up.
- In case your screen should be displayed in a new Task Group, create a new Task Group by putting the name of the new Task Group in a separate line *before* the line of your new screen, followed by a colon (':'). Outdent (=the opposite of indent) the line for the new Task Group so that it starts in the same text column as other Task Groups do.
- Modify the pasted text line
- Change the text before the colon (':') so it reflects what your Maintain Table screen is maintaining. Leave out any space characters and capitalise the first letter of every word.
- Example: if your new Maintain Table screen is maintaining 'Location Types', change the text to 'LocationTypes'.
- Change the text that follows 'Label=' to match how other Maintain Screens are showing up in the Task List.
- Example: if your new Maintain Table screen is maintaining 'Location Types', change the text to 'Setup Location Types'.
- Change the text that follows 'Description=' to match how other Maintain Screens are described in the Task List.
- Example: if your new Maintain Table screen is maintaining 'Location Types', change the text to 'Maintain Location Types'.
- Change the text that follows 'ActionOpenScreen' to match the Class Name of your new screen.
- You can find out the Class Name by looking it up in the *.ManualCode.cs file: look for the line that starts with 'public partial class '. The text that follows that declaration is the Class Name of your new screen.
- Example: if your new Maintain Table screen is maintaining 'Location Types', the Class Name is most likely 'TFrmLocationTypeSetup'.
- Change the text before the colon (':') so it reflects what your Maintain Table screen is maintaining. Leave out any space characters and capitalise the first letter of every word.
- Close the openPETRA Client, if you have it open.
Step 7: Opening the new screen in openPETRA for the first time :-)
- Start the openPETRA Client.
- Go to the Module, Sub-Module and Setup Area to which you have added your new screen (in Step 6).
- Ensure that the Task for your new screen is listed, and that is in the Task Group that you want it in.
- If you can't see your new screen listed, check back in the
UINavigation.yaml
file to see where you put the text line that defines the Task for your new screen, and move the text line of your new screen to a text line of the Setup Area and Task Group that you wanted to see it appearing in. Restart the openPETRA Client to see if the change made the difference you wanted. - If you still can't see your new screen listed where you want it to appear, seek help from other openPETRA developers in the Developer Forum in the openPETRA Forum.
- If you can't see your new screen listed, check back in the
- Click on the Task for your new screen.
- Your new Maintain Table screen should open and display a list of entries.
- If the screen opens: congratulations, you have created and added your first Maintain Table screen to openPETRA :-)
- If the screen does not open: check the Status Bar of the Main Window of openPETRA for a message. That message should help you in finding the problem.
- The most likely cause for a screen not opening is that the Class Name and/or the Namespace in the
UINavigation.yaml
file are not correctly specified.- Check the Class Name in the text line that defines your new screen and correct it if it is wrong. If you corrected it, save the
UINavigation.yaml
file and restart openPETRA. Check whether the screen opens after this change. - Check the Namespace.
- The Namespace of a screen is specified by the word 'Namespace=', followed by text that denotes the exact Namespace in which the screen is located.
- Ensure that the text that follows the word 'Namespace=' specifies the namespace of your screen: switch back to the SharpDevelop IDE and bring up the *.ManualCode.cs file. Search for the line that starts with 'namespace '. Check the text that follows and compare it with the text after the word 'Namespace='.
- The word 'Namespace=' will most likely not appear in the text line that defines your new screen, but one or two steps higher in the hierarchy.
- If it appears one or two steps higher in the hierarchy and it fits the namespace declaration of your screen's *.ManualCode.cs file, ensure that there is no 'Namespace=' defined in the text line that defines your new screen.
- If it appears in the text line that defines your new screen, check that it is correct, and whether it is needed there at all - if the word 'Namespace=' appears one or two steps higher in the hierarchy and it fits the namespace declaration of your screen's *.ManualCode.cs file, then you should remove the 'Namespace=' declaration in the text line that defines your new screen because it is superfluous.
- If you corrected the Namespace, save the
UINavigation.yaml
file and restart the openPETRA Client. Check whether the screen opens after this change.
- Check the Class Name in the text line that defines your new screen and correct it if it is wrong. If you corrected it, save the
- The most likely cause for a screen not opening is that the Class Name and/or the Namespace in the
- If the screen does not open after your modifications (or the Class Name and the Namespace declarations in the
UINavigation.yaml
file seem to be right), seek help from other openPETRA developers in the Developer Forum in the openPETRA Forum.
- Your new Maintain Table screen should open and display a list of entries.
Step 8: Iterations: adjusting to needs, re-generate screen, re-open screen
- Once your new Maintain Table screen opens, it is time to check whether it produces the correct result by checking the following:
- Screen
- Check that the screen's title is correct.
- It should follow the format 'Maintain xxx', where 'xxx' is the name that the user knows for the entries of the DB table, in plural.
- Example: if your new Maintain Table screen maintains 'Location Types', the screen's title should read 'Maintain Location Types'.
- It should follow the format 'Maintain xxx', where 'xxx' is the name that the user knows for the entries of the DB table, in plural.
- Check that the size of the screen is appropriate.
- The width of the screen should be so that at least the first four columns are displayed without the need of scrolling to the right.
- The height of the screen should be so that at least 15-20 rows are displayed, or, if there are generally less entries in the DB table, that there isn't too much empty room (no more than for 4-5 lines) at the bottom of the list.
- Check that the screen's title is correct.
- List
- Check that all the columns are displayed that should be displayed.
- Check that all the columns have correct Headings.
- Check that all the columns have the correct display format (e.g. plain text, CheckBox, Date, etc.).
- Details section
- Check that all the Controls are displayed that should be displayed.
- Check that the Labels for all the Controls are correct.
- Check that the layout of the Labels and Controls closely follows the layout of other, similar Maintain Table screens.
- Check that appropriate Controls are used for the purpose: TextBoxes, CheckBoxes, RadioButtons, ComboBoxes, etc.
- For ComboBoxes
- Check that they are populated with the correct data items.
- Check that any label text that might displayed to the right of the CheckBox isn't cut off (you might want to open the ComboBox to select the entry with the longest description for that). (If label text is cut off, you will need to specify the 'ColSpan' Attribute for the ComboBox where this is the case.)
- If the DB table has a flag that is named something like 'Deletable', e.g. 'p_deletable_l' or 'p_type_deletable_l': the CheckBox for the flag should automatically be disabled, and automatically be ticked for new records. This is because a 'set' flag indicates 'System Records' that must not be deleted by the user. On the other hand, user's must not be allowed to create 'System Records'.
- If the flag is called 'p_deletable_l', the disabling of the CheckBox should happen automatically. Please verify that this is the case.
- If the flag is called something else than 'p_deletable_l', the disabling of the CheckBox needs to be done manually:
- Add the following Attribute to the Control definition in the yaml file:
- Screen
Enabled=false or Enabled: false
- Buttons
- Check that the 'New' Button and the 'New xxx' ToolBarButton work - they both should create a new record that has a default code.
- The text of the 'New' Button should always be just 'New', with no further text.
- The text of the 'New xxx' ToolBarButton should should follow the format 'New xxx', where 'xxx' is the name that the user knows for the entries of the DB table, in singular.
- Example: if your new Maintain Table screen maintains 'Location Types', the text of the 'New xxx' ToolBarButton should read 'New Location Type'.
- Check that the 'New' Button and the 'New xxx' ToolBarButton work - they both should create a new record that has a default code.
- Saving of data
- Check that data that has been changed or added can be saved by
- 1) clicking the 'Save' ToolBarButton,
- 2) closing and re-opening your new Maintain Table screen,
- 3) checking that the changed/added data is still there.
- 4) make sure you check that every Control's data is saved and displayed again correctly!
- Check that data that has been changed or added can be saved by
- Buttons
- If you noticed that something needs to change, go back to the screen's yaml file, make the necessary changes, save the file and run the Generator. Then check whether the changes have the desired effect on the screen in the openPETRA Client.
- If you need help with any necessary changes, seek help from other developers by posting your problem in the Developer Area of the openPETRA Forum. Provide as much detail as possible and attach the yaml file of your new Maintain Table screen.
- If you are not sure if the layout of the screen follows the standard that most Maintain Table screens follow, make a screenshot of your new screen and seek guidance from other developers by posting your problem in the Developer Area of the openPETRA Forum. Attach the screenshot and the yaml file of your new Maintain Table screen.
- Repeat the steps above until you are satisfied with the new Maintain Table screen.
Once you are happy with the appearance of the screen and how it works, you can move on to the next step!
Step 9: Commit new screen's files to your local Bazaar repository
TODO
Step 10: Integration of new screen into official openPETRA Bazaar repository
There are two options, depending on whether you have or haven't write access to the official openPETRA Bazaar repository.
You can follow the instructions of 'Option B' only if you have write access to the official openPETRA Bazaar repository. If you don't, then you have to follow the instructions of 'Option A'.
Step 10, Option A: Creating a Patch and sending the Patch to the openPETRA core development team
One option to do this would be using launchpad. Please see How_to_commit_to_launchpad for further information.
Step 10, Option B: Committing the new screen's files directly to the openPETRA Bazaar repository
TODO