User Guide: AVEVA User Documentation 12 Series
User Guide: AVEVA User Documentation 12 Series
User Guide: AVEVA User Documentation 12 Series
.NET Customisation
User Guide
Printable Version
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Introduction
The .NET Customisation User Guide gives software engineers with experience of software development in C#
using Visual Studio guidance on the development of .NET customisation for the AVEVA Plant and AVEVA
Marine products.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 2 of 79
The Common Application Framework (CAF) is an extensible framework which provides the .NET programmer
with access to various services which support both application development and customisation. The foundations
of the CAF are provided by the two interface assemblies:
• Aveva.ApplicationFramework.dll
• Aveva.ApplicationFramework.Presentation.dll
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Database Interfaces
The database related interfaces are provided by the interface assemblies:
• Aveva.Pdms.Database.dll & PDMSFilters.dll
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 3 of 79
• DbPseudoAttribute: This Class allows pseudo attribute code to be plugged in for UDAs.
• DbRule: Class to hold a database rule
• DbUserChanges: This is passed through by the 'database change' event. It contains a list of database changes made since the
last 'database change' event was raised. Changes may be queried down to the attribute level.
• MDB: Methods to do operations on an MDB. e.g. savework, getwork.
• Table: Various classes to access the internal Dabacon tables. E.g. the name table.
• Project: The main method is to open the MDB.
As well as the class methods there is a lot of functionality that can be accessed via pseudo attributes. The
relevant pseudo attributes are listed where relevant.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Geometry Interfaces
The geometry related interfaces are provides by the interface assembly:
• AVEVA.Pdms.Geometry.dll
This interface has a number of geometry related classes. See reference documentation.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Shared Interfaces
Some general shared interfaces are provided in the interface assembly:
• Aveva.Pdms.Shared.dll
This provides current element, selection changed events and Datal listing facilities.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Utilities Interfaces
Utility interfaces are provided in the interface assembly:
• Aveva.Pdms.Ultilities.dll
This provides messaging, string utilities, tracing, undo and units. It also provides access to the command line but
this is not supported
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Graphics Interfaces
Interfaces to access the drawlist and colours are provided in the interface assembly:
• Aveva.Pdms.Graphics.dll
The rest of this user guide will cover in detail how to write a .NET addin and an assembly containing classes with
methods which are callable from PML. It will describe the use of the various .NET interfaces via the use of
sample code.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 4 of 79
Sample Code
A zip file (Samples.zip) containing the samples can be found in the installation directory. For the projects
assembly references to be valid the zip file should be unzipped into the installation directory. It will create a
Samples directory containing the sub-directories described below. If they are moved elsewhere then the
references to assemblies in the installation directory will need to be updated.
Samples are provided which are compatible with Visual Studio 2005, and Visual Studio 2005 Express.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
AttributeBrowserAddin
A zip file (Samples.zip) containing the samples can be found in the installation directory. This example project
creates an addin which implements a very simple database element attribute browser. It also illustrates the
implementation of a command object to control the visibility of the docked window created by the addin.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
ExamplesAddin
A zip file (Samples.zip) containing the samples can be found in the installation directory. .NET API Examples
can be found in the ExamplesAddin project below the Samples directory. This is a C# addin which adds a
ComboBoxTool on a Toolbar to the main menu. Each entry in the list runs a particular example. This can be
loaded by adding the ExamplesAddin to the applications addin config file. Since these examples create and
claim Design elements they need to be run in a Design multi-write database. There is an example config file in
the ExamplesAddin directory.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
NetGridExample
A zip file (Samples.zip) containing the samples can be found in the installation directory. An example of a .NET
C# addin containing an AVEVA Grid Control.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
PMLNetExample
A zip file (Samples.zip) containing the samples can be found in the installation directory. An example of a .NET
class that has been made PML callable.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 5 of 79
PMLGridExample
A zip file (Samples.zip) containing the samples can be found in the installation directory. An example of an
AVEVA Grid Control hosted on a PML form.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Reference Documentation
Reference documentation for the various .NET interfaces is provided in the form of help files which can be found
in the Documentation directory.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
As in all coding situations there is much benefit to be gained by keeping these concepts separate and the code
relating to each one self-contained, or "encapsulated" in object oriented jargon. This keeps the code for each
simple, and offers maximum flexibility.
For example GUI controls can often be shared with other addins and applications. The NetGridControl is a good
example of a control that can be reused in many situations. When this is the case the control code should be
placed in a separate assembly (dll) from the addin and application. At the very least the control code should be
in a separate class (file) from the addin code. Whether shared or not the principles of encapsulation advise
having no application data specific code in the control.
Similarly if the application specific code needs to be active when the GUI itself is not displayed, for example in
teletype (TTY) mode or for batch runs, then it, too, should be in a separate assembly and care will be needed to
ensure it is correctly initialised independently of the addin itself.
Keeping the application code, the GUI control code and the GUI management code separate is good practice
that leads to clearer and more logical code in all areas - much easier to support and maintain in the long term.
Inevitably the addin, the application, the management and the controls need to communicate during operation.
There is a natural hierarchical relationship between them. The following diagram shows the principal lines of
communication between the components of the Addin and between the Addin and the AVEVA host program.
The circles denote the interfaces that each component exposes - its own API (application programmable
interface) and other standard interfaces. The arrows illustrate the natural lines of communication between each
component and the interfaces of the other components.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 6 of 79
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 7 of 79
What distinguishes an addin from any other .NET assembly is that an addin must contain a class which
implements the IAddin interface. When the CAF loads and starts an addin it interrogates the assembly for the
class which implements this interface, creates an instance of this class and calls the IAddin.Start method.
The following code is a simple example of a class which implements the IAddin interface.
This is the AttributeBrowserAddin.cs file which is part of the AttributeBrowserAddin sample project which can be
found in the samples directory. The Start method performs the initialization of the Addin.
using System;
using System.Collections.Generic;
using System.Text;
// Add additional using statements
using Aveva.ApplicationFramework;
using Aveva.ApplicationFramework.Presentation;
namespace Aveva.Presentation.AttributeBrowserAddin
{
public class AttributeBrowserAddin : IAddin
{
#region IAddin Members
#endregion
}
}
Figure 2:2. AttributeBrowserAddin Sample - AttributeBrowserAddin.cs
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 8 of 79
populate it with data unless and until the window is shown. Unnecessary calculations of this kind can add
appreciably to the time taken to start up the PDMS/Marine module giving a poor user experience. Normally a
slight delay at the point where the window in question is first shown goes almost unnoticed by the user and is
therefore much more acceptable.
The principle of delaying calculations until the point where the result is required is known as "lazy evaluation".
Lazy evaluation is useful not only at start up, but can also be used, for example, to limit the extent of calculation
done. The NetGridControl, for example, exploits this to calculate fully only the part of the table which is visible at
any one time, and thereby greatly improving responsiveness for large data sets.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
The WindowManager
Window Creation
An addin will typically expose its functionality to the user through the use of a graphical user interface. This can
take the form of forms which are shown from menu or commandbar buttons or the addin writer may wish the
addins graphical user interface to be hosted inside a dockable window or in an MDI child window. The facilities
provided by the CAF WindowManager can be used to create these two types of window.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 9 of 79
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 10 of 79
Figure 2:4. : Code to create a StatusBar Panel containing the project name.
The StatusBarTextPanel object has a number of properties which control its content and behaviour. It also
supports PanelClick and PanelDoubleClick events. For details of these please refer to the reference help file.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Addin Commands
User access to an Addin's functionality is typically accessed via main menus, context menus and tools on a
commandbar or grouped on a command ribbon. In common with most Windows applications, the CAF provides
an interactive interface via the CommandBarManager for the creation and customisation of menus,
commandbars and ribbon groups and the various types of tool that they can contain. The CAF offers a
mechanism for publishing the capabilities of the Addin to the CommandBarManager for this purpose, namely the
Command object. The Command is a C# class that provides this interface for the CommandBarManager, and
also provides a standard communication channel between the user interface and the Addin for the execution of
the command and the feedback of state such as "enabled", "visible" and "checked". This is therefore a good
mechanism for keeping the requirements of the user interface separate from the definition of the Addin itself.
The code of the Command objects provides part of the formal interface of the "GUI Manager" component of the
Addin as described in The IAddin Interface.
For historical reasons the CAF also support a traditional event style interface where the programmer provides
event handlers to respond to the various events generated as a result of user interaction with the user interface.
However this traditional approach to user interface development although still supported by the CAF is not
recommended. There are known issues with this older approach, not least being an incompatibility with newer
user interface styles such as command ribbons. It should also be noted here that old style tool bars are
themselves not compatible with command ribbons. Thus any Addin that needs to be deployed with older style
menus/command bars as well as newer style command ribbons should avoid the use of free standing tool bars.
When the user interacts with the CommandBarManager to build or customise menus, command bars or ribbon
groups and their tools, the result is stored in a "User Interface Customization" (UIC) file. This is a XML file
containing the definitions of the menus, commandbars and their contents including the values of their various
properties. Details of how to create these UIC files will be covered later in this manual. The UIC file provides the
link between the user interface and the Command objects for the Addin. The UIC definition is loaded at start-up
and the links to the Addin Commands are then created using the services of the Command Manager. Selection
of the menu entry or clicking on the button will then cause the associated command to be executed.
One of the advantages of a command based model is that it forces the decoupling of the user interface or
presentation layer from the application logic. The application logic has no direct reference to the presentation
layer entities. If application state needs to be reflected in the user interface then the application modifies the
state of the command. The command knows which user interface entities are associated with it and takes the
necessary steps to ensure that its internal state is reflected in the user interface. This is easily achieved for state
such as "enabled", "visible" or "checked", but becomes complex when dynamic application state needs to be
reflected in user interface entities such as a combo-box.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 11 of 79
Command class.
void Execute() : This method must be overridden to provide the command execution functionality.
Optionally you can specify a collection of arguments to the execute method:
void Execute(ArrayList arguments) : This will automatically use the correct overload of Execute() which
matches the argument types given in the ArrayList. If no match is found then nothing is called. You can use the
support property Executes to obtain a list of valid Execute() overloads and the method FindExecute(ArrayList
arguments, out MethodInfo info) to determine if an argument list matches an overload.
CommandState GetState() : This method is called by the CAF to update the state of the contents of a context
menu. The returned value is a CommandState enumeration for various states of a command. This enumeration
can be treated as a bit field; that is, a set of flags. Bit fields can be combined using a bitwise OR operation. The
command state is then reflected by the user interface.
String Description : A description for the command.
void Refresh(string context) : This method will be called whenever the CommandManager.ApplicationContext
property is changed. This gives the command the opportunity to update its Enabled or Visible state in response
to this context change. This command state change would then be reflected in the user interface.
The Command base class also has a number of properties which are use to update the command state following
user interface changes or vice-versa.
bool Checked: If associated with a user interface entity such as a StateButtonTool then this property and the
corresponding state of the user interface entity are kept synchronised.
bool Enabled: Changes to this property are reflected in all associated user interface entities.
ArrayList List: This property allows a command to communicate a list of string values to the user interface. This
can be used when a command is associated with for example a ComboBoxTool.
int SelectedIndex: This property is updated to indicate which item from a list has been selected by the user.
object Value: This property holds the currently value of an associated user interface entity.
bool ValueChanged: Before calling the execute method the CAF sets this property if the value of the user
interface entity has changed. The flag is cleared when execution has finished.
bool Visible: Changes to this property are reflected in all associated user interface entities.
Registering a command with the CAF is done by adding an instance of a command class to the
CommandManagers.Commands collection.
namespace Aveva.Presentation.AttributeBrowserAddin
{
/// <summary>
/// Class to manage the visibility state of the AttributeBrowser docked window
/// This command should be associated with a StateButtonTool.
/// </summary>
public class ShowAttributeBrowserCommand : Command
{
private DockedWindow _window;
/// <summary>
/// Constructor for ShowAttributeBrowserCommand
/// </summary>
/// <param name="window">The docked window whose visibility state will be managed.</param>
public ShowAttributeBrowserCommand(DockedWindow window)
{
// Set the command key
this.Key = "Aveva.ShowAttributeBrowserCommand";
// Save the docked window
_window = window;
// Create an event handler for the window closed event
_window.Closed += new EventHandler(_window_Closed);
// Create an event handler for the WindowLayoutLoaded event
WindowManager.Instance.WindowLayoutLoaded += new EventHandler(Instance_WindowLayoutLoaded);
}
void Instance_WindowLayoutLoaded(object sender, EventArgs e)
{
// Update the command state to match initial window visibility
this.Checked = _window.Visible;
}
void _window_Closed(object sender, EventArgs e)
{
// Update the command state when the window is closed
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 12 of 79
this.Checked = false;
}
/// <summary>
/// Override the base class Execute method to show and hide the window
/// </summary>
public override void Execute()
{
if (this.Checked)
{
_window.Show();
}
else
{
_window.Hide();
}
}
}
}
Figure 2:5. AttributeBrowserAddin Sample - ShowAttributeBrowserCommand.cs
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Command Events
The Command base class provides two events BeforeCommandExecute and CommandExecuted which enable the
addin writer to write code to respond to the execution of any command object registered with the
CommandManager. A command object can be retrieved from the CommandManger if its Key is known and
event handlers can be attached to these events.
Command anotherCommand = commandManager.Commands["KeyOfCommand"];
anotherCommand.BeforeCommandExecute += new
System.ComponentModel.CancelEventHandler(anotherCommand_BeforeCommandExecute);
anotherCommand.CommandExecuted += new EventHandler
(anotherCommand_CommandExecuted);
The BeforeCommandExecute event handler is of type CancelEventHandler and is passed a
CancelEventArgs object which enables the command execution to be cancelled by setting the
Cancel property to true.
void anotherCommand_BeforeCommandExecute(object sender,
System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
}
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Resource Manager
Another CAF service is the ResourceManager which provides addins with a simplified mechanism to access
localizable resources. The ResourceManager supports the loading of ResourceSets which consist of a number
of locale specific resource files with a given "basename".
resourceManager.LoadResourceFile("AttributeBrowserAddin");
This will load all resource files with a basename of "AttributeBrowserAddin". E.g.
AttributeBrowserAddin.resources (Invariant language locale)
AttributeBrowserAddin.de.resources (German locale)
AttributeBrowserAddin.ko-KR.resources (Korean-Korea locale)
Depending on the machine's regional settings resource lookups will firstly try to locate the resource from the
corresponding locale specific resource file. If this is not found it will defer to the language invariant resource file.
The ResourceManager provides a number of methods which allow an addin to access the various types of
resources (string, image, cursor, icon etc.) which these resource files may contain. Each of the resource retrieval
methods takes as an argument a resource identifier string and an optional resourceset name. If the resourceset
name is omitted then it will default to a resourceset with the same name as the addin retrieving the resource.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 13 of 79
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Users who build their own controls can also define their own system of events for communication with their
application code. This is a standard part of the C# language, but the syntax is not straight-forward. The following
example illustrates the use of delegates and events.
Code in the control:
/// <summary>Event Handler definition for My Control</summary>
public delegate void MyControlEventHandler(ArrayList args);
/// <summary>After Data Filter is changed</summary>
public event MyControlEventHandler DataFilterChanged;
/// <summary>Another event ...</summary>
public event MyControlEventHandler AnotherEvent;
// ...
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 14 of 79
// ...
And of course it is entirely possible for some or all of the application code to be implemented in PML. For this
purpose the CAF provides an event and call-back mechanism to communicate between C# and PML
applications thus enabling effective encapsulation of behaviour in the code whichever combination of languages
is chosen. Mixed language C#/PML working is covered in PMLNet.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 15 of 79
There are still problems with this however as you will need to catch every "return" statement individually. Also
the Dispose() method will never be called if an exception occurs. A simpler and more robust way is to do this job
using the C# "using" command as follows:
using (TraceEntry tr = TraceEntry.Enter("Start", (TraceNumber)101))
{
// ...
// code being traced ...
// ...
} // implicit call to Dispose() on exit from the block
// even if there are exceptions or multiple return statements
If you are using these facilities to investigate the start-up of an addin, you will need to set the chosen trace flag
from your code:
PdmsTrace.SetTraceFlag((TraceNumber)101, 1);
And, finally, you can use the PDMS CPU time profiling options in conjunction with TraceEntry by using:
PdmsTrace.StartCPUTrace();
// ...
// code being timed ...
// ...
PdmsTrace.StopCPUTrace(true);
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 16 of 79
- namely PdmsExceptions and PMLNetExceptions. In the situation where the host program is in the process of
executing PML, then the PML first has an opportunity to handle the exception itself. If the PML does not handle
the exception, or if no PML is currently being executed, the host program handles these exceptions by notifying
the user of the exception text and number interactively via MessageBoxes or the CommandLine display as
appropriate. Event loop processing then continues normally.
For all other classes of exception the host event loop has no standard procedure and the outcome is that the
host program terminates untidily. It is therefore very poor programming style to allow general exceptions to
escape from the Addin. A relatively easy way to prevent this is to trap exceptions systematically at every entry
point between the host event loop and the component interfaces - for example in every Command.Execute
function:
/// <summary>
/// Execute
/// </summary>
public override void Execute()
{
try
{
// Do the required function.
DoTheJob();
}
catch (System.Exception ex)
{
// Pass on PdmsExceptions and PMLNetExceptions.
// Handle all others:
// (perhaps by raising a PdmsException).
}
}
This recommendation does not, of course, replace the routine practice of handling exceptions at the appropriate
points within the Addin code when they are anticipated and can be dealt with effectively. It simply provides a
safety net for unanticipated and otherwise unhandled exceptions.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 17 of 79
load a UIC file, and how the UIC file can be edited using the applications interactive user interface customisation
tool. Newer modules (such a Tags) use the new Ribbon commandbar, this is configured in the same way as the
original toolbar (detailed below).
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
The order of the UIC files in this configuration file is significant. They are loaded in order since it is possible for a
UIC file to define a tool which is hosted in a menu or on a commandbar defined in a UIC file already loaded.
A new UIC file can be added to a module simply by adding a new line to the corresponding customisation
configuration file. The actual content of the UIC file will be created using the interactive user interface
customisation tool described below.
As well as adding to the customisation configuration file an addin can also load a UIC file directly using the
AddUICustomisationFile method of the CommandBarManager.
// Load a UIC file for the AttributeBrowser.
CommandBarManager commandBarManager = (CommandBarManager)serviceManager.GetService(typeof
(CommandBarManager));
commandBarManager.AddUICustomizationFile("AttributeBrowser.uic", "AttributeBrowser");
This UIC file will be loaded before those define in the Customisation configuration file, so it must create its own
menu or commandbar to host its tools.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 18 of 79
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 19 of 79
are not defined in the currently active customisation file are displayed with an italic font in grey. Any
customisation file which a user does not have write access to does not appear in the drop-down list, but its
contents are included in the tree and list of tools.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
The Tree
The tree is populated with a representation of the Active Customisation file: CommandBars and their contents:
Menubars and their entries and Context Menus defined in each of the configuration files above and including the
currently selected file. It also contains a list of the currently loaded resource files. The Tree View supports the
following user interactions:
Selecting a Node in the Tree
The property grid (5) is updated with the corresponding object so that its properties can be edited. Only objects
which are defined in the currently active customisation file can have their properties modified. Selecting a node
in the tree which represents an object defined in a non-active file will update the property grid, but it will be
disabled thus preventing modification.
If the selected node represents a CommandBar then a representation of the CommandBar will be displayed in
the Preview Area (1).
If the selected node represents a resource file then the resource editor (7) will be displayed instead of the
property grid.
Drag & Drop within the Tree
The tools owned by a MenuTool or a CommandBar can be re-ordered by dragging the tool to the new desired
position. MenuTools owned by the MenuBar can also be re-ordered using drag and drop.
Node Context Menus
The context menu for the CommandBars Node contains the following operations:
New Command Bar - Creates a new CommandBar with unique default name (CommandBar<N>).
The context menu for a CommandBar node contains the following operations:
Delete - Delete the CommandBar. If the CommandBar contains tools then a confirmation MessageBox is
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 20 of 79
displayed.
The context menu for the MenuBar node contains the following operations:
New Menu - Creates a new MenuTool with a unique default name (Menu<N>).
The context menu for the Context Menus node contains the following operations:
New Menu - Creates a new MenuTool with a unique default name (Menu<N>).
The context menu for a Tool node contains the following operations:
First in group - Marks the tool instance as being the first in a group. It then gets a separator drawn above it.
Delete - Removes the tool instance from the MenuTool or CommandBar.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 21 of 79
Delete - Deletes the currently selected tool. If the selected tool is not editable then the delete operation is
disabled. If the tool has been used then a warning message is displayed to confirm that the delete should be
carried out.
Creates a new tool of the required type with a unique default name (Tool<N>) and adds it to the list.
Tool Types
When placed on a CommandBar the Button tool can have either an icon or a text caption. In a menu both the
caption and the icon, if one is defined are displayed. The button tool simply executes the associated command
when clicked.
The ComboBox tool allows selection from a list of items. The associated command provides the list via its List
property.
The ControlContainer supports the hosting of any WinForms control. Here it is shown hosting a ProgressBar.
The control it should host is set via the Control property which presents a list of the controls registered with the
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 22 of 79
The FontList tool allows selection of a font from a pulldown list of installed fonts.
The Label tool allows the addition of a static icon and/or caption.
The List tool can only be use in a menu and will create a menu entry for each of the items returned from the List
property of the associated Command object. This is typically used to implement a MRU list of files.
The MdiWindowList tool can also only be added to a menu. It supports the standard operations on the
applications MDI Windows.
Menu tools can be added to both an existing menu to create a sub-menu or to a CommandBar.
The PopupControlContainer tool allows any WinForms control to be hosted in a popup window. Here the
MonthCalendar control is being hosted.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 23 of 79
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Property Grid
The property grid allows editing the various properties of the tools and CommandBars. The tree view (3) or the
list of command (4) is kept up to date with any property changes.
By default the command type is set to Macro. The uses a special command class to invoke the entered single
PML command. This enables the PML developer to use the interactive customisation tool to create their own
menus and commandbars without needing to write C# command classes.
Changing the command type to "Core Command" will change the dialog to:
Here a list of the currently loaded CAF Command objects is displayed for selection.
Command Tool Properties
The following properties can be set for all Command Tools:
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 24 of 79
• ApplicationContext
• Currently unused
• Arguments
• List of arguments supplied to the Command
• Caption
• Text to display on CommandBar
• Command
• Command to run (see above)
• DisplayStyle
• Determines how the tool is displayed on the CommandBar
• Default- The tool is displayed in a default style.
• DefaultForToolType - The tool is displayed based on the default for the tools type and its location.
• TextOnlyAlways - The tool is always displayed as text only.
• TextOnlyInMenus - The Tool is displayed as a graphic when located on a Toolbar, and displayed as text when located on a
Menu.
• ImageAndText - The tool is displayed using its assigned image and text. This setting is ignored when the item is on a top-
level menu.
• ImageOnlyOnToolbars - The Tool is displayed as a graphic when located on a Toolbar, and displayed as image and text
when located on a Menu.
• Icon
• Icon to display on CommandBar
• KeyTip
• Tip is shown on the ribbon when the Alt key is pressed, aids quick navigation
• Name
• Unique name for this tool
• Shortcut
• Shortcut key to activate this tool
• Tooltip
• Plain tool-tip text to display on mouse-over
• TooltipFormattedText
• Formatted tool-tip text to display on mouse-over
• TooltipTitle
• Title for tool-tip
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Action Buttons
The customisation dialog has the following action buttons:
OK - Saves any modified customisation files and updates the application user interface with any changes and
closes the customisation dialog.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 25 of 79
Cancel - Restores the application user interface to state defined by customisation files if any changes have been
applied and closes the customisation dialog.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Resource Editor
The resource editor enables each of the currently loaded resource sets to be edited. It supports String, Icon and
Bitmap resources. Each resource set can comprise of a number of resource files, comprising of the "Invariant
Language" resource file and any number of locale specific resource files.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 26 of 79
Paste a resource.
Delete a resource.
Add a new resource (Icons and Bitmaps only). New bitmaps or icons can be added by drag-and-drop from a
windows explorer. The resource id is generated from the filename capitalised and prefixed with "ID_". If there is
a clash with an exiting resource then the following dialog will request confirmation of replacement.
String resource can be added for modified by editing them in the grid.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 27 of 79
Add a new locale specific resource file to the resource file set.
Choosing a locale from the list of locales will add a new resource file specific for this locale. This can then be
selected for editing.
The caption and icon properties can be set on a tool in the tool list by drag-and-drop from the resource editor
onto the tool.
Standalone Resource Editor
There is a standalone version of the resource editor available to enable resource files to be created and edited.
This program is called "ResourceEditor.exe" and can be found in the installation directory.
When started it will display a file selection dialog to enable you to choose an existing resource file or give the
name of a new one.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Database Interface
The classes fall into the following groups:
1. Data model definition classes
2. Basic database access, query and modification.
3. Filters and iterators
4. Dabacon table access
5. DB, MDB, Project access
6. Events and pseudo attribute plugins
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 28 of 79
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
DbElementType
Overview
There is a single class for all element types.
The purpose of the class is to:
• Instances of the class identify the element type. i.e. methods on other classes take a DbElementType as an argument rather than
a string to denote an Element type. The DbElementType has 'value' semantics for comparison purposes. i.e. comparing of two
DbElementTypes will always return true if they refer to the same type, even if they are different objects.
• Access the metadata associated with element types.
External to PDMS/Marine, the hash value can be used to uniquely identify an Element type. The hash value is a
32 bit integer.
Constructors
In C# a DbElementType object may be obtained in one of three ways:
1. Use the globally defined instances in DbElementTypeInstance. This is the recommended and easiest way to obtain a
DbElementType.
2. The static 'GetElementType' method may be used to return a DbElementType given the Element Type name. This is only needed
for UDETs. The colon must be included as part of the name.
3. There is also a static 'GetElementType' method that may to be used to return a DbElementType given the hash value. This is only
needed where a hash value has been stored outside of PDMS/Marine.
4. Various methods on other classes, such as DbElement will return a list of DbElementTypes.
Methods
The methods allow the Element type metadata to be accessed. E.g.
• Name
• Description
• BaseType (for UDETs)
• List of attributes
• List of UDAs
• Allowed members
• Allowed owners
• Types that may appear above this element type
• Types that may appear below this element type
• Element types that may be referenced from a given attribute on this element type
• Database types in which it occurs
Related ENUMS
DbNounManual- Manual category
DbType - DB type
Related Pseudo Attributes
Pseudo attributes that provide similar information on a particular element instance (i.e. on a DbElement) are:
Attribute Name C# Data Type Description
HLIS DbElementType[] List of all possible types in
owning hierarchy
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 29 of 79
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
DbAttribute
Overview
This is very similar to DbElementType. There is a single class for all attributes.
The purpose of the class is to:
• Access the metadata (i.e. data about data) associated with attributes. E.g. type, name, length
• Identify attributes. i.e. methods on other classes should always take a DbAttribute rather than a string as an argument to denote
the attribute. Any comparison of attribute identity should be done by comparing DbAttribute objects.
The class should not be confused with the attribute value. The actual Attribute value for a particular Element can
only be accessed via the DbElement class. Comparing two DbAttributes just compares whether they identify
the same attribute, the comparison does not look at attribute values in any way.
External to PDMS/Marine, the hash value can be used to uniquely identify an Attribute. The hash value is a 32
bit integer.
Constructors
In C# a DbAttribute object may be obtained in the following ways:
1. Use globally defined instances. Each attribute has a globally declared instance in the DbAttributeInstance class. This is the
standard way of specifying an attribute.
2. Look up the DbAttribute given the attribute name. This is only needed for UDAs, since all other attributes can be obtained from the
global instances. The colon must be included as part of the name.
3. Look up the DbAttribute given the attribute hash value. Generally this is only needed if reading the hash value from an external
system.
4. Various methods on other classes, such as DbElement, will return a list of DbAttributesTypes.
Methods
The methods allow the following metadata to be accessed:
Attribute Type
Units
Name
Description
Category
Size
Allowed Values
Allowed ranges
Is a UDA
Is a pseudo attribute
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 30 of 79
Example:
Find the type of attribute XLEN. We use the global instance of XLEN on the DbAttributeInstance class.
using ATT=Aveva.Pdms.Database.DbAttributeInstance;
DbAttributeType xlenTyp= ATT.XLEN.Type;
Related ENUMS
DbAttributeUnit Type of units, e.g. distance or
- bore or none.
DbAttributeType – Type of attribute. One of
INTEGER = 1,
DOUBLE = 2,
BOOL = 3,
STRING = 4,
ELEMENT = 5,
DIRECTION = 7,
POSITION = 8,
ORIENTATION = 9
DATETIME = 10
DbAttributeQualifier – used to determine what sort of
qualifier an attribute has
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
DbElementTypeInstance
This class contains instances of DbElementType for every element type in PDMS/Marine. These instances may
be used wherever a DbElementType is expected. E.g. if a method MyMethod() takes an DbElementType, then you
could write:
e.g.
MyMethod(Aveva.Pdms.Database.DbElementTypeInstance.EQUIPMENT);
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
DbAttributeInstance
This class contains instances of DbAttribute for every element type in PDMS/Marine. These instances may be
used wherever a DbAttribute is expected. E.g. if a method MyMethod() takes a DbAttribute, you could write:
e.g.
MyMethod(Aveva.Pdms.Database.DbAttributeInstance.XLEN);
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 31 of 79
Element Access
DbElement Basics
Overview
This section describes the DbElement class. The DbElement class is the most widely used class and it covers a
large proportion of the database functionality that will be used in practise.
The methods fall into the following groups:
• Navigation
• Querying of attributes
• Database modifications
• Storage of rules and expressions
• Comparison across sessions
DbElement is a generic object that represents all database elements regardless of their type.
Constructors
An instance of a DbElement may be obtained as follows:
• There is a static GetElement() method with no arguments to return a 'null' DbElement.
• There is a static GetElement() method which returns a DbElement given a name. This name should include the '/'.
• There is a static GetElement() method which returns a DbElement given a ref (two long int array) and type. This is only
needed where a reference has been stored externally to PDMS/Marine.
• There are many methods on various classes which return DbElements
e.g.
DbElement vess1 = DbElement.GetElement("/VESS1");
Identity
The DbElement object encapsulates the identity of the database object. Any comparison of database objects
must be done using DbElements. The DbElement has 'value' semantics for comparison purposes. i.e. comparing
of two DbElements will always return true if they refer to the same element, even if they are different objects.
DbElement instances should be used in all cases where the identity of an element is being passed or stored.
A DbElement can be identified externally to PDMS/Marine by a combination of the ref number AND type. The ref
number is a two long integer, for example: =123/4567.
Element Validity
A DbElement need not represent a 'valid' element. There are a number of reasons why a DbElement might be
invalid:
• The element is in a DB not opened.
• The element has been deleted.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 32 of 79
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Navigation
Basic Navigation
There are basic methods to navigate the primary hierarchy. e.g. consider the following hierarchy:
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 33 of 79
Scanning the database is a very common operation. For this reasons there are additional iterator and filter
classes that ease this task. These are described in the section on Filters/Iterators.
Pseudo Attributes Relating to Element Navigation
Attribute Data Type Qualifier Description
Name
ALLELE DbElement[]) DbElementType All elements in
the MDB of a
particular type
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 34 of 79
In the example there are two secondary nodes S1, S2. S1 holds element A, C, and S2 holds S1,D,G.
For S1,
SMEMB returns A,C
SEXPND returns A,C
For S2,
SMEMB returns S1,D, G
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 35 of 79
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
int, int[]
double, double[]
bool, bool[]
string, string[]
DbElement, DbElement[]
DbElementType,
DbElementType[]
DbAttribute, DbAttribute[]
Position
Direction
Orientation
Expression
Datetime
Note The methods that are called GetAttribute, GetAttributeArray are the 'getattribute' methods that return
DbAttributes. Similarly the GetElement, GetElementArray methods are the 'getattribute' methods that return
DbElements. This is confusing since GetElement is also the name of the method to return a DbElement given a
name. We may change the names of these in the future.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 36 of 79
obtained via the PSATTS attribute. N.B. querying PSATTS can be slow.
The definition of what pseudo attributes take what qualifier is described in the data model reference manual.
The DbQualifier class represents the qualifier. This can hold any type of qualifier, i.e. int, double,string,
DbElementType, Attribute, position, direction, orientation. It can hold multiple qualifier values, although few
current attributes require multiple valued qualifiers. There is a separate method to set the WRT element.
There is a set of query routines that take a qualifier as an extra argument.
e.g. to query the bore of ppoint 1:
DbQualifier qual=new DbQualifier();
qual.Add(1);
double bore=myele.GetDouble(ATT.PPBO, qual);
Getting an Attribute as a Formatted String
If the attribute value is to go onto a form then the value must be formatted correctly. The correct formatting is not
always obvious or available. Therefore there are special methods to return any attribute as a formatted string.
This will format the attribute into the form that would appear at the command line. For example if the attribute is
a position and we are working in finch unit, then something like 'W 39'4.7/16 N 59'0.85/128 U 4'0.31/128'
might be returned.
The method to do this is GetAsString().
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Database Modifications
Overview
The following modifications are allowed:
• Set attribute
• Create element
• Delete element
• Copy element
• Change type
• Move element
The Modification Pipeline
When an element is modified, it is not simply the case of directly updating the database. For example, when
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 37 of 79
It can be seen that making what appears to be a simple modification is actually quite complicated.
In particularly a lot of errors are possible. Errors may be generated by any of the steps 1-2 plus steps 4-8.
If an error occurs the code will raise a PdmsException. The calling code needs to allow for this.
Clarification of some of these errors is as follows:
Check that the attribute value is the right type - i.e. if a text attribute then the new value must be text. E.g.
setting DESC to 99 will raise an error.
Check against any valid values or ranges - This will check the value against any user provided criteria stored
in the dictionary DBs.
Check access control - An error will be raised if the modification is not allowed. An error will also be raised at
this point if the attribute is not valid for the given element.
Check that the DB is open in write - An error will be raised if 'read only'.
Check LOCK flag - An error will be raised if the LOCK flag is true.
Do claim check, and claim if needed (and implicit claim is allowed) - An error will be raised if:
• The DB uses explicit claims and the primary element has not been claimed.
• The primary element is claimed by another user or extract.
Call the legality checking routines to ensure that the modification is valid - These checks are made by the
plugged in application specific code. Thus potentially any error could be raised.
Claiming Elements
If a DB has been set up to be 'implicit' the user will claim elements as needed without having to do explicit
claims.
There are some methods on DbElement to claim/release individual elements or a hierarchy of elements. If
working on a hierarchy of elements, and errors occur, then the system will still do what it can.
There are also methods on the MDB class to claim/release a list of elements. Performance is improved by
claiming or releasing elements in bulk, thus in general the MDB methods should be used rather than the ones on
DbElement.
The granularity of claim is at the level of primary element. This is described in the data management reference
manual.
Pseudo Attributes Relating to Claims
Attribute Name C# Data Type Description
CLMID String Unique system ID of user
claiming element
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 38 of 79
If creating an element below a given element then the position in the list must be given. E.g.
DbElement myNewPipe=myZoneElement.Create(1,NOUN.PIPE);
This creates a new PIPE below 'myZoneElement' as the first member. If the position is beyond the end of the
current members list, it will create it at the end.
An exception will be raised if the required type of element cannot be created at the required point.
There is a boolean method IsCreatable to test if an element of a given type could be created at the required
location.
Deleting element
The method to delete an element is Delete(). e.g.
MyEle.Delete();
All descendants in the primary hierarchy will be deleted. It will not delete elements in any secondary hierarchies.
There is a boolean method IsHierarchyDeleteable to test if an element can be deleted.
Copy
As with Delete, the standard COPY method copies the primary hierarchy. The following points are relevant when
copying:
• Certain attributes are not copied. e.g. NAME.
• For Name attributes, automatic renaming is possible
• The element may be copied to an existing element, or as a new element.
• Cross references within the copied hierarchy are automatically updated to the copied element. References external to the copied
hierarchy are left unchanged.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 39 of 79
myEle1.Copy(myEle2);
myEle1.CreateCopyHierarchyAfter(myEle2,copyoption);
The first example copies 'myEle2' on top of myEle1. The second example copies myEle2 and all its descendants
to a new element after myEle1.
There are methods to:
• Copy a single element to an existing element
• Copy an element and all its descendants to an existing element
• Copy an element and all its descendants to a new element
• Copy common attributes ('CopyLike') between existing elements
There is a separate class DbCopyOption to hold the options when doing a copy. These options are only available
when copying an element and all its descendants.
The element types must match if copying to an existing element.
There is a boolean method IsCopyable to test if an element can be copied.
Moving Element
An element can be moved to a different location in the primary hierarchy. There are methods to:
• Inset before a given element
• Insert after a given element
• Insert into members list at the last position
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 40 of 79
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
There is a DbExpression class to hold an expression. An DbExpression may be obtained in one of the following
ways:
• Use the static method internalParse() that creates a DbExpression from a string. e.g. internalParse("XLEN *
100" )
• Retrieve an expression from a rule
• Retrieve an expression from a catalogue parameter
Having got an DbExpression there are two things that can be done with it:
1. Turn it back into text
2. Evaluate it against a given element
The methods to evaluate an expression against an element are on the DbElement class. There are different
methods depending on the expected result of the expression. The method names start with 'Evaluate'. The
method that returns a double has an argument for the units (distance/bore/none). The result will always be in
millimetres (mm). E.g.
DbExpression expr = DbExpression.Parse("DIAM OF PREV + 2");
double dval;
DbAttributeUnit units = DbAttributeUnit.DIST;
dval = nozz1.EvaluateDouble(expr4, units);
In this case the core system can work out that it is a distance, since DIAM is a distance. Thus although we
specified that it was a distance, it was not strictly needed. Thus if the distance units were inch or finch then the
'+2' would be interpreted as '+2inches'.
However consider:
DbExpression expr = DbExpression.Parse("10");
double dval;
DbAttributeUnit units = DbAttributeUnit.DIST;
dval = nozz1.EvaluateDouble(expr4, units);
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 41 of 79
In this case we do not know if "10" is 10mm or 10 inches. We must tell the system that it is a 'distance' unit. The
system then interrogates the current distance units to return the result. If the current distance units is mm, then
dval will be 10.0. If the current distance units is inch/finch then "10" is interpreted to mean 10 inches and is
hence returned as 254. N.B. if the value is required to be formatted for output, then it must be converted back in
all cases. A method will be added to return values in local units at a later point.
Rules
PDMS/Marine rules consist of an expression and a dynamic/static flag. When constructing a rule, the expression
type is also needed.
There are methods on DbElement to:
• Set a rule for any attribute.
• Get a rule for any attribute
• Evaluate a rule
• Verify that the rule result is up to date
Pseudo Attributes Relating to Rules and Expressions
Attribute Data Type Qualifier Description
Name
NRULEE Int Number of rule
inconsistencies on
element
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 42 of 79
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 43 of 79
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Filters/Iterators
Iterators
The DBElementCollection class can be used to iterate through the database hierarchy. The iterator is created
with a root element and an optional filter. There are then methods to step through the hierarchy and return the
element at the current location.
E.g. to look for all nozzles below a given element
TypeFilter filt = new TypeFilter(DbElementTypeInstance.NOZZLE);
DBElementCollection collection;
collection = new DBElementCollection(ele, filt);
The iterator class has been written to avoid unnecessarily scanning parts of the database that will not match the
filter. e.g. if looking for all boxes then the iterator will not bother to look below pipes.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Filters
There are a variety of ready built filter classes available. The main ones are:
TypeFilter - True for given Element type(s)
AttributeFalseFilter - True if given attribute is false
AttributeTrueFilter - True if given attribute is true
AttributeRefFilter - True if given attribute value matches given DbElement
AndFilter - AND two existing filters
OrFilter - OR two existing filters
BelowFilter - Filter to test if element is below an element for which the given filter is true.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Dabacon Tables
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 44 of 79
John = 321/543
Jonathon = 111/321
…
Thus for a given name, the corresponding element can rapidly be found without having to scan the entire MDB.
The keys in a name table must be unique. Integer and reference tables may contain the same key many times.
e.g. internally a reference table may look like:
….
=123/456 =234/555
=123/456 =222/333
=123/456 =211/999
=123/458 =203/909
In the above table, element =123/456 has appeared in the table three times. This means that three different
elements were all referencing =123/456 for this particular attribute. This is common. e.g. catalogue references
are reference tables, and for these there may be hundreds of elements referencing the same catalogue
component. A further point worth noting with respect to tables:
• Each DB has its own table. The entries in that table are for 'values' in that DB. Thus for the above ftable, =234/555 etc must be in
this DB. However =123/456, =123/458 may be in a different DB. Indeed there may well be further references to =123/458 from
other DBs. Hence to find all references to =123/456 we need to check the tables in each opened DB.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Table Classes
There are C# classes that enable direct access to the Dabacon tables. The classes are defined as follows:
NameTable - for iterating through name tables
RefTable - for iterating through reference tables
IntTable - for iterating through integer tables
These classes work on a single DB. In most cases, we really want to iterate through all DBs in the MDB as if it
was one table. Thus for integer and name tables there are iterator classes that go across the whole MDB as
follows:
MdbNameTable - for iterating through a name table across entire MDB
MdbIntTable - for iterating through an integer table across entire MDB
There is no method for iterating through a reference table since the order of references in a table is not
meaningful.
There are also methods to return all entries for a given key. This is particularly useful for reference tables; these
are methods of the MDB class.
In C# there is a NameTable class. An example of C# code that looks for all names starting with the letter 'B' is as
follows:
string nam1=new string(“/B”);
string nam2=new string(“/C”);
NameTable ntable = new MdbNameTable(db, DBAttribute.NAME, nam1, nam2);
using (ntable)
{
foreach (Element ele in ntable)
{
// Do something here with each element
}
}
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 45 of 79
The error generating code does not actually free the tokens. So typically you will see the number climb as more
tokens are used up and not freed. The messages will be generated until the database is closed.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
MDB Functionality
The MDB class exposes methods that act on the currently opened MDB. This is a singleton class. It contains
methods to
• open/close an MDB
• savework/quitwork
• query claims
• claim/release elements
• extract operations, e.g. flush, refresh, extract claim, extract release, extract drop.
• get opened DBs
• return an element(s) of a given name
• return elements with matching values in name and integer tables (as described in previous section
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
DB Functionality
When an MDB is opened, a DB class instance is created for each opened DB.
The functionality offered by this class falls into the following categories:
• Query the properties of the DB. e.g. number, MULTIWRITE or not
• Returning the world element for that DB
• Session information. e.g. when was the session written and by whom. There is a DbSession object that holds details on a
database session.
• Return the DbElement in the system DB that represents this DB. This DbElement can then be used to query system attributes and
additional pseudo attributes. The additional pseudo attributes available on the DbElement representing the DB are described
below:
Attribute Name Data Type Qualifier Description
ACCEDB string DB access
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 46 of 79
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 47 of 79
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Events
Overview of Events
The database events fall into the following groups;
• General capture of Database changes
• Writing Pseudo attributes for UDAs
• DB/MDB related events
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Overview of C# Mechanism
The generalised mechanism in C# is as follows:
• There is a delegate to define the event signature.
• There is a method to add a delegate to the list of event handlers to be called.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 48 of 79
The event will only be fired if database changes have been made.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
The same UDA may have multiple delegates registered for different element types.
There is a different delegate for each attribute type. E.g. for integer attributes the delegate is:
public delegate double GetDoubleDelegate(DbElement ele, DbAttribute att, int qualifier);
An instance of the delegate containing the method must then be created and registered with PDMS/Marine.
There are separate methods to register the different types of delegates. There are also separate methods to add
a plugger for a particular element type. E.g. the two methods to add a GetDoubleDelegate are:
public static void AddGetDoubleAttribute(DbAttribute att,GetIntDelegate plug)
public static void AddGetDoubleAttribute(DbAttribute att, DbElementType type, GetIntDelegate plug)
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 49 of 79
namespace Aveva.PDMS.Shared.Tests
{
static public void RegisterDelegate()
{
// get uda attribute
DbAttribute uda=DbAttribute.GetDbAttribute(":VOLUME");
Code may be plugged by UDET as well as the base type. The following criteria are used to locate the right
plugged code:
1. If a UDET, look for a delegate plugged by UDET and attribute.
2. Look for a delegate plugged by base type and attribute
3. Look for a delegate plugged by matching attribute only.
e.g. you could add three delegates to calculate :WEIGHT. You could add one that calculates the :WEIGHT on
a :MYELE, one that calculates the :WEIGHT of SCTN and one that calculates WEIGHT for any other element for
which :WEIGHT is valid.
A delegate only needs adding once at start up.
The events do not allow for errors. Thus if the value can not be calculated then the pseudo attribute code should
return a sensible default.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Except for quit, the pre actions are really called post action but with the DB in the pre action state. The pre action
is only called if the action succeeds.
Most of the pre and post actions fall into just two categories:
1. Changes made to the database file itself, but not our view of it (Savework, Flush, Refresh, drop).
2. Changes in our view of the database, but no changes to the database file (Getwork, undo, Redo, quit).
The interested parties are different in the two cases. When changing the database file, the interested parties are
3rd party systems outside of PDMS/Marine. When changing our view of the database it is the current
PDMS/Marine session that needs to reflect the changes. E.g. update the 3D graphics and explorer.
The events raised reflect this split.
The events are:
• CommitPending - This is called to commit any outstanding change to the database. It is called prior to setmark, undo, redo,
Savework, quit, Getwork.
• ClearCache() - This will be called after doing a temporary switch to a different session in a DB, or after doing a Getwork, undo,
redo, quit.
Note ClearCache may be called thousands of times within a single operation. Thus any event handlers must
be fast.
• Pre and Post events for local changes. i.e. changes affecting the current view of the data. These will be Getwork, undo, redo.
• Pre and Post events for changes affecting the data on the DB. These will be Savework, refresh, drop, flush, refresh. These will
pass the list of changes. For 'global' DBs, if the parent extract is at a different location, the flush event will be raised by the child
extract.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 50 of 79
Note In this case the flush could still fail at the parent. Alternatively the daemon needs to raise the flush event.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Units
Real dimensioned quantities may be created or returned as objects of type DbDouble which have a dimension,
DbDoubleDimension, current units, DbDoubleUnits , and a real value which may be presented as a string using
a format object, DbFormat. Standard dimensions and units are defined by the enumerated types DbDimension
and DbUnits returned by DbDoubleDimension and DbDoubleUnits respectively. The DbElement Get/Set
interface supports both undimensioned and dimensioned attributes which may be formatted using the DbFormat
object. The following classes are available in the Aveva.Pdms.Database interface.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
DbDoubleUnits
Represents a standard or compound unit constructed via static constructors. For example, construct a
compound unit from an expression
DbDoubleUnits u1 = DbDoubleUnits.GetUnits("kg.m.s-2");
There is a static method to get all the defined standard and compound units
DbDoubleUnits[] units = DbDoubleUnits.AllUnits();
and properties to get the description, dimension, conversion factor etc. For example, get the dimension of given
units
DbDimension d1 = DbDoubleUnits.GetUnits(DbUnits.MM).Dimension;
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
DbUnits
Enumeration of standard units. For example:
DbUnits.KG
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
DbDoubleDimension
Represents a standard or compound dimension constructed via static constructors. For example, construct a
compound dimension from an expression
DbDoubleDimension d1 = DbDoubleDimension.GetDimension("volt/m");
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 51 of 79
There are properties to get the current units for given dimension, all units for given dimension etc. For example,
get all the units of given dimension
DbDoubleDimension mass = DbDoubleDimension.GetDimension(DbDimension.MASS);
DbDoubleUnits[] massUnits = mass.Units;
DbAttribute also has a property, Dimension, which returns the dimension of given attribute. For example,
DbAttribute ud1 = DbAttribute.GetDbAttribute(":UD1");
DbDoubleDimension dimension = ud1.Dimension;
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
DbDimension
Enumeration of standard dimensions. For example
DbDimension.MASS
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
DbDouble
Represents a real dimensioned quantity which can be constructed from an expression and/or a format or
returned from DbElement. For example, create a DbDouble from a real value
DbDouble d1 = DbDouble.Create(1.0);
DbDouble's may also be used to set dimensioned attributes. For example, setting the HBOR of a branch
DbElement bran = DbElement.GetElement("/100-B-1-B1");
DbDouble hbor = DbDouble.Create("300", fbore)
bran.SetAttribute(DbAttributeInstance.HBOR, hbor);
returning the nearest nominal bore depending on the current BORE units. There are also properties to return the
units, dimension etc. For example, get the units of given DbDouble
DbDouble d1 = DbDouble.Create("2m");
DbDoubleUnits u1 = d1.Units;
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 52 of 79
DbDouble d2 = d1.ConvertUnits(DbDoubleUnits.GetUnits(DbUnits.LB));
DbDouble also implements the expected binary operator overloads '+', '-', '\', '*', '==', '!=', '<', '<=', '>' and '>='
allowing arithmetic operations and comparison of dimensioned quantities. For example, adding 2 quantities of
the same dimension together
d1 = DbDouble.Create("1 kg");
d2 = DbDouble.Create("2.2046 lb");
d3 = d1 + d2;
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Exception Handling
Arithmetic errors or errors constructing DbDouble's will throw a PdmsException containing the error message.
For example, adding 2 quantities of different dimensions together will throw a PdmsException which can be
caught
d1 = DbDouble.Create("1 kg");
d2 = DbDouble.Create("2 mm");
try
{
d3 = d1 + d2;
}
catch (PdmsException ex)
{
}
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
DbFormat
This object allows formatting of DbDouble's as a string having properties to set the dimension, decimal points,
label etc. For example, formatting a temperature
t1 = DbDouble.Create("0 celsius");
DbFormat tempFmt = DbFormat.Create();
tempFmt.Dimension = DbDoubleDimension.GetDimension(DbDimension.TEMP);
tempFmt.Units = DbDoubleUnits.GetUnits(DbUnits.CELSIUS);
tempFmt.DecimalPoints = 1;
tempFmt.Label = "degC";
string tempStr = t1.ToString(tempFmt);
or constructing a DbDouble from a string and given format
DbFormat f1 = DbFormat.Create();
f1.Dimension = DbDoubleDimension.GetDimension(DbDimension.DIST);
f1.Units = DbDoubleUnits.GetUnits(DbUnits.INCH);
DbDouble d1 = DbDouble.Create("1", f1);
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
PMLNet
PMLNet allows you to instantiate and invoke methods on .NET objects from PML proxy objects. PML proxy class
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 53 of 79
definitions are created from .NET class definitions at run time. These proxy classes present the same methods
as the .NET class which are described using custom attributes. Proxy methods are passed arguments of known
types which are marshalled to the corresponding method on to the .NET instance. The PML proxy objects
behave just like any other PML object.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Design Details
PML callable assemblies are loaded by PDMS/Marine using the IMPORT syntax. Assemblies may be defined in
potentially any .NET language, for example managed C++, C# or VB.NET. The PMLNet Engine loads a given
assembly using reflection. The assembly may be located in the %PDMSEXE% directory, a subdirectory below %
PDMSEXE% a mapped drive or on a UNC path. When the assembly is loaded PML class definitions are created
for each PML callable class within the assembly. The PMLNet Engine only loads assemblies which are marked
with the custom attribute PMLNetCallable. Only classes and methods which are marked as PMLNetCallable are
considered. In order to create a valid PML Proxy class definition the .NET class and its methods must adhere to
certain rules. Once an assembly has been loaded instances of PMLNetCallable classes may be created. No
additional code to interface between PML and .NET is necessary. This is provided by the PMLNetEngine.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Using PMLNet
The diagram below shows how PDMS/Marine may be customised using PMLNet. A number of .NET API's are
available which allow access to the current database session, drawlist, geometry and other functionality. Users
are able to write their own managed code which accesses PDMS/Marine via these C# API's. It is not possible to
directly call PML from C#. However there is an event mechanism which allows PML to subscribe to events
raised from C# (these are shown in dashed lines below). Events are also raised when the database changes
and can be subscribed to from C# (also shown in dashed lines). In this example the external C# assemblies
share the same database session as Design i.e. they run in the same process and therefore see the same data.
Limitations
• Only .NET classes which are marked as PMLNetCallable and adhere to certain rules can be called from PML (these rules are
described later)
• Module switching does not persist .NET objects. Core PML objects defined in FORTRAN or C++ are not persisted either.
• Passing other PML system/user objects to .NET e.g. DIRECTION, ORIENTATION, … is not possible. It is possible to pass
database references to .NET either as an array or String. It is also possible to pass an existing instance of a PML Net Proxy
to .NET.
• It is not possible to call directly PML objects from .NET. The only way to call PML from .NET is via events.
• It is not possible to enter 'partial' namespaces as you might in C# and expect them to be concatenated.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 54 of 79
creates an instance of the .NET class netobject. To specify in which assembly this class is defined and resolve
any name clashes the user needs to also specify the namespace in which the .NET class is defined using the
following syntax:
USING NAMESPACE <string>
then all namespaces in the current scope will be searched to find a match. In this example, if 'Aveva.PDMS.
PMLNetExample' is not currently in scope, then the error:
(46,87) PML: Object definition for NETOBJECT could not be found.
will be raised.
Object Names
Object names can consist of any alpha but not numeric characters (this restriction is imposed by PML). They are
treated as case-independent. However, it is no longer necessary to define them in upper case - any mixture of
upper and lower case letters will have the same effect.
Query Methods
The query methods on an object have been enhanced as follows:
(a) Querying an object will show the namespace name as well as the object name:
e.g.
q var !x
< AVEVA.PDMS.NAMESPACE.NETOBJECT>
AVEVA.PDMS.NAMESPACE.NETOBJECT
(b) There is a new query method to list all the methods of an object (including constructors)
Q METH/ODS
e.g.
q meth !x
<AVEVA.PDMS.NAMESPACE.NETOBJECT>AVEVA.PDMS.NAMESPACE.NETOBJECT
NETOBJECT ( )
NETOBJECT (REAL)
ADD (REAL)
REMOVE(REAL)
ASSIGN(AVEVA.PDMS.NAMESPACE.NETOBJECT)
DOSOMETHING(REAL, REAL, REAL)
Note that query methods will not list the methods on objects of type ANY, even though such methods are
available on all objects.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 55 of 79
.methods()
which returns a list of the methods on the object as an array of strings.
e.g.
!arr = !x.methods()
q var !x
returns:
<ARRAY>
[1] <STRING> 'NETOBJECT ( )'
[2] <STRING> 'NETOBJECT (REAL)'
[3] <STRING> 'ADD (REAL)'
[4] <STRING> 'REMOVE(REAL)'
[5] <STRING> 'ASSIGN(AVEVA.PDMS.NAMESPACE.NETOBJECT)'
[6] <STRING> 'DOSOMETHING(REAL, REAL, REAL)'
Importing an assembly
Before an instance of a .NET object can be instantiated the assembly containing the class definition must be
loaded. This is done using the IMPORT syntax as follows
IMPORT <string>
STRING string
BOOLEAN bool
!a = object netobject()
!a.val(1)
!b = !a
!b.val(2)
then
q var !a.val() returns 1
and
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 56 of 79
This class has a default constructor and a single method. Both the constructor and method are marked as
PMLNetCallable along with the class itself.
The assembly itself must also be marked as PMLNetCallable. This is normally done in the AssemblyInfo file as
follows
using Aveva.PDMS.PMLNet;
[assembly: PMLNetCallable()]
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 57 of 79
proxy goes out of scope the destructor destroys the underlying .NET instance.
ToString() Method
The string() method is available on all PML objects. For a .NET Proxy this will call the ToString() method on
the .NET instance. If the ToString() method is overridden on the .NET class then this will be called.
Method Names
PML is case independent, so it is not possible to have MyMethod() and MYMETHOD() in .NET. PML will report
non-unique object/method names.
Double Precision
Doubles are used in PMLNet to store reals and ints so doubles must be used in .NET (integers are not available
in PML)
Events
Events on PMLNet objects may be subscribed to from PML. A PML callback on a particular instance may be
added to an event on another PMLNet instance. Events are defined by a .NET component by associating the
delegate PMLNetEventHandler with the event. This delegate has the signature
__delegate void PMLNetEventHandler(ArrayList __gc *args);
Where args is an array of event arguments of any PMLNet type (see table of valid types). The following code
associates this delegate with an event
[PMLNetCallable()]
public class PMLNetExample
{
[PMLNetCallable()]
public event PMLNetDelegate.PMLNetEventHandler PMLNetExampleEvent;
[PMLNetCallable()]
public PMLNetExample ()
{
}
[PMLNetCallable()]
public void Assign(PMLNetExample that)
{
}
[PMLNetCallable()]
public void RaiseExampleEvent()
{
ArrayList args = new ArrayList();
args.Add("PMLNetExampleEvent ");
args.Add("A");
if (PMLNetExampleEvent!= null)
PMLNetExampleEvent(args);
}
}
This event can then be caught in PML by adding an appropriate callback to the instance raising the event
!n = object pmlnetexample()
!c = object netcallback()
Where
• !n is the PMLNet instance on which the event will be raised
• !c is the instance of a PML object with a method callback() with the appropriate arguments
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 58 of 79
handle(1000,1)
…
endhandle
Any other exception within the loaded assembly itself is caught by the global exception handler inside
PDMS/Marine.
Rules for Calling .NET
Certain rules must be adhered to when defining a .NET class which is PML callable. These are enforced by the
PMLNetEngine when an assembly is imported. They are
• PML callable assemblies must be marked as PMLNetCallable and reside in the %PDMSEXE% directory, subdirectory of the
application or UNC path.
• Only classes may be PML Callable (this excludes Structures, Interfaces, Enums, …).
• A PML callable class must be marked as PMLNetCallable.
• A PML callable method must be marked as PMLNetCallable.
• A PML callable method can only pass valid argument types (see table of types).
• PML callable classes and methods must be public.
• PML callable methods with default arguments cannot be defined.
• PML callable class and method names must be case independent.
• PML callable classes must have an Assign() method.
• PML callable classes must have a public default constructor which is PMLNetCallable.
If these rules are not adhered to then errors are reported to the trace log when the assembly is loaded and a
PML class definition will not be created. If the class definition has not been defined then the following PML error
will result
(46,87) PML: Object definition for XXX could not be found.
Tracing
In order to output trace to a log file and the console window add the following lines to the exe's config file
<system.diagnostics>
<switches>
<add name="PMLNetTraceSwitch" value="4" />
</switches>
</system.diagnostics>
<appSettings>
<add key="PMLNetTraceLog" value="C:\temp\PMLNetTrace.log" />
</appSettings>
This will create the file PMLNetTrace.log in C:\temp and log all the valid class definitions as they are imported.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
.NET Controls
.NET controls can be hosted on a PML form. In order to do this PML provides a container gadget which can host
the control. This container gadget has attributes to set and get its size and position and may be added to any
PML defined form. It has similar behaviour to a Frame gadget in terms of docking, anchoring and positioning
within an owning form. An instance of the .NET control is instantiated from PML. The PML container provides a
method to add an instance of a .NET control to it. The .NET control may raise events which may be handled by
PML. In order to customise the context menus of the .NET control from PML the ability to define a PML menu
which can be shown when the .NET control raises an event is provided.
Creating a Container
A container on a form that can host the .NET control can be created in the following way in the form setup
container .exampleContainer PmlNetControl 'example' dock fill width 30 height 20
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 59 of 79
where the method to call when the event is fired is defined as follows
define method .rightClickGrid(!data is ARRAY)
!this.exampleContainer.popup = !this.examplePopup
!this.exampleContainer.showPopup(!data[0], !data[1])
endmethod
and the menu shown by the method which is added to the container is defined as follows
menu .examplePopup popup
!this.examplePopup.add( 'CALLBACK', 'Add to 3D View',
'!this.addToThreeDView()' )
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Examples
The following examples are available in the Samples directory -
PMLGridExample
Example of a .NET grid hosted on a PML form
PMLNetExample
Example of a PML Callable assembly
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Note That you can only use the AVEVA C# Grid Control on your own Visual Studio form if you have a design
time license for Infragistics.
Note That you can run this C# Addin with PDMS/Marine without having an Infragistics license.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 60 of 79
The example C# code collects all the Equipment items within the current project and lists them inside the grid
along with attribute values for Name, Type, and Owner.
The data in the grid can be selected, sorted and filtered.
Note The following features of the example addin. These features make use of the published Grid Control API
(see the section below entitled "AVEVA Grid Control API").
1. The data in the grid can be exported to a Microsoft Excel file (XLS) by entering a path name in the text box beneath the grid and
by clicking on the "Export to Excel" button.
2. The grid content can be previewed and printed by clicking on the "Print Preview" button.
3. The colour of the first row in the grid can be set either by choosing a colour in the drop down list, or by typing a valid colour into it.
4. The number of selected rows in the grid is written to a read-only text box. Note that this feature makes use of an event on the grid.
(See the section below entitled "Adding an event to the C# Grid Control").
5. Notice that there are two different context menus available on the grid. One is available when equipment items are selected:
And the other menu is available from the header bar at the top of the grid:
Note That these menu options will only become available once you have made some modifications to the
Design.uic file through menu customisation. See below for instructions on how to do this.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 61 of 79
Note that you could also create your own toolbar which contained a menu item to open/close the addin.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
There are two other ways that an instance of the grid can be populated with data:
1. Populate the grid with non-database data
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 62 of 79
The grid can be populated with non-database data from a Microsoft Excel file. The first row of the Microsoft
Excel file will supply the headings for the grid and the other rows will supply the row data.
The following data source is available for this method of working. See the AVEVA Grid Control API below for
further information.
• NetDataSource(String TableName, string PathName)
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
To add the menus you will need to do the following in the Menu Customisation utility:
1. Add a new Context Menu, which has its name property set to: NewAddin.SelectMenu. This name is used by the code to locate the
set of menus to display when the user makes a context menu selection on one or more equipment items in the grid. The C#
method below from the addin class, is the code which loads the menu. The menus which you create in the Menu Customisation
Utility will be stored in the Design.uic file.
contextMenuKey = "NewAddin.HeaderMenu";
if(mCommandBarManager.RootTools.Contains(contextMenuKey))
{
MenuTool menu = (MenuTool)mCommandBarManager.RootTools[contextMenuKey];
mAddinControl.HeaderMenu = menu;
}
}
2. Create a button and set the command to AVEVA.DrawList.Add. When this menu is used in the Addin it will add the selected
equipment item(s) to the 3D view.
3. Assign the button to the context menu named NewAddin.SelectMenu. You can create other menu options (either from existing
commands which have been exposed, or from existing PML methods and functions) in the same way and assign these to the
context menu.
4. Create a second Context menu named NewAddin.HeaderMenu. This name is used by the code to locate the set of menus to
display when the user makes a context menu selection on the header bar in the grid.
5. Create a button and set the command to AVEVA.Grid.ExportToExcel. When this menu is used in the Addin it will export the grid
data to a Microsoft Excel file.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 63 of 79
6. Assign the button to the context menu named NewAddin.HeaderMenu. You can create other menu options in the same way and
assign these to the context menu.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
An array of selected items is passed through to the calling application. See the example C# code snippet below.
The example code shows that the number of selected items is written to a text box.
private void netGridControl1_AfterSelectChange(System.Collections.ArrayLst args)
{
//Print the number of the selected rows in textbox2
if (args == null)
{
return;
}
Hashtable al = new Hashtable();
al = (Hashtable)args[0];
if (al == null)
{
return;
}
this.textBox2.Text = al.Count.ToString();
}
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 64 of 79
Cell data is passed back to the calling application as an array before a change is made in a cell of the grid (This
assumes that the grid is in editable mode or bulk editable mode). The fourth argument of the array (Array[3]) can
be set to false by the calling application in order to disallow the new value of the cell.
Note This event is the opportunity for the calling code to make a synchronising change to any related data
source. In the case where the related data is Dabacon element/attribute data, the BeforeCellUpdate event
should arrange for the Dabacon element/attribute to be modified appropriately. A convenient way to do this is
to use the NetGridControl.DoDabaconCellUpdate(Array) function to perform the modification. Simply pass the
Array to this function as an argument. If the function is unable to perform the modification for any reason the
Array[3] and Array[4] values will be set to indicate the problem.
BeforeRowsDeleted (Array)
• Array[0] the rows to be deleted
• Array[1] is a Boolean. If you set it to "false" then the action is cancelled
• Array[2] is a string. If you set Array[1] to "false" then this value can be set to give the reason why the action has been cancelled.
The message will be displayed in the cell tooltip.
BeforeRowInsert (Array)
• Array[0] is a Boolean. If you set it to "false" then the action is cancelled
• Array[1] is a string. If you set Array[0] to "false" then this value can be set to give the reason why the action has been cancelled.
The message will be displayed in the cell tooltip.
BeforeRowUpdate(Array)
• Array[0] is a Boolean. If you set it to "false" then the action is cancelled
• Array[1] is a string. If you set Array[0] to "false" then this value can be set to give the reason why the action has been cancelled.
The message will be displayed in the cell tooltip.
CellChange
• Array[0] is the tag of the row
• Array[1] is a tag of the column
The position of the mousedown, and an array of selected items is passed through to the calling application when
the context menu is used on the grid.
OnDragDropCopy (Array)
• Array[0] is the row tag of the copied row
• Array[1] is the drop index
• Array[2] is a Boolean. If you set it to "false" then the action is cancelled
• Array[3] is a string. If you set Array[2] to "false" then this value can be set to give the reason why the action has been cancelled.
The message will be displayed in the cell tooltip.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 65 of 79
OnDragDropMove (Array)
• Array[0] is the row tag of the copied row
• Array[1] is the drop index
• Array[2] is a Boolean. If you set it to "false" then the action is cancelled
• Array[3] is a string. If you set Array[2] to "false" then this value can be set to give the reason why the action has been cancelled.
The message will be displayed in the cell tooltip.
PasteKeyPressed (Array)
• Array[0] is a Boolean. If you set it to "false" then the action is cancelled
• Array[1] is a string. If you set Array[0] to "false" then this value can be set to give the reason why the action has been cancelled.
The message will be displayed in the cell tooltip.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Note That you can only use the AVEVA C# Grid Control on your own Visual Studio form if you have a design
time license for Infragistics.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 66 of 79
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 67 of 79
"Nulref" reference
attribute data.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 68 of 79
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 69 of 79
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 70 of 79
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 71 of 79
LEFT or RIGHT
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 72 of 79
string value)
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 73 of 79
Literal All other symbols are displayed as literals; that is, they
appear as themselves.
hh, mm, ss, tt Combination of these three special strings can be used
to define a time mask. hh for hour, mm for minute, ss for
second, and tt for AP/PM. Examples: hh:mm, hh:mm tt,
hh:mm:ss.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
AVEVA My Data
My Data is a .NET addin that allows database elements to be collected together in collections which are
persisted between modules. The API to modify My Data is also available from PML.
My Data assembly can be imported as follows
IMPORT 'MyDataAddin'
handle any
endhandle
USING NAMESPACE 'Aveva.Pdms.Presentation.MyDataAddin'
!!mydata=object pmlmydata()
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
My Data API
The following api is then available on the My Data object.
Name Type Purpose
PMLMyData MyData
constructor
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 74 of 79
given name
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 75 of 79
strings
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Add an Element
!!mydata.addElement('/VESS1')
!!mydata.addElement('/VESS2')
!!mydata.addElement('/PUMP1')
!!mydata.addElement('/PUMP2')
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
!b=object array()
!b[1]='/PUMP1'
!b[2]='/PUMP2'
!!mydata.addElements(!a)
!!mydata.addElements(!b)
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Remove an Element
!!mydata.removeElement('/VESS1')
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 76 of 79
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Add a Collection
!!mydata.addCollection('My collection1')
!!mydata.addCollection('My collection2')
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Remove a Collection
!!mydata.removeCollection('My collection1')
!!mydata.removeCollection('My collection2')
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 77 of 79
!!mydata.addCollection('My collection1')
!!mydata.addCollection('My collection2')
!!mydata.addElementToCollection('/VESS1', 'My collection1')
!!mydata.addElementToCollection('/VESS2', 'My collection2')
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 78 of 79
Rename a Collection
!!mydata.renameCollection('collectionA', 'collectionX')
!!mydata.renameCollection('collectionB', 'collectionY')
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020
.NET Customisation Page 79 of 79
Use the following syntax to return the name of the file selected in the File Browser window.
q var !browser.file()
Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.
file:///C:/Users/leo/AppData/Local/Temp/~hh43DD.htm 7/10/2020