The WebBrowser control embeds a full modern browser inside a FrameworX display. On the WPF runtimes (Windows, RichClient, SmartClient) it uses the Chromium-based WebView2 engine; on the HTML5/Web client it runs via OpenSilver as an embedded web frame. It accepts three content sources — a URL, a tag value containing HTML, or inline HTML — and exposes a JavaScript bridge (window.RW) that lets embedded HTML, SVG, or React components read FrameworX tags in real time.
Typical uses:
data-rw-tag attributes).RW.useTag).<ac:structured-macro ac:name="info"> ac:rich-text-body
This control supersedes the legacy HTML5Control component. New work should use WebBrowser; existing HTML5Control instances continue to run but should be migrated when convenient.
</ac:rich-text-body> </ac:structured-macro>
Runs on two runtimes:
Content-Security-Policy: frame-ancestors response header may need to be adjusted to allow framing. The RW JavaScript bridge and data-rw-tag binding target feature parity with the WPF runtime on the HTML5 client; see HTML5 client parity below for current status.| Property | Type | Description |
|---|---|---|
WebContentsSource | Enum: Url, Tag, Html | Selects the content source. See the three modes below. |
LinkedValue | String with expressions | Used by Url mode (the URL) and Tag mode (the tag reference whose value is an HTML string). Supports tag expressions such as @Tag.Reactor1.ReportUrl. |
HtmlContent | String | Used by Html mode. Full HTML, a fragment, an SVG document, or a React-bearing page. May contain data-rw-tag attributes for automatic live binding. |
AutoWrapHtml | Boolean (default true) | When true, fragments and bare SVG are wrapped in a minimal HTML document automatically. Set to false if you are supplying a complete <!DOCTYPE html> document and want no wrapping. |
EnableBrowserStorage | Boolean (default false) | When true, HTML content is served to the embedded browser through a virtual host (https://twebcontent.local/) instead of NavigateToString. This gives the content a proper browser origin so localStorage, sessionStorage, and other origin-dependent APIs work. Leave off unless the embedded content actually needs these APIs. |
Background, Foreground, BorderBrush, BorderThickness | Color / Thickness | Standard theming. Omit colors to inherit from the active theme. |
Embed an external web page. Set WebContentsSource = Url and put the address in URL (stored as LinkedValue). The value supports tag expressions, so the URL can be computed at runtime from tag values:
text https://reports.example.com/asset/{@Tag.Asset.Id}/summary
Useful for intranet dashboards, live reports, external documentation, and anything that already exists as a web page.
The HTML is supplied by a tag whose value is an HTML string. Set WebContentsSource = Tag and put the tag expression in String{With Tags} (stored as LinkedValue). The control reloads the HTML whenever the tag value changes.
Useful when the same display needs to show different content per asset, per recipe, or per operator role, and that content is produced by a ScriptTask, imported from a database, or delivered via an MQTT payload.
Inline HTML (or SVG, or a React-bearing page) is stored directly on the control. Set WebContentsSource = Html and paste the content into HtmlContent. This is the mode used for hand-authored mockups, Claude Design exports, and in-display React components.
HTML mode recognizes several content shapes automatically:
<!DOCTYPE html>…) — rendered as-is.<div>…) — wrapped in a minimal HTML document when AutoWrapHtml is on.<svg) — recognized as SVG and rendered natively by Chromium.<script> tags), the control's tag binder recognizes React patterns and wires the RW bridge so components can call hooks like RW.useTag().At runtime, the control injects a global window.RW object into the embedded page. This is the API that HTML, SVG, or React content uses to read FrameworX tag values. It is available immediately on page load — there is no explicit initialization step.
data-rw-tag attributeThe simplest way to bind live values is a plain HTML attribute. Any element with data-rw-tag="TagRef" is automatically bound — its text content is replaced with the live tag value, and the element gets a CSS class reflecting the tag's quality.
html <div class="card"> <h3>Reactor 1</h3> <p>Temperature: <span data-rw-tag="Plant.Reactor1.Temperature">--</span> °C</p> <p>Pressure: <span data-rw-tag="Plant.Reactor1.Pressure">--</span> kPa</p> </div>
No JavaScript required. The initial text (--) is the fallback shown until the first value arrives. Quality classes (rw-quality-good, rw-quality-bad, rw-quality-uncertain) can be styled in CSS if you want color-coded quality indication.
The RW object exposes these methods:
| Method | Description |
|---|---|
RW.subscribe(tagRef, callback) | Subscribe to a tag. The callback receives (value, quality, timestamp, tagRef) on each update. Returns an unsubscribe function. |
RW.tags.A.B.C | Proxy-style access. Reading RW.tags.Plant.Reactor1.Temperature returns the current value. |
RW.isConnected() | Returns true if the bridge is connected to the FrameworX runtime. |
RW.formatValue(v) | Standard value formatting (returns '--' for null/undefined). |
RW.getQualityClass(q) | Maps a quality code to a CSS class: rw-quality-good, rw-quality-bad, or rw-quality-uncertain. |
Quality codes follow the OPC convention: 192 (0xC0) is Good; values in the 0x00–0x3F range are Bad; the 0x40–0xBF range is Uncertain.
useTag and useTagsFor React-based content, the bridge exposes hook-style helpers so components re-render when tag values change:
| Hook | Description |
|---|---|
RW.useTag(tagRef) | Returns [value, quality]. The component re-renders on each tag update. |
RW.useTags([refs]) | Returns {ref: {value, quality}, …} for batch subscription. |
Example — a minimal React component embedded in HTML mode:
html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <script src="https://unpkg.com/react@18/umd/react.production.min.js"></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script> <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> </head> <body> <div id="root"></div> <script type="text/babel"> function ReactorCard() { const [temp, quality] = RW.useTag('Plant.Reactor1.Temperature'); return ( <div className={"card " + RW.getQualityClass(quality)}> <h3>Reactor 1</h3> <p>{RW.formatValue(temp)} °C</p> </div> ); } ReactDOM.createRoot(document.getElementById('root')).render(<ReactorCard />); </script> </body> </html>
The control detects when embedded content uses React and wires the bridge so hook calls (RW.useTag, RW.useTags) trigger hook-driven re-renders on tag updates. No extra configuration is required beyond including React via CDN scripts as shown above.
The current release of this control is read-only from JavaScript — embedded content can subscribe to tag values through the RW bridge but cannot write them back. Write-back from embedded HTML/React is a planned feature. Build read-only dashboards, mockups, and visualizations today; designs that need operator-controlled setpoints from embedded content should use native FrameworX input controls (Slider, TextBox, Button with setpoint dynamic) for now.
In the Designer editor, the control shows a live preview of the configured content:
RW bridge injected. All data-rw-tag elements show placeholder values (12.34) with the rw-quality-good class, and RW.useTag()/RW.subscribe() calls return the same placeholder data. This lets you verify layout and styling without a running solution.If an HTML5 display using the WebBrowser control fails to load correctly at runtime, clear the WebView2 cache:
Alternatively, clear cached files from the browser settings.
On the HTML5/Web client (OpenSilver + WebAssembly), the WebBrowser control maps to an OpenSilver web frame rather than an embedded WebView2. URL mode and inline HTML rendering work on both runtimes. The RW JavaScript bridge and data-rw-tag auto-binding target feature parity with the WPF runtime, but parity is an active area — complex React content that works in WPF may need adjustment on HTML5. When authoring embedded web content that must run on both, validate on both runtimes before shipping.
Url mode, the control navigates to whatever URL you supply. Treat it the same as any browser — don't navigate the control to untrusted pages.EnableBrowserStorage gives the content a persistent origin. Only turn it on when the embedded content actually uses localStorage, sessionStorage, IndexedDB, or similar APIs.Content-Security-Policy: frame-ancestors header may need to permit framing. Not relevant on the WPF runtime.| Situation | Mode |
|---|---|
| Embedding an existing web app, report, or intranet page | URL |
| HTML content that varies per asset / recipe / operator and is generated elsewhere | Tag |
| Hand-authored mockup or Claude Design export, with live tag values | HTML (with data-rw-tag) |
| Small React component reacting to tag updates | HTML (with React + RW.useTag) |
| Custom chart or visualization that FrameworX primitives don't cover | HTML (SVG or Canvas + RW.subscribe) |
Sometimes when running WeBrowser with a HTML5 display, the connection doesn't load properly. To fix that, as well as other display issues, we recommend clearning the cache from the WebBrowser.
To do that, go to “More tools”, “Development Tools”, “Network”, “Disable Cache”, or, in the browser settings, clear the cached files.