Visibility Property Binding Not Reevaluating - Popup Window

Currently we have a screen with a button, that button launches a popup window.

  • The popup window has a single parameter passed to it, indicating which screen the popup was launched from.
  • The root container of the popup has a variety of SQL bindings to check what it should display.
  • On internalFrameActivated calls a method on the root container to set up some additional visibility options.
  • The structure of the popup is Popu Window → Root Container → Injection Pumps (container) → Lag Injection Pump (container) → Numeric Text Field (bound to a tag coming from a device).
  • The lag injection pump container has a binding on its visibility property that is an expression looking at a custom property on itself for true or false. If true another nested if statement is looking at the quality of the data bound to the numeric text field, if the quality is good it evaluates to true, if it is bad it evaluates to false.

This all works correctly the first time you open the popup window. The numeric text field’s visibility will toggle correctly based off what the expression evaluates.

If you navigate to another window and launch the popup from there it will not re-evaluate the expression and evaluate the same as the previous time it was opened. In designer, you can click the binding icon, get the expression editor window, and click OK without changing anything, and the expression will evaluate a appropriately.

In the actual client, you have to close out of the client completely, and relaunch to force a new expression evaluation.

If the first launch should mark visible as true it reliably marks it as true and holds that even if subsequent launches should be visible is false. The same also works if the first launch should be visible as false, it will hold this indefinitely.

I am not sure what would cause this or how to troubleshoot further.

What are the conditions for the visibility? These sound like they should be bindings, not a scripted toggle of these visibilities.

internalFrameActivated is definitely the right event you should be using to run a script on startup though :thinking:

The script that runs on internalFrameActivated is doing some checks to see if certain tag folders exist in the end device. If those tags exist a custom property on the container called .exists() is toggled to true. The expression binding on the visible property is:

if( {Root Container.Injection Pumps.Lag Inj Pump.Exists}, if( trim(toStr({Root Container.Injection Pumps.Lag Inj Pump.StartSP.dataQuality})) != "Error_Configuration", 1, 0 ), 0 )

You can check if a tag or folder exists by either using the isGood() function (won’t only look for doesn’t exist) or you can read the quality of the tag/folder path and check if it’s not Bad_NotFound:

toStr({path/to/folder.quality}) != 'Bad_NotFound'

Unfortunately there isn’t a better way to do this in an expression at the moment, but I believe there is a ticket to add more functions to complement isGood for testing other qualities.

Using the above, you can then bind that to your Exists property and do away with your startup script

That isn’t the only thing the start up script is doing. I could rewrite that portion but that doesn’t seem to address the problem of the .visible not evaluating properly, unless you’re saying the start up script is somehow impacting the visibility binding?

Have you proven that the script is actually setting the exists property value each time correctly? Can you show its value on the screen in a temporary label and check? The binding on the visible property shouldn’t be affected by the script directly

We do something similar on some of our popups. I ended up using a timer that fires off and then using system.util.invokeAsynchronous and system.util.invokeLater to se the various properties.

A simple example:
Note this is in a timer action performed event

intlkTag = event.source.parent.IntlkTag

hasIntlk = False

def checkIntlk():
	hasIntlk = system.tag.exists(intlkTag)
	
	def updateGUI():
		event.source.parent.HasInterlock = hasIntlk
	
	system.util.invokeLater(updateGUI)

system.util.invokeAsynchronous(checkIntlk)