Skip to content

Plugin UI Notifications and Themes

NyxionSoftware edited this page Aug 5, 2026 · 2 revisions

Plugin UI, Notifications, Controls, and Themes

Notifications

await context.UiManager.ShowNotificationAsync(
    Info.PluginIdentifier,
    new PluginNotificationRequest("Schedule refreshed", "42 events were loaded.", PluginNotificationSeverity.Success),
    cancellationToken);

Use Information for neutral state, Success for completed user actions, and Error for actionable failures. Avoid showing a notification for high-frequency background events; log those instead.

Confirmation

bool confirmed = await context.UiManager.ShowConfirmationAsync(
    Info.PluginIdentifier,
    "Clear cached schedule?",
    "The schedule will be downloaded again the next time it is needed.",
    cancellationToken);

Use confirmation only for destructive or difficult-to-reverse actions.

Plugin dialog

UserControl content = new ScheduleDetailsView { DataContext = viewModel };
await context.UiManager.ShowDialogAsync(
    Info.PluginIdentifier,
    new PluginDialogRequest("Schedule Details", content, Width: 760, Height: 560),
    cancellationToken);

Plugin dialogs are owned, modeless windows. The main window remains interactive. The host closes registered plugin dialogs during plugin cleanup.

Find and extend the application UI

Named main-page elements currently include:

Name Type/purpose
MainViewRoot Main view root grid
ApplicationToolbar Top application toolbar
ApplicationToolbarActions Toolbar button host
ReceiverList Receiver list
ReceiverWorkspace Workspace scroll viewer
ReceiverWorkspaceGrid Main receiver content grid
ReceiverInformationCard Receiver information card
NowPlayingCard Now-playing card
NowPlayingEventName Event title text
NowPlayingEventTime Event time text
NowPlayingProgressBar Live event progress
NowPlayingOptionsHost Preferred host for compact now-playing options
ChannelControlCard Channel-control card
ReceiverActionsCard Receiver-actions card

Named elements are extension points, not permanent child-index contracts. Handle null and application upgrades gracefully.

StackPanel? host = await context.UiManager.FindElementAsync<StackPanel>(
    Info.PluginIdentifier,
    "NowPlayingOptionsHost",
    cancellationToken);

if (host is not null)
{
    CheckBox option = new() { Content = "Use plugin schedule for now playing" };
    option.SetResourceReference(FrameworkElement.StyleProperty, "ModernCheckBoxStyle");
    host.Children.Add(option);
    context.UiManager.RegisterCleanup(Info.PluginIdentifier, () => host.Children.Remove(option));
}

For arbitrary main-window work:

await context.UiManager.InvokeOnMainWindowAsync(Info.PluginIdentifier, window =>
{
    window.Activate();
}, cancellationToken);

Cleanup pattern

Register cleanup immediately after insertion, not later:

panel.Children.Add(card);
context.UiManager.RegisterCleanup(Info.PluginIdentifier, () =>
{
    card.DataContext = null;
    panel.Children.Remove(card);
});

Also unsubscribe events owned by the control or view model. Host removal from the visual tree does not automatically detach external event subscriptions.

Available control styles

Apply styles with dynamic lookup:

button.SetResourceReference(FrameworkElement.StyleProperty, "PrimaryButtonStyle");
Resource Target/use
CardBorderStyle Standard card Border
PrimaryButtonStyle Accent primary action
SecondaryButtonStyle Neutral secondary action
SuccessButtonStyle Positive action
DangerButtonStyle Destructive action
IconButtonStyle Compact icon-only button
TransparentButtonStyle Low-emphasis action
ModernTextBoxStyle Text input
ModernComboBoxStyle Single-choice input
ModernCheckBoxStyle Checkbox
ModernToggleSwitchStyle Toggle represented by a CheckBox
ModernContextMenuStyle Context menu
ModernMenuItemStyle Context-menu item
ModernMenuSeparatorStyle Menu separator
PluginDataGridStyle Themed schedule/data grid
ReceiverListBoxStyle / ReceiverListBoxItemStyle Receiver-like lists
PageTitleTextStyle Page title
SectionTitleTextStyle Card/section title
LabelTextStyle Uppercase field label
ValueTextStyle Display value

Styles used internally for plugin-manager cards, notifications, or discovery state may exist but are less stable extension points. Prefer the general-purpose resources above.

Use dynamic resources in XAML

<Border Style="{DynamicResource CardBorderStyle}">
  <StackPanel>
    <TextBlock Text="Plugin Schedule" Style="{DynamicResource SectionTitleTextStyle}" />
    <TextBlock Text="Current program" Foreground="{DynamicResource SecondaryTextBrush}" />
    <Button Content="Refresh" Style="{DynamicResource SecondaryButtonStyle}" />
  </StackPanel>
</Border>

Use DynamicResource, not StaticResource, for theme colors and styles that should update while the application is running.

Clone this wiki locally