dng

Building a ProcessBook Docking Window with AF UI Controls

Blog Post created by dng Employee on Jun 12, 2015

PI ProcessBook 2014 introduces a new AF Display Builder add-in that provides visualization to the AF hierarchy (see KB01122 for more information). The AF Display Builder allows users to easily explore PI AF elements and attributes as well as create symbols in PI ProcessBook. Recently, I was assisting a customer in building a PI ProcessBook docking window that displays the AF hierarchy. When users double-click on any element, the .pdi file associated with the element will be opened. I figure I will share this application here in case someone is looking to build a docking window for other purposes.

 

Part I of the blog post will show how to add some simple AF UI controls to a docking window in PI ProcessBook, while Part II will show how to modify the controls to open a .pdi file when an element is double-clicked.

 

 

Part I: Building a PI ProcessBook Docking Window with some AF UI Controls

 

Using the PI ProcessBook Add-In Templates

 

We provide VB.NET and C# templates for creating PI ProcessBook 3.x add-ins. These templates are available for download in the Tech Support Download Center. Since we are developing a docking window in C#, after downloading the templates, unzip and place the AddInPBDockWin_CS file in %USERPROFILE%\Documents\Visual Studio 2013\Templates\ProjectTemplates\Visual C# folder.

 

In Visual Studio 2013, create a new project and select the AddInPBDockWin_CS template:

addtemplate.png

 

Investigating the Docking Window Add-In Template

 

Let’s briefly investigate the docking window add-in project that we have just created from the template. For detailed information, please refer to the document “PI ProcesBook AddIn Templates for VS2008.doc” that comes with the template download.

 

Connect.cs

The Connect class contains IDTExtensibility2 methods that all PI ProcessBook add-ins must implement. The two main methods that can be changed are:

  1. OnConnection
    • Specifies the load behavior when PI ProcessBook initializes the add-in.
  2. OnDisconnection
    • Specifies any cleanup needed when PI ProcessBook terminates the add-in.

 

AddinReg.reg

This file contains the registry keys that PI ProcessBook uses to locate and initialize add-ins. While we are here, let’s edit the “FriendlyName” and “Description” field. Also, make sure that the registry path is correct (see the "extra" section below for more information).

addinreg.png

 

Adding References to PI AF SDK and AF UI

 

Let’s add some references so we can access objects from the AF Database. In addition, we will make use of some ready-made controls available from the AF UI so we don’t have to reinvent the wheel.

  • AF SDK (from %pihome%\AF\PublicAssemblies\4.0\OSIsoft.AFSDK.dll)
  • AF UI (from %pihome%\AF\PublicAssemblies\4.0\OSIsoft.AF.UI.dll)

Since we are adding the .NET 4 version of the PI AF SDK and AF UI to the project, please ensure that the project is targeting .NET framework 4.5.

 

 

Adding the AF UI to a .NET User Control

 

We will next add a .NET user control and put some AF UI components in it. (Thanks to Steve Pilon’s post which gave many useful guidelines!)

 

1.     Right-click the PB_DockWin_AFTreeView project and add a user control. We’ll name it AFTreeControl.cs:

     usercontrol.png

 

2.     In the design mode, resize the user control. We will then add 3 AF UI controls:

    • PISystemPicker: to allow user select and connect to an AF server
    • AFDatabasePicker: to allow user select and connect to a database in the AF server selected
    • AFTreeView: to display the AF element hierarchy

 

     For more information about AF UI components, refer to the AF User Interface Library Reference located at %pihome%\help\AFUIRef.chm.

 

     Modify the PISystem picker and AFDatabasePicker to remove unneeded controls. E.g.:

     afPickerProp.png

 

     The resulting user control will look something like this:

     usercontrol2.png

 

3.     Open the code behind the user control and make the user control visible to COM:

 

using System.Runtime.InteropServices;

 

namespace PB_DockWin_AFTreeView
{
    [ComVisible(true)]
    public partial class AFTreeControl : UserControl
    {

 

 

Adding functionality to the AF UI Controls

 

Let’s add code to our user control (AFTreeContol.cs) to allow us to populate the AFTreeView with the element hierarchy when an AF Server and AF Database is selected.

 

To begin, add using directives to the referenced AF SDK and AF UI:

 

using OSIsoft.AF;
using OSIsoft.AF.UI;

 

We would like the AFDatabasePicker (named afDbPicker) to populate the list of databases whenever an AF server is selected from the PISystemPicker (named afPicker) control.

 

// Initialize the AF UI Controls
public AFTreeControl()
{
    InitializeComponent();
    afDbPicker.SystemPicker = afPicker;
}

 

Next, we need populate the AFTreeView when users select/change the AF Database using AFDatabasePicker. We will add code to react to the SelectionChange event:

  • Click on the AFDatabasePickerControl and select Events under the Properties Window.
  • Double-click on SelectionChange:

