11 Replies Latest reply on Aug 18, 2009 9:17 PM by mlemley

    Access to Controls on PB display

    tomster71

      I have tried to access the controls MDBTree and BatchView on a PB display by a PB Add-In.  I am able to get the controls in the PB.Symbols collection but do not know how to cast them the appropriate data type. To demonstrate the problem i submit a sample code (C#/VS2008). The code work for the symbol type pbSymbolTrend but not for pbSymbolControl and pbSymbolBTrend.

       

      Any hint how to access these two controls (catching events, calling methods, reading/writing properties) are welcome.

      private void OnDisplayActivate(Display aDisplay)
      {
          try
          {
              SymbolClass symb = null;
              try {
                  symb = (SymbolClass)aDisplay.Symbols.Item("MDBTree1");
              }
              catch (Exception ex) {
                  symb = null;
              }
              if (symb == null || symb.Type != (int) PBSymLib.pbSYMBOLTYPE.pbSymbolControl)
                  return;

              try
              {
                  PBControl cont = (PBControl)symb;
                  MessageBox.Show("Type PBControl OK");
              }
              catch (Exception ex)
              {
                  MessageBox.Show("dont know the type for PBControl");
              }

              try
              {
                  symb = (SymbolClass)aDisplay.Symbols.Item("Trend1");
              }
              catch (Exception ex) {
                   symb = null;
              }
              if (symb == null || symb.Type != (int)PBSymLib.pbSYMBOLTYPE.pbSymbolTrend)
                  return;

              try
              {
                  PBSymLib.Trend trend = (PBSymLib.Trend)symb;
                  MessageBox.Show("Type Trend OK");
              }
              catch (Exception ex)
              {
                  MessageBox.Show("dont know the type for Trend");
              }

              try
              {
                  symb = (SymbolClass)aDisplay.Symbols.Item("BatchGroup1");
              }
              catch (Exception ex) {
                  symb = null;
              }
              if (symb == null || symb.Type != (int)PBSymLib.pbSYMBOLTYPE.pbSymbolBTrend)
                  return;

              MessageBox.Show("dont know the type for BTrend");

              // else
          }
          catch (Exception ex)
          {
              MessageBox.Show("Exception in OnDisplayActivate: " + ex.Message);
          }
      }

        • Re: Access to Controls on PB display
          andreas

          Thomas,

           

          you will have to add a reference to the PI-BatchTrend Type Library in your AddIn. The BatchTrend is not a "native" PB Symbol.

           

          Here is some sample code:


          if (_MySymbol.Name.ToString() == "BatchGroup1")
          {
              PIBTPB.BatchGroup _MYBatchGroup;
              _MYBatchGroup = (PIBTPB.BatchGroup)_MySymbol;
              _MYBatchGroup.BackgroundColor = 1;
          }

          Regarding the MDB Tree I need to think some more (and get in touch with the developers) because this is another case. The MDB Tree is an AddIn - so you are trying to manipulate one AddIn by the other.

           

          Hope this helps.

            • Re: Access to Controls on PB display
              tomster71

              Dear Andreas,

               

              first thanks a lot for your fast response.

               

              I have referenced the btrend32.dll in the Procbook folder and done the cast of the symbol named "BatchGroup1" to PIBTPB.BatchGroup. I got the exception "Unable to cast object of type PBObjLib.SymbolClass to type PIBTPB.BatchGroup".

                • Re: Access to Controls on PB display
                  andreas

                  Hi Thomas,

                   

                  that's interesting - the code snippit did work on my machine. Can you post the version of PI PB and visual studio you are using?

                   

                  I am not sure about it but I think when I wrote the code I had some issues and removed the OSIsoft.PBObjLib and added the PBObjLib COM Library (I was playing around with the XYPlot - another one of those candiadates ) - that would explain why I was able to run the code - both would be COM objects in that case.

                   

                  Are you actually using one of the PB AddIn templates? If so, which one (for sake of simplicity I use the PBToolbar)?

                   

                  Let us see what the developers have to say about this.

                   

                  regards,

                    • Re: Access to Controls on PB display
                      tomster71

                      Dear Andreas,

                       

                      i am using the AddInPBSimple_CS template for this test case. It generates references to OSIsoft.PBSymlib and OSIsoft.PBObjLib. After manually adding a reference to btrend32.dll i have got another reference to PBObjLib which is in conflict to OSIsoft.PBObjLib and prevents the compile of the project. So i had to delete OSIsoft.PBObjLib or PBObjLib from the references. I both cases the cast to PIBTPB.BatchGroup fails.

                       

                      Here are my versions
                      - VS 9.0.30729.1 SP (VS2008 + SP1)
                      - .NET FW 3.5 SP1
                      - BatchView 3.1.4.0
                      - PB 3.1.0.1
                      - PB Patch 3.1.1.0
                      - PB MUI Pack 3.1.0.1

                       

                      About the PB Patch 3.1.1.0:
                      Some of the users here like German GUI's. So we need to use the PB MUI Pack. This MUI is in conflict with the current BatchView. To fix it we have installed the PB Patch 3.1.1.0. After this the BatchView only appears on English regional settings. I case you are using PB without the patch i can try to delete the MUI pack and the PB patch.

                       

                      Best regards

                        • Re: Access to Controls on PB display
                          andreas

                          I just did the following:

                          • create new project AddInPBSimple
                          • add a COM reference PI-BatchTrend Type Library
                          • removed the reference to PBObjLib, so that I have only OSIsoft.PBObjLib as reference
                          • added the DisplayActivate event handler with the following code:
                            public void m_theApp_DisplayActivate(Display aDisplay)
                            {
                                PBObjLib.Symbols _MySymbols;
                                _MySymbols = m_theApp.ActiveDisplay.Symbols;
                                foreach (PBObjLib.Symbol _MySymbol in _MySymbols)
                                {
                                    if (_MySymbol.Name.ToString() == "BatchGroup1")
                                    {
                                        PIBTPB.BatchGroup _MYBatchGroup;
                                        _MYBatchGroup = (PIBTPB.BatchGroup)_MySymbol;
                                        _MYBatchGroup.BackgroundColor = 1;
                                    }
                                }
                            }

                          and it works on my system.

                           

                          The differences are the versions:

                          • MS VS2005 (This should not be an issue)
                          • PI BatchView 3.1.2
                          • PI ProcessBook 3.1.0.1 (this is the same), but without German GUI, plain english.
                          • Btrend32.DLL 3.1.3.1 (this might be the cause of the problem)
                          • PIBTPB Interop 3.2.0.0 (could you check yours?)
                          • OSIsoft.PBSymLib 3.1.0.0 (could you check yours?)
                          • OSIsoft.PBObjLib 3.1.0.0 (could you check yours?)

                          regards,

                            • Re: Access to Controls on PB display
                              tomster71

                              It seems like accessing the symbols by the item() property causes the problem. The following code works:

                              private BatchGroup _btrend = null;
                              private MDBTree _tree = null;
                              private Trend _trend = null;

                              private void OnDisplayActivate(Display aDisplay)
                              {
                              try
                              {
                                  foreach (Symbol symb in aDisplay.Symbols)
                                  {
                                      switch (symb.Name)
                                      {
                                          case "BatchGroup1":
                                              if (symb.Type == (int) PBSymLib.pbSYMBOLTYPE.pbSymbolBTrend)
                                                  _btrend = (BatchGroup) symb;
                                              break;
                                          case "MDBTree1":
                                              if (symb.Type == (int)PBSymLib.pbSYMBOLTYPE.pbSymbolControl)
                                                  _tree = (MDBTree) ((PBControl) symb).Object;
                                              break;
                                          case "Trend1":
                                              if (symb.Type == (int)PBSymLib.pbSYMBOLTYPE.pbSymbolTrend)
                                                  _trend = (Trend) symb;
                                              break;
                                      }
                                  }
                              }
                              catch (Exception ex)
                              {
                                  MessageBox.Show("Exception in OnDisplayActivate: " + ex.Message);
                              }

                               

                              Thanks a lot for your help! I have found the solution by comparing your example with my test case.

                               

                              The MDBTree can be accessed by the PBControl.Object attribute. It need a reference to OSIsoft.MDBTree.dll of the PI-SDK.

                                • Re: Access to Controls on PB display
                                  mlemley

                                  I have replicated the problem with the casting the PBObjLib.Symbol to BatchGroup. The problem appears to have been introduced with BV 3.1.3/PB 3.1. I'll post more information as soon as I've completed my investigation.

                                    • Re: Access to Controls on PB display
                                      tomster71

                                      My last test case works for me even with BV 3.1.4. It seems to depend on the way of taking the Symbol from the Symbols Collection.

                                       

                                      Display.Symbols.Item("BatchGroup1") could not be casted to BatchGroup. But the same Symbol retrieved inside a foreach loop could be casted.

                                        • Re: Access to Controls on PB display

                                          For the MDBTree control, you can use the the following code:

                                          PBSymLib.IDualSymControl control = (PBSymLib.IDualSymControl)aDisplay.Symbols.Item("MDBTree1");
                                          PISDKCtl.MDBTree tree = control.Object as PISDKCtl.MDBTree;

                                          Note that, as Andreas pointed out, the elements you are trying to manipulate are not "native" ProcessBook types, so you need to add the appropriate reference(s) in your project:
                                            - MDBTree is an ActiveX Control provided with PI SDK (\PIPC\PISDK\OSIsoft.MDBTree.dll)
                                            - BatchGroup is a type defined in the PI BatchView product's PIBTPB library (\PIPC\Batch\btrend32.dll)

                                           

                                          Also note that, while you can deal with the Module Database- and the PI-related parts of the MDBTree through this interface (i.e. the "tree" pointer), you will have to do any UI stuff using the PB Symbol itself (i.e. the "control" pointer or this particular item in the display's Symbols collection).

                                           

                                          As for the BatchGroup and the "calling it from a foreach loop or not" issue, I'll let Michael get back to you, as he is investigating on this within the PI BatchView product.

                                          With that said, I would like to ask you whether there's anything specific you're trying to achieve here or if you were just playing around and trying to understand the object model. The reason I ask is, if you are seriously planning to use the PI Module Database and the MDBTree Control, then I would suggest you consider using AF instead. Everything related to PI Module Database is already phasing out as we prepare the ground for AF - in fact, not too long from now, everything ModuleDB-related stuff will become obsolete as 100% of its functionality will be available (and better) in AF-related components.

                                            • Re: Access to Controls on PB display
                                              tomster71

                                              We have no problem with the current solution (foreach loop) as posted above. So we are fine.

                                               

                                              The reason for accessing the components by the Add-In was given in my starting post. We want to integrate the components in one display and want some interaction between them, e.g. clicking in the MDBTree should trigger someting in the BatchView. This could be done with VBA also, but for obvious reasons we like to use .NET.

                                            • Re: Access to Controls on PB display
                                              mlemley

                                              The ProcessBook problem has been documented as SCR# 29361. These are the details included in the SCR write-up:

                                               

                                              C# cannot cast PBObjLib.Symbol to PBControl or BatchGroup
                                              Problem with BatchGroup introduced in PB 3.1.

                                               

                                              PBControl - the following C# code fails to convert a Symbol object into a PBControl.

                                              private void PBControlFailure_Click(object sender, EventArgs e)
                                              {
                                                  PBObjLib.Symbol sym;
                                                  sym = display.Symbols.Add(PBObjLib.pbSYMBOLTYPE.pbSymbolControl, "Forms.ToggleButton.1");
                                                  Console.WriteLine(sym.Type);
                                                  PBSymLib.PBControl pbsym = sym as PBSymLib.PBControl;
                                                  if (pbsym != null)
                                                  {
                                                      Console.WriteLine(pbsym.Name);
                                                  }
                                              }

                                               

                                              Workaround - To workaround the problem, the IDualSymControl interface can be used to access properties on the PBControl. No workaround is available to retrieve a full PBControl to handle events.

                                              private void PBControlWokaround_Click(object sender, EventArgs e)
                                              {
                                                  PBObjLib.Symbol sym;
                                                  sym = display.Symbols.Add(PBObjLib.pbSYMBOLTYPE.pbSymbolControl, "Forms.ToggleButton.1");
                                                  Console.WriteLine(sym.Type);
                                                  PBSymLib.IDualSymControl pbsym = sym as PBSymLib.IDualSymControl;
                                                  if (pbsym != null)
                                                  {
                                                      Console.WriteLine(pbsym.Name);
                                                  }
                                              }

                                               

                                              BatchGroup - the following C# code fails to convert a Symbol object into a BatchGroup.

                                              private void BatchGroupFailure_Click(object sender, EventArgs e)
                                              {
                                                  PBObjLib.Symbol sym = display.Symbols.Add((PBObjLib.pbSYMBOLTYPE)21, null);
                                                  OSIsoft.ProcessBook.BatchView.BatchGroup bg = sym as OSIsoft.ProcessBook.BatchView.BatchGroup;
                                                  if (bg != null)
                                                  {
                                                      Console.WriteLine(bg.Name);
                                                  }

                                                  AccessBatchGroup(sym.Name);
                                              }

                                               

                                              Workaround - To workaround the problem, the symbol must be already be created in the ProcessBook display. In addition, the foreach loop must be used to iterate through all the symbols in the display.Symbols collection. If the symbol has been accessed by the foreach loop before being accessed by Display.Symbols.Item("BatchGroup1"), it can be successfully cast to a BatchGroup.

                                              private void AccessBatchGroup(string name)
                                              {
                                                  PBObjLib.Symbol sym = null;
                                                  try
                                                  {
                                                      sym = display.Symbols.Item(name);
                                                  }
                                                  catch (Exception )
                                                  {
                                                  }
                                                  if (sym == null)
                                                      return;
                                                  OSIsoft.ProcessBook.BatchView.BatchGroup bg = sym as OSIsoft.ProcessBook.BatchView.BatchGroup;
                                                  if (bg != null)
                                                  {
                                                      Console.WriteLine(bg.Name);
                                                  }
                                              }

                                              private void BatchGroupWorkaround_Click(object sender, EventArgs e)
                                              {
                                                  PBObjLib.Symbols mySymbols = display.Symbols;
                                                  foreach (PBObjLib.Symbol sym3 in mySymbols)
                                                  {
                                                  }

                                                  AccessBatchGroup("BatchGroup1");
                                                  AccessBatchGroup("BatchGroup2");
                                                  AccessBatchGroup("BatchGroup3");
                                                  AccessBatchGroup("BatchGroup4");

                                                  foreach (PBObjLib.Symbol sym3 in display.Symbols)
                                                  {
                                                      OSIsoft.ProcessBook.BatchView.BatchGroup bg3 = sym3 as OSIsoft.ProcessBook.BatchView.BatchGroup;
                                                      if (bg3 != null)
                                                          Console.WriteLine(bg3.Name);
                                                  }
                                              }