General
The generic OPC UA browsing control is represented by the UABrowseControl Class (in Windows Forms) or by the WpfUABrowseControl Class (in WPF).
With it, your forms can integrate a control with various OPC nodes from which the user can select. This control can be configured to serve many different purposes.
Here is an example of the generic OPC browsing control in action:

The functionality and properties of the UABrowseControl or WpfUABrowseControl are similar to that of UABrowseDialog, described earlier in this text. Please refer to the documentation of UABrowseDialog for details. Here are the major differences:
- There is no toolbar, no filter controls, no node information box, no error box, and no status bar. Events are provided (described further below) that allow you to implement similar functionality yourself, if needed.
- Changes you make in run-time to relevant values of the Inputs and InputsOutputs properties are immediately reflected in the control. Analogically, actions by the user that change the current node or the selection set are immediately projected into the InputsOutputs and Outputs properties.
- When multi-selection mode is enabled, the nodes are always selected directly in the list view, and not in a separate list. For this reason, the nodes in a multi-selection must all belong under a single parent branch.
- If only a tree view is displayed, the tree will also contain the leaves.
- If only a list view is displayed, the list will also always contain the branches, regardless of the Mode.ShowListBranches property value.
- When a node is selected in the tree view, a first node in the list view is not automatically focused.
- In the design-time mode, the control always shows simulated data, even if the Simulated property is set to false.
Using the Kind property, the browsing control can be configured to provide a tree view only (BrowseControlKinds.Tree), a list view only (BrowseControlKinds.List), or a combined tree view and list view (BrowseControlKinds.TreeAndList; this is the default).
The View property (of System.Windows.Forms.View enumeration type) controls how the list view items are displayed. Possible values are LargeIcon, Details (the default), SmallIcon, List, or Tile.
In order to achieve tight integration with other controls on your form, you can hook to events that the browsing control provides.
The CurrentNodeChanged event occurs when the current node changes. You can obtain the information about the new current node from InputsOutputs.CurrentNodeDescriptor and Outputs.CurrentNodeElement properties inside the event handler.
The SelectionChanged event is meant for multi-selection mode, and occurs when the selection set changes. You can obtain the information about the new selection set from InputsOutputs.SelectionDescriptors and Outputs.SelectionElements collections inside the event handler.
The NodeDoubleClick event occurs when a node is double-clicked. This is the current node, and therefore the information about it can be obtained in the same way as in the CurrentNodeChanged event handler, described above.
The BrowseFailure event indicates that an exception has occurred during browsing. The information about the exception is contained in the event arguments.
Windows Forms
In Windows Forms, the generic OPC UA browsing control is represented by the UABrowseControl Class, which is implemented directly in the Windows Forms technology. There is also a corresponding icon in the Visual Studio Toolbox that you drag onto a design surface of your forms or user control.
WPF
In WPF (Windows Presentation Foundation), the generic OPC UA browsing control is represented by the WpfUABrowseControl Class, which is implemented as a WPF wrapper around the Windows Forms control (UABrowseControl). There is also a corresponding icon in the Visual Studio Toolbox that you drag onto a design surface of your window.
Example
// This example shows how to allow browsing for an OPC Unified Architecture node by placing a browsing control on the form.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.
using System;
using System.Windows.Forms;
using OpcLabs.BaseLib;
using OpcLabs.EasyOpc.UA.Forms.Browsing;
namespace UAFormsDocExamples._UABrowseControl
{
public partial class UsageForm : Form
{
public UsageForm()
{
InitializeComponent();
}
private void getOutputsButton_Click(object sender, EventArgs e)
{
// Obtain the current node element.
UABrowseNodeElement currentNodeElement = uaBrowseControl1.Outputs.CurrentNodeElement;
// Display the present parts of the current node element in the outputs text text box.
outputsTextBox.Text = "";
if (!(currentNodeElement.HostElement is null))
outputsTextBox.Text += $"{nameof(UABrowseNodeElement.HostElement)}: {currentNodeElement.HostElement}\r\n";
if (!(currentNodeElement.DiscoveryElement is null))
outputsTextBox.Text += $"{nameof(UABrowseNodeElement.DiscoveryElement)}: {currentNodeElement.DiscoveryElement}\r\n";
if (!(currentNodeElement.NodeElement is null))
outputsTextBox.Text += $"{nameof(UABrowseNodeElement.NodeElement)}: {currentNodeElement.NodeElement}\r\n";
}
private void uaBrowseControl1_BrowseFailure(object sender, FailureEventArgs e)
{
// Append the event name and its arguments to the browsing events text box.
browsingEventsTextBox.Text += $"{nameof(UABrowseControl.BrowseFailure)}: {e}\r\n";
}
private void uaBrowseControl1_CurrentNodeChanged(object sender, EventArgs e)
{
// Append the event name and the current node element to the browsing events text box.
browsingEventsTextBox.Text += $"{nameof(UABrowseControl.CurrentNodeChanged)}; {uaBrowseControl1.Outputs.CurrentNodeElement}\r\n";
}
private void uaBrowseControl1_NodeDoubleClick(object sender, EventArgs e)
{
// Append the event name to the browsing events text box.
browsingEventsTextBox.Text += $"{nameof(UABrowseControl.NodeDoubleClick)}\r\n";
}
private void uaBrowseControl1_SelectionChanged(object sender, EventArgs e)
{
// Append the event name to the browsing events text box.
browsingEventsTextBox.Text += $"{nameof(UABrowseControl.SelectionChanged)}\r\n";
}
private void setInputsButton_Click(object sender, EventArgs e)
{
// Set the current node to our pre-defined OPC UA server.
uaBrowseControl1.InputsOutputs.CurrentNodeDescriptor.EndpointDescriptor = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer";
}
}
}
' This example shows how to allow browsing for an OPC Unified Architecture node by placing a browsing control on the form.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBNET .
' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
' a commercial license in order to use Online Forums, and we reply to every post.
Imports OpcLabs.EasyOpc.UA.Forms.Browsing
Imports OpcLabs.BaseLib
Namespace UAFormsDocExamples._UABrowseControl
Public Class UsageForm
Private Sub getOutputsButton_Click(sender As Object, e As EventArgs) Handles getOutputsButton.Click
' Obtain the current node element.
Dim currentNodeElement As UABrowseNodeElement = uaBrowseControl1.Outputs.CurrentNodeElement
' Display the present parts of the current node element in the outputs text text box.
outputsTextBox.Text = ""
If currentNodeElement.HostElement IsNot Nothing Then
outputsTextBox.Text += $"{NameOf(UABrowseNodeElement.HostElement)}: {currentNodeElement.HostElement}" + Environment.NewLine
End If
If currentNodeElement.DiscoveryElement IsNot Nothing Then
outputsTextBox.Text += $"{NameOf(UABrowseNodeElement.DiscoveryElement)}: {currentNodeElement.DiscoveryElement}" + Environment.NewLine
End If
If currentNodeElement.NodeElement IsNot Nothing Then
outputsTextBox.Text += $"{NameOf(UABrowseNodeElement.NodeElement)}: {currentNodeElement.NodeElement}" + Environment.NewLine
End If
End Sub
Private Sub uaBrowseControl1_BrowseFailure(sender As Object, e As FailureEventArgs) Handles uaBrowseControl1.BrowseFailure
' Append the event name and its arguments to the browsing events text box.
browsingEventsTextBox.Text += $"{NameOf(UABrowseControl.BrowseFailure)}: {e}" + Environment.NewLine
End Sub
Private Sub uaBrowseControl1_CurrentNodeChanged(sender As Object, e As EventArgs) Handles uaBrowseControl1.CurrentNodeChanged
' Append the event name and the current node element to the browsing events text box.
browsingEventsTextBox.Text += $"{NameOf(UABrowseControl.CurrentNodeChanged)}; {uaBrowseControl1.Outputs.CurrentNodeElement}" + Environment.NewLine
End Sub
Private Sub uaBrowseControl1_NodeDoubleClick(sender As Object, e As EventArgs) Handles uaBrowseControl1.NodeDoubleClick
' Append the event name to the browsing events text box.
browsingEventsTextBox.Text += $"{NameOf(UABrowseControl.NodeDoubleClick)}" + Environment.NewLine
End Sub
Private Sub uaBrowseControl1_SelectionChanged(sender As Object, e As EventArgs) Handles uaBrowseControl1.SelectionChanged
' Append the event name to the browsing events text box.
browsingEventsTextBox.Text += $"{NameOf(UABrowseControl.SelectionChanged)}" + Environment.NewLine
End Sub
Private Sub setInputsButton_Click(sender As Object, e As EventArgs) Handles setInputsButton.Click
' Set the current node to our pre-defined OPC UA server.
uaBrowseControl1.InputsOutputs.CurrentNodeDescriptor.EndpointDescriptor = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
End Sub
End Class
End Namespace
namespace UAFormsDocExamples._UABrowseControl
{
partial class UsageForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.uaBrowseControl1 = new OpcLabs.EasyOpc.UA.Forms.Browsing.UABrowseControl();
this.setInputsButton = new System.Windows.Forms.Button();
this.getOutputsButton = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.outputsTextBox = new System.Windows.Forms.TextBox();
this.browsingEventsTextBox = new System.Windows.Forms.TextBox();
((System.ComponentModel.ISupportInitialize)(this.uaBrowseControl1)).BeginInit();
this.SuspendLayout();
//
// uaBrowseControl1
//
this.uaBrowseControl1.Location = new System.Drawing.Point(13, 42);
this.uaBrowseControl1.MinimumSize = new System.Drawing.Size(135, 150);
this.uaBrowseControl1.Name = "uaBrowseControl1";
this.uaBrowseControl1.Size = new System.Drawing.Size(450, 300);
this.uaBrowseControl1.TabIndex = 0;
this.uaBrowseControl1.BrowseFailure += new OpcLabs.BaseLib.FailureEventHandler(this.uaBrowseControl1_BrowseFailure);
this.uaBrowseControl1.CurrentNodeChanged += new System.EventHandler(this.uaBrowseControl1_CurrentNodeChanged);
this.uaBrowseControl1.NodeDoubleClick += new System.EventHandler(this.uaBrowseControl1_NodeDoubleClick);
this.uaBrowseControl1.SelectionChanged += new System.EventHandler(this.uaBrowseControl1_SelectionChanged);
//
// setInputsButton
//
this.setInputsButton.Location = new System.Drawing.Point(13, 13);
this.setInputsButton.Name = "setInputsButton";
this.setInputsButton.Size = new System.Drawing.Size(75, 23);
this.setInputsButton.TabIndex = 1;
this.setInputsButton.Text = "&Set inputs";
this.setInputsButton.UseVisualStyleBackColor = true;
this.setInputsButton.Click += new System.EventHandler(this.setInputsButton_Click);
//
// getOutputsButton
//
this.getOutputsButton.Location = new System.Drawing.Point(13, 349);
this.getOutputsButton.Name = "getOutputsButton";
this.getOutputsButton.Size = new System.Drawing.Size(75, 23);
this.getOutputsButton.TabIndex = 2;
this.getOutputsButton.Text = "&Get outputs";
this.getOutputsButton.UseVisualStyleBackColor = true;
this.getOutputsButton.Click += new System.EventHandler(this.getOutputsButton_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(481, 42);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(88, 13);
this.label1.TabIndex = 3;
this.label1.Text = "&Browsing events:";
//
// outputsTextBox
//
this.outputsTextBox.Location = new System.Drawing.Point(13, 379);
this.outputsTextBox.Multiline = true;
this.outputsTextBox.Name = "outputsTextBox";
this.outputsTextBox.ReadOnly = true;
this.outputsTextBox.Size = new System.Drawing.Size(951, 59);
this.outputsTextBox.TabIndex = 4;
//
// browsingEventsTextBox
//
this.browsingEventsTextBox.Location = new System.Drawing.Point(484, 59);
this.browsingEventsTextBox.Multiline = true;
this.browsingEventsTextBox.Name = "browsingEventsTextBox";
this.browsingEventsTextBox.ReadOnly = true;
this.browsingEventsTextBox.Size = new System.Drawing.Size(480, 283);
this.browsingEventsTextBox.TabIndex = 5;
//
// UsageForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(976, 450);
this.Controls.Add(this.browsingEventsTextBox);
this.Controls.Add(this.outputsTextBox);
this.Controls.Add(this.label1);
this.Controls.Add(this.getOutputsButton);
this.Controls.Add(this.setInputsButton);
this.Controls.Add(this.uaBrowseControl1);
this.Name = "UsageForm";
this.Text = "UsageForm";
((System.ComponentModel.ISupportInitialize)(this.uaBrowseControl1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private OpcLabs.EasyOpc.UA.Forms.Browsing.UABrowseControl uaBrowseControl1;
private System.Windows.Forms.Button setInputsButton;
private System.Windows.Forms.Button getOutputsButton;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox outputsTextBox;
private System.Windows.Forms.TextBox browsingEventsTextBox;
}
}
Namespace UAFormsDocExamples._UABrowseControl
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class UsageForm
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()>
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Me.uaBrowseControl1 = New OpcLabs.EasyOpc.UA.Forms.Browsing.UABrowseControl()
Me.setInputsButton = New System.Windows.Forms.Button()
Me.getOutputsButton = New System.Windows.Forms.Button()
Me.label1 = New System.Windows.Forms.Label()
Me.browsingEventsTextBox = New System.Windows.Forms.TextBox()
Me.outputsTextBox = New System.Windows.Forms.TextBox()
Me.uaBrowseControl1.BeginInit()
Me.SuspendLayout()
'
'uaBrowseControl1
'
Me.uaBrowseControl1.Location = New System.Drawing.Point(13, 42)
Me.uaBrowseControl1.MinimumSize = New System.Drawing.Size(135, 150)
Me.uaBrowseControl1.Name = "uaBrowseControl1"
Me.uaBrowseControl1.Size = New System.Drawing.Size(450, 300)
Me.uaBrowseControl1.TabIndex = 0
'
'setInputsButton
'
Me.setInputsButton.Location = New System.Drawing.Point(13, 13)
Me.setInputsButton.Name = "setInputsButton"
Me.setInputsButton.Size = New System.Drawing.Size(75, 23)
Me.setInputsButton.TabIndex = 1
Me.setInputsButton.Text = "&Set inputs"
Me.setInputsButton.UseVisualStyleBackColor = True
'
'getOutputsButton
'
Me.getOutputsButton.Location = New System.Drawing.Point(13, 349)
Me.getOutputsButton.Name = "getOutputsButton"
Me.getOutputsButton.Size = New System.Drawing.Size(75, 23)
Me.getOutputsButton.TabIndex = 2
Me.getOutputsButton.Text = "&Get outputs"
Me.getOutputsButton.UseVisualStyleBackColor = True
'
'label1
'
Me.label1.AutoSize = True
Me.label1.Location = New System.Drawing.Point(481, 42)
Me.label1.Name = "label1"
Me.label1.Size = New System.Drawing.Size(88, 13)
Me.label1.TabIndex = 3
Me.label1.Text = "Browsing &events:"
'
'browsingEventsTextBox
'
Me.browsingEventsTextBox.Location = New System.Drawing.Point(484, 59)
Me.browsingEventsTextBox.Multiline = True
Me.browsingEventsTextBox.Name = "browsingEventsTextBox"
Me.browsingEventsTextBox.ReadOnly = True
Me.browsingEventsTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical
Me.browsingEventsTextBox.Size = New System.Drawing.Size(480, 283)
Me.browsingEventsTextBox.TabIndex = 5
'
'outputsTextBox
'
Me.outputsTextBox.Location = New System.Drawing.Point(13, 379)
Me.outputsTextBox.Multiline = True
Me.outputsTextBox.Name = "outputsTextBox"
Me.outputsTextBox.ReadOnly = True
Me.outputsTextBox.Size = New System.Drawing.Size(951, 59)
Me.outputsTextBox.TabIndex = 4
'
'UsageForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(976, 450)
Me.Controls.Add(Me.browsingEventsTextBox)
Me.Controls.Add(Me.outputsTextBox)
Me.Controls.Add(Me.label1)
Me.Controls.Add(Me.getOutputsButton)
Me.Controls.Add(Me.setInputsButton)
Me.Controls.Add(Me.uaBrowseControl1)
Me.Name = "UsageForm"
Me.Text = "Usage"
Me.uaBrowseControl1.EndInit()
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents uaBrowseControl1 As OpcLabs.EasyOpc.UA.Forms.Browsing.UABrowseControl
Friend WithEvents setInputsButton As Button
Friend WithEvents getOutputsButton As Button
Friend WithEvents label1 As Label
Friend WithEvents outputsTextBox As TextBox
Friend WithEvents browsingEventsTextBox As TextBox
End Class
End Namespace
Advanced
If you want to change the parameters of the client objects the component uses to perform its OPC operations, you can use the ClientSelector Property.
See Also
Examples - Client User Interface