XControls have not been mentioned much around here, and it's time to give some credits to this advanced, poorly-documented, buggy feature in LabVIEW (which is also why it's one of my favourite ones). Thanks to XControls, you can really make custom controls. While normal custom controls (type definitions) allow you to change the aesthetics of existing controls, XControls enable pretty much any customization capabilities. In this series, I will try to explain when to use XControls, how they work, and of course some advice on how to create your own.
Where Do I Start?
You'll actually find some XControls lurking in your LabVIEW IDE: (jump) navigation buttons, 3D graphs or Sound & Vibration DAQ controls are examples of native XControls. And, of course, the overly simple but necessary Simple Dual Mode Thermometer XControl in the example finder. These are all great starting points to study how XControls work and how they can be used.
The Advanced Architectures in LabVIEW training from NI also covers XControls for an in-depth understanding with a professional instructor.
Here is a more theoretical article from NI, with a rather good explanation of what XControls are.
However, I suggest you keep reading this article before digging in all this material!
Why & When Do I Need XControls?
The first answer to that question is the same as for type definitions: reuse. If you intend to copy/paste that piece of code in 10 different places across projects, then it makes sense to convert it into a reusable component, and XControls are exactly made for this.
The next answer is code & UI de-cluttering. The first step towards UI simplification is usually to gather controls together and put them in a cluster. If the controls have some intelligence, it may be convenient to separate this logic from the calling VI, and put it in a new VI (displayed as a distinct window, or in a subpanel), or, in a XControl! NI particularly demonstrates this aspect with the FXP XControl, that you can come across when dealing with FXP data types (e.g. in the properties dialog box):
Last but not least, the representation of complexity. It may seem strange at first, but because XControls can be difficult to get hold of, the cost for developing a proper XControl can only be justified by the lack of maintainability and the difficulty to represent such UI features using simpler artifacts such as typedefs or subpanel VIs.
In ALL other cases (a.k.a. you're not checking all three criterias above), then what you need is not a XControl, so you'll to use something else instead.
But, What is a XControl?
A XControl is a special type of libraries (*.lvlib files) which extension is *.xctl. It basically inherits all the lvlib features (namespacing, public/private scopes..) and extends them. Keep that in mind when designing a XControl when you're in the project window.
On the front panel of a calling VI, a XControl is a typed subpanel: it has a terminal representation on the block diagram (don't forget a subpanel has no terminal!). In other words, it's a control which graphic representation is the "front panel" of the XControl (named façade).
Then we have it: a XControl is a library, and a XControl instance is a subpanel and a control at once.
How Does It Work?
At its core, a XControl behaves just like any other front panel control and is primarily controlled by the calling VI. User events (such as clicks, value changed...) are propagated from the VI to the XControl façade, and the code in this latter decides how to handle this event. However one thing greatly differs from normal controls: the event handler are developed and maintained by you!
In addition, there are system events triggered by the calling VI, which the XControl needs to listen to, for instance when a new value is written to the XControl terminal (during run-time), or when we change the XControl terminal from a control to an indicator (at edit time). This implicitly means a XControl is running as soon as it's dropped on a front panel (not just at run time). Never forget it (more on this later in the series)!
To make all of this work seamlessly, LabVIEW provides a pretty opaque API that connects the code inside XControl library, to the VIs using the XControl.
To that end, the XControl library must contain some mandatory files:
- A façade VI: the front panel corresponds to the look of the XControls when used by a calling VI, and the block diagram contains most of the engine, through an event structure responding to all the possible events mentioned above
- A data type: when declaring the XControl, you give it a fixed type. This will be the data type of the XControl on the block diagram of the calling VI. For instance, if you're creating a custom graph with extended capabilities, the data type is likely to be an array of DBL.
- A state: the state of the XControl is the most important part of the XControl. The state contains information eager to be modified, either internally by the XControl, or externally by the outside world through property and invoke nodes. The state is only available from the XControl and maintained by it.
Next time, there will be more on how a XControl executes (triggering, threading...) and how to easily debug it so you finally understand what in the world is going on with that XControl you've been working on.