     eventchange.png

 

Visual Studio will automatically populates code needed to handle this event. Back in the User Controls code, we see that afDbPicker_SectionChange has been added. Add the following code to get the elements to display in the AFTreeView (named afTreeView):

 

// Change the elements in the TreeView to the selected AF system and AF Database
private void afDbPicker_SelectionChange(object sender, SelectionChangeEventArgs e)
{
    afTreeView.AFRoot = null;
    AFDatabase myDatabase = afDbPicker.AFDatabase;
    if (myDatabase != null && myDatabase.Elements != null)
        afTreeView.AFRoot = myDatabase.Elements;
}

 

Now, our control should display the AF element hierarchy after an AF server and database has been selected.

 

 

Displaying the User Control in PI ProcessBook

 

The last step would be to ask the docking window add-in to load our user control.

 

Let’s clean up the default label added as an example in the docking window template:

  • Remove the label control and the associated variable m_strAddInName
  • Change the name of the docking window to “AFTreeView Docking Window”
  • Add our user control (AFTreeControl) to the view in the docking window

 

The edited OnConnection method looks like the following:

 

public void OnConnection(object Application, Extensibility.ext_ConnectMode ConnectMode, object AddInInst, ref System.Array custom)
{
    try
    {
        m_theApp = (PBObjLib.Application)Application;

        #region docking window

        m_dockWindow = m_theApp.DockWindows.Add(PBObjLib.pbDockWindowType.pbTypeSingleViewWindow, "AFTreeView Docking Window", PBObjLib.pbDockPosition.pbDockLeft, false);

        if (m_dockWindow != null)
        {
            m_dockWindow.Visible = true;

            //ensure the tree view is fully visible
            m_dockWindow.Width = 250;

            //create a view in the docking window to contain the control
            PBObjLib.PBControlView ctrlView = (PBObjLib.PBControlView)m_dockWindow.Views.Add(PBObjLib.pbViewType.pbControlViewType);

            AFTreeControl treeControl = (AFTreeControl)ctrlView.CreateControl("PB_DockWin_AFTreeView.AFTreeControl");
        }

        #endregion

    }
    catch (Exception ex)
    {
        MessageBox.Show("Exception in OnConnection=" + ex.Message);
    }
}

 

 

Finally, we are ready to test! Note that the Debug configuration specify the start action as opening PI ProcessBook. Make sure to change the hard-coded path to reflect the actual location of the PI ProcessBook executable on your machine.

debugprop.png

 

Clicking Debug will register the add-in in the registry (remember AddReg.reg?) and launch PI ProcessBook. The docking window should now be loaded automatically!

dockingwin.png

 

 

Part II: Additional Functionality

 

We have successfully added a AFTreeView in a PI ProcessBook docking window! We are ready to add some custom functionality!

 

As I mentioned in the beginning of this blog post, the goal of this application is to open up a .pdi file when user double-click on any element. To do that, we will parse the path of the element by accessing the node that has been double-clicked. If a .pdi file with the same name already exists, the file will be opened; if not, a new file will be opened.

 

To open up a display at a double-click event, the user control needs to know about the PI ProcessBook application.

 

// The processBook application
public PBObjLib.Application app; 

 

We can then set the ProcessBook Application in the OnConnection method during initialization:

 

AFTreeControl treeControl = (AFTreeControl)ctrlView.CreateControl("PB_DockWin_AFTreeView.AFTreeControl");
treeControl.app = m_theApp;

 

(By the way, this is by no means perfect. Please feel free to comment/improve upon this!)

 

 

Let’s add code to react to a NodeMouseDoubleClick event: (make sure to first create an event handler for the event as described above for the SectionChange event for the AFDatabasePicker)

 

using System.IO;

 

// Open a new display when the node is double-clicked
private void afTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
{
     // Parse element path to get the name of the element
    string[] path = e.Node.FullPath.Split('\\');
    string filePath = String.Format("C:\\Dev Support\\VBA in PB\\{0}.pdi", path[path.Length - 1]);

     // If the pdi exists, open the file
    if (File.Exists(filePath))
    {
        app.Displays.Open(filePath, false);
    }
     // If pdi doesn't exist, add a dislpay with the name of the element
    else
    {
        app.Displays.Add(path[path.Length - 1]);
    }
}

 

 

Rebuild the project and test the new functionality in PI ProcessBook!

 

 

Extra: A Few Tips about Deployment

 

Note that PI ProcessBook reads the list of add-ins from the registry at

  • HKLM\SOFTWARE\Wow6432Node\PISystem\PI – ProcessBook\Addins, or
  • HKLM\SOFTWARE\Software\PISystem\PI – ProcessBook\Addins

 

depending on the bitness. It is important to modify the AddinReg.reg file so that the registry keys are added in the correct location.

 

To modify the load/unload behavior, you can open up Add-In Manager in PI ProcessBook (Tools > Add-In Manager) and modify the default loading properties for your add-in:

addinmanager.png

 

Finally, if you have finished development and would like to deploy your add-in on a client machine, please refer to KB00592.

 

 

Conclusion

 

The full project is in the GitHub repository pb-dockwin-aftreeview. Feedback and comments are always welcomed!

Outcomes