I am trying to rename some template parameters on a Vision template that has many instances of it in my project. When I rename the parameter, however, all of the parameter values and bindings that were associated with the renamed parameter are lost.
Is there any way to prevent this behavior from happening?
No. To do what you're describing automatically, editing a template would have to 'reach out' to every single window in your project, open it up, check whether it has an instance of that template, then rename the property and binding (and assume that it succeeds). On large projects, that could take many minutes and would absolutely kill designer performance as we open literally hundreds of windows.
With that limitation in mind, do you know of any good ways to accomplish renaming a template parameter and somehow restoring the bindings?
Is there a way to do this via the underlying xml that is copied when you copy a Vision component or have you heard of any tools created by others to help with this type of task?
I am trying to avoid needing to manually transfer the parameters and bindings of each template instance, if possible, as that would likely take me days…
In theory, you could do this via XML editing. If you're on a new enough 8.1 version, change the project properties to store window configuration in XML format, then open -> save every window in your project. The XML format is not documented and not particularly human readable, but if you're lucky and your "from" parameter name you're trying to replace is unique in the window you could use a programmatic find/replace on all the files to make changes in bulk.
Take lots of backups before you start, because it's quite easy to break the XML representation in such a way that you cannot open the resource in the designer at all anymore.
I would manipulate each window's interaction controller object with a designer script. (Use the SDK javadocs for guidance.) Not trivial, but likely easier than XML manipulation.
(Have the script close the windows after manipulation to keep the memory usage down.)
This is probably a silly mistake on my part caused by my lack of familiarity with the Ignition SDK.
I am trying to test the InteractionController interface in a designer script and keep getting an error stating that I am not providing enough arguments to the getPropertyAdapter method even though the javadocs makes it seem like the getPropertyAdapter method only takes 2 arguments.
from com.inductiveautomation.factorypmi.application.binding import InteractionController
# Get window object
vision_window = system.gui.getWindow("Stations/TEST")
# Find the template instance
template_instance = vision_window.getRootContainer().getComponent("ExampleComponent")
# Modify a template parameter
InteractionController.getPropertyAdapter(template_instance, "Title")
This code yields the following error:
Traceback (most recent call last):
File "<input>", line 10, in <module>
TypeError: getPropertyAdapter(): expected 3 args; got 2
It’s been awhile since I’ve done stuff with the interactionController but I believe you need to get a reference to it with interactionController = vision_window.getInteractionController() then call the getPropertyAdapter method on that reference
To expand on the 'why' of this:
Java has both static and instance methods (since everything is contained in a class).
Jython allows you to call instance methods of a class using a similar calling convention to Python, by providing your own "self" argument (Java would call it this).
I almost have a working solution in place (which I will share when finished) however, I am missing one last piece of the puzzle.
After I move the parameter bindings from the old template to the new template, I can see that the parameters are bound but the bindings do not seem to have been activated yet. I have to click on each parameter’s binding editor dialog button to get the actual bound value to refresh.
The new bindings are also lost if I copy/paste the new template unless I open the binding dialog of each new binding as described above.
Thanks again for you suggestion of using the InteractionController class. Does the code in my post above follow the idea you were presenting? Can you see what I am doing wrong in correctly moving the adapters from the old template to the new template?
I'd try to alter the binding to point at the new parameter, not try to replace it. (Bindings have to start up with the component, and there are complex nuances there.)
I replaced the commented lines of code with the uncommented line and that fixed the copy/paste issue I mentioned above, and the template now acts like it is bound to the tags I am using.
binding = interactionController.getPropertyAdapter(component, parameter["OLD"])
if binding is not None:
#interactionController.setPropertyAdapter(component, parameter["NEW"], binding)
#interactionController.removePropertyAdapter(component, parameter["OLD"])
binding.setTargetPropertyName(parameter["NEW"])
The issue I am seeing now is that the Vision Property Editor does not show that the parameters are bound unless I cut/paste the template instance. Once it is pasted, the parameters show that they are bound.
I assume I am missing another step to complete the alteration process.
I apologize for my ignorance using these classes, this is my first time digging into the SDK classes.
Also, is there a better place to look for documentation on these classes than the javadocs? It does not seem like there is much information on what the methods do or how to use them in the javadocs.
Try closing and re-opening the window. (Component startup nuances, I suspect.)
You are completely off into the unsupported weeds. Sorry. If the javadoc doesn't help, your only further tool is reflection. (See the reflection tools in my Integration Toolkit.)
Closing/Opening the window also does not fix the issue, only copy/paste works so far.
I also tried restarting the designer and that also did not make a difference, unfortunately.
I compared the copied XML data before and after I pasted the component and there are certainly differences. @paul-griffith Do you know if the copy/paste function is doing some automatic repairs/substitutions that I can handle in my scripting to fix this issue?