WidBar.SDK
2.0.0
dotnet add package WidBar.SDK --version 2.0.0
NuGet\Install-Package WidBar.SDK -Version 2.0.0
<PackageReference Include="WidBar.SDK" Version="2.0.0" />
<PackageVersion Include="WidBar.SDK" Version="2.0.0" />
<PackageReference Include="WidBar.SDK" />
paket add WidBar.SDK --version 2.0.0
#r "nuget: WidBar.SDK, 2.0.0"
#:package WidBar.SDK@2.0.0
#addin nuget:?package=WidBar.SDK&version=2.0.0
#tool nuget:?package=WidBar.SDK&version=2.0.0
WidBar SDK
WidBar SDK is the public toolkit for building taskbar widgets for WidBar with WinUI 3 and .NET 8.
Your widget supplies three optional pieces of interface:
- a compact taskbar preview
- a flyout with richer content and controls
- a settings page for each placed widget instance
WidBar takes care of discovery, placement, taskbar behavior, flyout hosting, settings persistence, smart stacks, and communication with the widget process.
For a ready to use project, start with the WidBar widget template.
Install
Add the package to the WinUI 3 project that contains your widget:
<PackageReference Include="WidBar.SDK" Version="2.0.0" />
The project must be a packaged WinUI 3 application targeting Windows 11. The
package containing it must declare a Windows AppExtension named
com.widbar.widget.
Application entry point
Derive your application from WidgetHostApplication and return a new plugin
instance from CreatePlugin():
using WidBar.SDK;
using WidBar.SDK.Hosting;
public partial class App : WidgetHostApplication
{
public App()
{
InitializeComponent();
}
protected override IWidgetPlugin CreatePlugin()
{
return new WeatherWidget();
}
}
WidBar can place the same widget more than once. CreatePlugin() is called for
each instance, so instance state should be stored in normal instance fields and
not in static fields.
A minimal widget
WidgetPluginBase is the simplest way to implement a widget:
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using WidBar.SDK;
public sealed class WeatherWidget : WidgetPluginBase
{
public override string Id => "com.contoso.weather";
public override string Name => "Weather";
public override string Version => "1.0.0";
public override int PreviewLogicalWidth => 180;
public override int FlyoutWidth => 420;
public override int FlyoutHeight => 520;
public override WidgetFlyoutBackdrop FlyoutBackdrop => WidgetFlyoutBackdrop.Mica;
public override UIElement CreatePreviewContent()
{
return new WeatherPreview();
}
public override UIElement CreateFlyoutContent()
{
return new WeatherFlyout();
}
}
Plugin API
IWidgetPlugin
Every widget implements IWidgetPlugin. WidgetPluginBase provides useful
defaults for optional members.
| Member | Description |
|---|---|
Id |
Stable reverse DNS identifier for the widget. |
Name |
Name used by the widget host and standalone information window. |
Version |
Runtime version reported to WidBar. |
PreviewLogicalWidth |
Requested taskbar width in logical 96 DPI pixels. The default is 188. |
IsPreviewVisible |
Controls whether this widget currently occupies and displays its preview. The default is true. |
FlyoutWidth |
Requested flyout width in logical pixels. The base default is 390. |
FlyoutHeight |
Requested flyout height in logical pixels. The base default is 480. |
FlyoutBackdrop |
Selects a transparent, Mica, or Acrylic flyout background. |
InitializeAsync(context) |
Initializes one widget instance and receives its host context. |
CreatePreviewContent() |
Returns the WinUI 3 element shown on the taskbar. |
CreateFlyoutContent() |
Returns the WinUI 3 element shown in the flyout, or null when no flyout is needed. |
OnSettingsDraftChanged(json) |
Applies settings while the user edits them. The original JSON is sent again when the user cancels. |
DisposeAsync() |
Releases timers, subscriptions, sensors, and other resources owned by the instance. |
Description and Category are not runtime properties of IWidgetPlugin.
They belong to the extension metadata generated from the project properties.
IWidgetContext
InitializeAsync receives an IWidgetContext for the current placed instance.
| Member | Description |
|---|---|
InstanceId |
Stable identifier for this specific placed instance. |
SettingsJson |
Settings previously saved for this instance. |
DataDirectory |
Persistent directory created for this instance. |
RequestPreviewRefresh() |
Asks WidBar to read the current preview width and visibility again. |
RequestOpenFlyout() |
Opens the flyout without closing it when it is already open. This is useful for drag and drop workflows. |
RequestAttention() |
Makes this widget the visible member when it belongs to a smart stack. |
IsPreviewVisible |
Reports whether this widget is currently the visible member of its smart stack. |
PreviewVisibilityChanged |
Raised on the UI thread when the visible smart stack member changes. |
Store the context if the widget needs to send requests later:
private IWidgetContext? _context;
public override async Task InitializeAsync(IWidgetContext context)
{
await base.InitializeAsync(context);
_context = context;
}
RequestPreviewRefresh() is intended for host state such as a changed
PreviewLogicalWidth or IsPreviewVisible value. Normal binding updates inside
an already visible preview do not need a host refresh.
Windows theme support
The SDK automatically applies the current Windows shell theme to the preview, flyout, and settings hosts. A widget does not need to call a theme API.
Use WinUI theme resources instead of fixed foreground and background colors:
<Grid Background="Transparent">
<Border
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="6">
<TextBlock
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
Text="Weather" />
</Border>
</Grid>
Standard WinUI controls update automatically when Windows changes between light
and dark mode. If a custom renderer caches colors, listen to
ActualThemeChanged on its root element and rebuild only those cached colors.
Keep the taskbar preview root transparent. WidBar provides the taskbar surface and interaction background.
Smart stacks and attention
A smart stack lets several widgets share one taskbar slot. Only one member is shown at a time.
Use RequestAttention() when an important event should bring the widget to the
top of its stack:
private void OnTimerCompleted()
{
_context?.RequestAttention();
}
The call is safe when the widget is not in a stack. In that case it does nothing.
Use IsPreviewVisible and PreviewVisibilityChanged to pause work that only
serves the taskbar preview:
public override async Task InitializeAsync(IWidgetContext context)
{
await base.InitializeAsync(context);
context.PreviewVisibilityChanged += OnPreviewVisibilityChanged;
SetPreviewUpdatesEnabled(context.IsPreviewVisible);
}
private void OnPreviewVisibilityChanged(object? sender, bool isVisible)
{
SetPreviewUpdatesEnabled(isVisible);
}
This host visibility is separate from the plugin property
IWidgetPlugin.IsPreviewVisible. The context tells the widget whether it is on
top of a stack. The plugin property tells WidBar whether the widget wants to be
shown at all.
When the plugin changes its own visibility, call RequestPreviewRefresh():
public override bool IsPreviewVisible => _hasContent;
private void SetHasContent(bool value)
{
if (_hasContent == value)
return;
_hasContent = value;
_context?.RequestPreviewRefresh();
}
Flyout API
Return any WinUI 3 UIElement from CreateFlyoutContent(). Return null if the
widget has no flyout.
Choose the host background with WidgetFlyoutBackdrop:
TransparentMicaAcrylic
Implement IWidgetFlyoutLifecycle when the flyout starts work that should stop
while it is hidden:
| Member | Description |
|---|---|
OnFlyoutShown() |
Called after the flyout open animation has completed. |
OnFlyoutHidden() |
Called after the flyout has closed. |
Use these callbacks for detailed polling, media rendering, sensors, or other work that is only useful while the flyout is visible.
Modal dialogs and pickers
Use WidgetFlyout.EnterModalScope() before opening a picker or another modal
window owned by the flyout:
using var modalScope = WidgetFlyout.EnterModalScope();
var file = await picker.PickSingleFileAsync();
The scope keeps the flyout open while the dialog has focus. Nested scopes are supported.
Settings API
Implement IConfigurableWidgetPlugin to expose settings for each widget
instance:
public sealed class WeatherWidget :
WidgetPluginBase,
IConfigurableWidgetPlugin
{
public UIElement CreateSettingsContent(IWidgetSettingsContext context)
{
return new WeatherSettingsView(context);
}
}
IWidgetSettingsContext provides:
| Member | Description |
|---|---|
InstanceId |
Identifier of the instance being configured. |
SettingsJson |
Current settings JSON for that instance. |
SaveSettings(json) |
Updates the pending settings that WidBar persists when the user selects Save. |
RequestPreviewRefresh() |
Applies the pending settings to the live preview. |
The plugin owns the JSON schema. WidBar stores the text without interpreting its contents.
Categories
WidBar recognizes these WidgetCategory values:
UtilitySystemMediaProductivityInformationDeveloperEntertainment
Category and description are catalog metadata, not members that a plugin overrides at runtime. Declare them in the project:
<PropertyGroup>
<WidBarPluginId>com.contoso.weather</WidBarPluginId>
<WidBarPluginName>Weather</WidBarPluginName>
<WidBarPluginDescription>Current conditions and forecasts.</WidBarPluginDescription>
<WidBarPluginCategory>Information</WidBarPluginCategory>
<WidBarPluginVersion>1.0.0</WidBarPluginVersion>
<WidBarPluginPreviewWidth>180</WidBarPluginPreviewWidth>
<WidBarPluginConfigurable>true</WidBarPluginConfigurable>
</PropertyGroup>
The SDK build target creates the public widget metadata from these properties.
File drag and drop
Preview and flyout content can use standard WinUI drag and drop:
root.AllowDrop = true;
root.DragOver += (_, args) =>
{
args.AcceptedOperation = DataPackageOperation.Copy;
};
root.Drop += async (_, args) =>
{
if (!args.DataView.Contains(StandardDataFormats.StorageItems))
return;
var items = await args.DataView.GetStorageItemsAsync();
// Process the files here.
};
Call RequestOpenFlyout() from a preview DragOver handler when the final drop
target lives inside the flyout.
Diagnostics
Messages written with Debug.WriteLine or Trace.WriteLine are forwarded to
the WidBar developer console. Enable Developer mode in WidBar settings to view
them.
Exceptions raised by plugin callbacks are also reported there. Release every
timer and event subscription in DisposeAsync() so an instance can be removed
cleanly.
Packaging and publishing
Use the template packaging project to create the MSIX package. The widget is a normal packaged Windows application with an AppExtension declaration.
Build and deploy the package before testing discovery in WidBar. For a Store
release, create the release bundle from the packaging project and submit the
resulting .msixupload file to Partner Center.
Developer guide, templates, and examples: https://github.com/andelby/widbar-widget-template
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0-windows10.0.19041 is compatible. net9.0-windows was computed. net10.0-windows was computed. |
-
net8.0-windows10.0.19041
- Microsoft.WindowsAppSDK (>= 2.2.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
WidBar SDK 2.0 is the first official release of the current widget contract. It includes live WinUI 3 previews, automatic Windows theme support, flyout and settings hosting, per-instance state, and smart stack APIs.