AI Windows: Blazor Windows
AI-first map of Blazor window framework APIs and window hosting.
Blazor Windows Discovery Map
Reference map for Blazor-backed native windows, WebView2 hosts, dialog windows, Razor view resolution, custom title bars, and window automation.
Use core/blazor.md for shared Razor component infrastructure such as
BlazorReactiveComponent, ReactiveSection, dynamic view resolution, content
repository, and JS utilities.
Use osd/screen-overlay.md for click-through desktop annotations and
nuget/imgui-sdk.md for optional ImGui windows.
User Intents
- Open a script-owned Razor/Blazor dialog.
- Host a Razor component in a native window.
- Understand when a C# Overlay is different from a script-created window.
- Configure size, position, owner, transparency, topmost, no-activate, or click-through behavior.
- Access the owning window from inside a Razor component.
- Register or resolve Razor views by DataContext.
- Open WebView DevTools.
- Load CSS/JavaScript/assets into the hosted WebView.
- Suppress WebView/browser shortcuts such as Ctrl+A, Ctrl+P, and F5 while keeping Blazor shortcut handlers active.
- Use reactive Razor components for toggles and script-facing UI.
- Open complex editor/tool windows from a large script app.
Concept Model
IBlazorWindowis a native WPF/WinForms window hosting Blazor content.ViewTypeis the Razor component type.DataContextis passed to the hosted view.IBlazorWindowControllerowns window state and operations.IBlazorWindowNativeControllerowns native handle/rectangle operations.IBlazorWindowAccessorexposes the owning window inside a component.BlazorContentPresenterresolves dynamic component content.- WebView2 is the embedded browser that renders the Razor/HTML/CSS/JS surface.
- C# Overlay is a preconfigured script-hosted Blazor surface controlled by aura overlay settings.
- A script-created Blazor window is opened explicitly by script/app code.
- Blazor windows are native windows; use OSD/screen-overlay maps for click-through screen annotations.
API Details
IBlazorWindow- main window contract;Show,ShowDialog,Close,ShowDevTools,ViewType,DataContext,Container,AdditionalFiles,AdditionalFileProvider,RegisterFileProvider.IBlazorWindowController- visual and behavior properties.IBlazorWindowNativeController-GetWindowHandle,GetWindowRect,SetWindowRect.IDialogWindowUnstableScriptingApi- script-facing helper for dialog windows.IBlazorWindowAccessor- injectable owner-window accessor.IBlazorViewRepository,IBlazorViewRegistrator,BlazorViewAttribute- DataContext-based view resolution.BlazorReactiveComponent/BlazorReactiveComponent<T>- common base for reactive Razor components.IBlazorContentRepository- app/global list of Blazor CSS/JS files inserted into hosted WebViews.IRootContentFileProvider- root/static-web-asset lookup for files referenced by Blazor content.IScriptFileProvider- script/project resource file provider.ScriptEmbeddedResourceFileProvider- exposes embedded script assembly resources throughIScriptFileProvider.ScriptBlazorWindowConfigurator- registers the script file provider with script-owned Blazor windows.IJsPoeBlazorUtils.LoadCss(...)- load CSS into the WebView at runtime.IJsPoeBlazorUtils.LoadScript(...)- load plain JavaScript into the WebView at runtime.IJsPoeBlazorUtils.SuppressWellKnownBrowserShortcuts(...)- explicit opt-in DOM listener for blocking common browser/WebView default shortcuts. It returns an async-disposable handle and does not stop propagation by default.HeadContent- declarative Blazor way to add CSS/head content.ToggleButton- reusable PoeShared Blazor two-state button control.ScriptBlazorWindowConfigurator- script-window integration point that wires script file providers/resources into windows.
Practical Concepts
Native file dialogs from a hosted component
For a WPF Open or Save file dialog, capture IBlazorWindowAccessor.Window at command
invocation. On that window's Dispatcher, obtain GetWindowHandle() and pass
it to PoeShared.Dialogs.Services.IOpenFileDialog.ShowDialog(IntPtr).
WpfFileDialog resolves the live WPF Window and uses
Microsoft.Win32.OpenFileDialog.ShowDialog(Window). For Save, pass the same
owner to ISaveFileDialog.ShowDialog(IntPtr); WpfFileDialog uses
Microsoft.Win32.SaveFileDialog.ShowDialog(Window). Cancellation returns no
file; successful selection updates LastFile.
The explicit owner must belong to a live WPF window on the calling dispatcher.
It does not fall back to an active window or a hidden helper. The parameterless
Open API retains its existing owner selection. A backend without explicit-owner
support throws NotSupportedException. The parameterless Save API retains its
existing owner selection. BT editor LoadFromFileCommand and SaveToFileCommand
require the invoking host IBlazorWindow as their command parameter; toolbar and
keyboard callers provide their scoped IBlazorWindowAccessor.Window.
These services live in PoeShared.Wpf and are host services, not top-level script
members.
Automatic ownership and pinning
AutoOwner defaults to true in the native window factory and applies to both
Show() and ShowDialog(). At the first automatic presentation the shared core
chooses the active registered application window, or the main root configured by
the desktop host through BlazorWpfRegistrations.ConfigureMainWindow. If that
window is disabled, it follows direct modal blockers within that owner's family.
Other families and prewarmed, unshown windows do not become modal owners.
The automatic decision, including no owner, is retained across repeated Show and
Hide/Show. This is presentation-time context, not the historical initiator of an
asynchronous operation. A nonzero OwnerHandle overrides automatic selection
exactly, including when AutoOwner is false. To detach an existing window, hide
it, set OwnerHandle = IntPtr.Zero and AutoOwner = false, then show it again.
Re-enabling AutoOwner returns to its cached automatic decision, if already made.
Ownership must be acyclic.
Topmost remains the caller's requested pin. The native effective pin is that
request OR the owner's effective pin, transitively, for modal and non-modal
windows. Inheritance never overwrites the requested setting. The same owner
supplies initial CenterOwner positioning and modal disable/restore behavior.
Repeated Show does not recenter the window.
ShowDialog() also blocks other visible registered windows on its dispatcher,
as WPF does. Overlapping modal windows share that blocking lifetime, so closing
one does not enable a window still blocked by another. Hide or successful
Close/Dispose while a dialog is waiting to open prevents that pending show;
a hidden window can subsequently be shown again.
Application dialog callers do not need an owner service, scoped HWND dependency, or owner arguments. Script-created windows, overlays, notifications and independent editor roots disable AutoOwner at their shared creation boundaries. Scripts may opt in explicitly or assign OwnerHandle. A standalone host without a configured root can still use an active registered window; disable AutoOwner for independent SDK roots. The internal registry retains weak controller references and also backs container-scoped AI browser-view discovery.
Set INativeWindow.SuppressActivation before native handle creation to constrain
ShowActivated, native activation and explicit Activate. Handle creation can precede
Show/ShowDialog. Later changes are ignored with a warning, like AllowsTransparency.
The default is false.
Hosts can call BlazorWpfRegistrations.ConfigureActivationSuppression(bool) during
container setup to apply the property to subsequently resolved native and Blazor windows
without replacing scoped Blazor configurators. EyeAuras configures it from --no-activate.
- Razor component files are normal project files and can have
.razor.cscode-behind. - Public Razor component classes are easiest for script-created windows.
- Components should use Blazor dependency injection, parameters, and
DataContext; top-level script host members are not component globals. DataContextis the main way to pass a view-model/service object into a hosted component.IBlazorWindowAccessoris the way for a component to reach the owning native window.ShowDevTools()opens WebView developer tools and is useful for CSS/JS debugging.- CSS can be inline, loaded declaratively through
HeadContent, or loaded programmatically throughLoadCss. - Bootstrap and the standard EyeAuras/PoeShared Blazor styles are normally registered by the host. Prefer these classes before adding custom CSS.
- JavaScript can be loaded through
LoadScript; module-style JS follows normal Blazor/JS interop rules. - Browser/WebView shortcuts that conflict with app UI can be suppressed with
IJsPoeBlazorUtils.SuppressWellKnownBrowserShortcuts(...); adddata-poe-browser-shortcuts="allow"to DOM subtrees that should opt out. - Script embedded resources are exposed through
IScriptFileProviderand registered with script-owned Blazor windows byScriptBlazorWindowConfigurator. They are available by relative path once the provider is attached. - Multiple toggles or repeated controls should be backed by explicit properties or item view-models, not copy-pasted hardcoded accessors.
PoeShared.Dialogs.Services.IFolderBrowserDialog.ShowDialog(IntPtr hwndOwner) in
PoeShared.Wpf borrows a live originating WPF HWND on that window's dispatcher;
explicit implementations validate dispatcher access and never fall back to a
foreground/global owner. Unsupported implementations throw; no-argument behavior
stays separate. App Razor callers obtain the current HWND from IBlazorWindowAccessor.
CSS And Static Assets
Blazor scoped CSS can be fragile in script-owned or dynamic windows. .razor.css
files are usually compiled into an assembly-level *.styles.css file, and the
scope attributes may not line up with generated child DOM, dynamic components,
third-party component markup, or content loaded through runtime composition.
Preferred order:
- Use no custom CSS when possible. Bootstrap and standard EyeAuras/PoeShared styles are already available in normal Blazor windows.
- Use normal global CSS for reusable UI shells, dynamic components, and third-party component styling.
- Add CSS/JS/images to the specific
IBlazorWindow.AdditionalFilescollection when the asset belongs to one window instance. - Add shared CSS/JS through
IBlazorContentRepository.AdditionalFileswhen it belongs to the app/module as a whole. - Use
IJsPoeBlazorUtils.LoadCss(...)orLoadScript(...)when a component must load an asset on demand during its lifecycle.
Per-window files are usually the best fit for mini-apps and script-created dialogs:
var window = dialogApi.CreateWindow<MyWindow>(viewModel);
window.AdditionalFiles = ImmutableArray.Create<IFileInfo>(
new RefFileInfo("my-window.css"),
new RefFileInfo("my-window.js"));
window.Show();
If files come from a provider instead of individual references, attach the provider to the window:
window.RegisterFileProvider(scriptFileProvider).AddTo(window.Anchors);
For global/module-level styles, register files once with the Blazor content repository:
var repository = container.Resolve<IBlazorContentRepository>();
repository.AdditionalFiles.Add(new RefFileInfo("MyModule.styles.css"));
repository.AdditionalFiles.Add(new RefFileInfo("assets/my-module.css"));
For lifecycle-controlled loading inside a component:
@inject IJsPoeBlazorUtils BlazorUtils
@code {
protected override async Task OnAfterFirstRenderAsync()
{
await base.OnAfterFirstRenderAsync();
await BlazorUtils.LoadCss("assets/my-window.css");
}
}
Embedded script resources flow through ScriptEmbeddedResourceFileProvider into
IScriptFileProvider. Script-owned windows get that provider registered by
ScriptBlazorWindowConfigurator, so Razor, CSS, JS, image, font, and other
resource paths can be resolved from the script project or compiled embedded
resources without manually copying files next to the application.
Common Flows
Script-Owned Dialog
- Create/resolve the dialog-window scripting API in top-level script or app composition code.
- Create a window for a Razor component type.
- Pass
DataContextif the component needs a view-model. - Configure startup location, size, transparency, or behavior before showing.
- Add the window to the owning lifetime so it closes when the script/app stops.
C# Overlay UI
- Create a C# Overlay aura item.
- Put Razor/CSS/JS/component code in the overlay script project.
- Use overlay settings for position, style, transparency, and window-vs-overlay behavior.
- Use live import/export workflow for fast UI iteration.
Load Assets
- Add CSS/JS/images as embedded resources in the script project.
- Reference images/videos by relative path from Razor.
- Prefer
IBlazorWindow.AdditionalFilesfor CSS/JS that belongs to one window instance. - Use
IBlazorContentRepository.AdditionalFilesfor app/module-wide CSS/JS. - Use
HeadContentfor simple declarative CSS links, orLoadCsswhen code controls loading time. - Use
LoadScriptfor plain JavaScript files or URLs.
Suppress Browser Shortcuts
- Inject
IJsPoeBlazorUtilsin the hosted component or shell. - Call
SuppressWellKnownBrowserShortcuts()during component initialization. - Store and dispose the returned
JsBrowserShortcutSuppressionRefwith the component/window lifetime. - Use
JsBrowserShortcutSuppressionOptionsfor custom shortcut lists or propagation behavior.
Embedded Resources In Script Windows
- Add files to the script project as embedded resources or project resources.
- Let the script runtime expose them through
IScriptFileProvider. - For script-created Blazor windows, rely on
ScriptBlazorWindowConfiguratoror callwindow.RegisterFileProvider(scriptFileProvider)directly. - Reference the resource by its normalized relative path from Razor, CSS, JS,
AdditionalFiles, orLoadCss/LoadScript.
Prefer
- Prefer
IDialogWindowUnstableScriptingApifor script-owned dialogs. - Prefer
IBlazorWindowAccessorinside hosted components. - Prefer
BlazorReactiveComponentwhen the component needs reactive refresh helpers. - Prefer
DataContext/view-models for non-trivial components. - Prefer embedded resources and relative paths for CSS/JS/images shipped with a mini-app.
- Prefer Bootstrap and built-in EyeAuras/PoeShared classes before adding custom CSS.
- Prefer
IBlazorWindow.AdditionalFilesfor per-window CSS/JS assets. - Prefer
IBlazorContentRepository.AdditionalFilesfor app/module-wide CSS/JS. - Prefer normal global CSS over scoped
.razor.csswhen styling dynamic components, child component DOM, or third-party component markup. - Prefer
SuppressWellKnownBrowserShortcuts(...)over one-off page-level scripts when a WebView app needs to block browser defaults. - Prefer
recipes/bot-memory-imgui-interface.mdwhen Blazor windows are part of a larger ImGui-rooted script app. - Prefer
osd/screen-overlay.mdfor drawing over the desktop. - Prefer
nuget/imgui-sdk.mdfor ImGui-specific tools.
Avoid
- Avoid manually creating WPF/WinForms shells for Razor content.
- Avoid changing creation-time transparency after the native window exists.
- Avoid assuming a Razor component can access its owner without accessor.
- Avoid assuming top-level script host members are available directly in Razor components.
- Avoid using Blazor Windows as the first choice for simple screen annotations; use the OSD/screen-overlay APIs for that.
- Avoid remote CSS/JS dependencies when a mini-app should work offline or be portable.
- Avoid relying on scoped
.razor.cssfor dynamic windows when the generated*.styles.cssfile is not registered, or when the final DOM is generated by child/third-party components. - Avoid page-specific global CSS names without a stable prefix.
- Avoid native/global keyboard interception when the issue is only browser DOM shortcut behavior inside a Blazor WebView.
Research Anchors
IBlazorWindow,IBlazorWindowController,IBlazorWindowNativeController,IDialogWindowUnstableScriptingApi,IBlazorWindowAccessor,BlazorContentPresenter,IBlazorViewRepository,BlazorViewAttribute,ShowDevTools,BlazorReactiveComponent,IJsPoeBlazorUtils,LoadCss,LoadScript,SuppressWellKnownBrowserShortcuts,HeadContent,ToggleButton,IBlazorContentRepository,IRootContentFileProvider,IScriptFileProvider,ScriptEmbeddedResourceFileProvider,ScriptBlazorWindowConfigurator,AdditionalFiles,AdditionalFileProvider,RegisterFileProvider.
Search Synonyms
- Blazor window
- Razor window
- script dialog
- WebView2 window
- C# Overlay
- hosted Razor component
- Razor code-behind
- HeadContent
- LoadCss
- LoadScript
- SuppressWellKnownBrowserShortcuts
- browser shortcut suppression
- Ctrl+A
- Ctrl+P
- AdditionalFiles
- AdditionalFileProvider
- RegisterFileProvider
- IBlazorContentRepository
- IScriptFileProvider
- embedded resources
- scoped CSS
- razor.css
- styles.css
- BlazorReactiveComponent
- ToggleButton
- custom title bar
- click-through window
- transparent window
- WebView DevTools
Related Maps
osd/screen-overlay.mdcore/blazor.mdrecipes/bot-memory-imgui-interface.mdnuget/imgui-sdk.mdscripting/project-workflow.mdscripting/references-and-resources.mdscripting/runtime.mdcore/app-runtime-contexts.md