PeterSpoenemann.HelpService 0.7.0

dotnet add package PeterSpoenemann.HelpService --version 0.7.0
                    
NuGet\Install-Package PeterSpoenemann.HelpService -Version 0.7.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="PeterSpoenemann.HelpService" Version="0.7.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PeterSpoenemann.HelpService" Version="0.7.0" />
                    
Directory.Packages.props
<PackageReference Include="PeterSpoenemann.HelpService" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add PeterSpoenemann.HelpService --version 0.7.0
                    
#r "nuget: PeterSpoenemann.HelpService, 0.7.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package PeterSpoenemann.HelpService@0.7.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=PeterSpoenemann.HelpService&version=0.7.0
                    
Install as a Cake Addin
#tool nuget:?package=PeterSpoenemann.HelpService&version=0.7.0
                    
Install as a Cake Tool

PeterSpoenemann.HelpService

Build and test NuGet

PeterSpoenemann.HelpService stellt wiederverwendbare Hilfekomponenten für WPF und Avalonia bereit. Sie lesen Markdown-Themen mit !include-Unterstützung, rendern das aktive Thema mit Markdig als statisches HTML und zeigen es in einem Hilfefenster an. Beide UI-Pakete bieten dieselben Interfaces und Funktionen: Inhaltsverzeichnis, Volltextsuche, Sprach- und Themewechsel sowie Zurück-/Vorwärts-Navigation.

Der plattformneutrale Kern liegt im separaten Assembly und NuGet-Paket PeterSpoenemann.HelpService.Core. Er enthält keine WPF- oder WebView2-Abhängigkeit und kann dieselben Hilfequellen beispielsweise für ASP.NET-Core- oder andere Weboberflächen laden.

Voraussetzungen

  • Für PeterSpoenemann.HelpService.Core: .NET 10
  • Für PeterSpoenemann.HelpService: Windows und eine WPF-Anwendung auf .NET 10 sowie die installierte Microsoft Edge WebView2 Runtime
  • Für PeterSpoenemann.HelpService.Avalonia: eine Avalonia-12-Desktop-Anwendung auf .NET 10. Unter Windows wird WebView2 verwendet, unter macOS WKWebView und unter Linux WPE WebKit beziehungsweise WebKitGTK. Die Linux-Pakete sind in der Avalonia-WebView-Dokumentation aufgeführt.

Unter Windows benötigt der NativeWebView-Host ein Anwendungsmanifest mit einem supportedOS-Eintrag. Das übliche Avalonia-Desktop-Template bringt dieses Manifest bereits mit. Bei manuell angelegten Projekten muss es wie im Avalonia-Sample über <ApplicationManifest>app.manifest</ApplicationManifest> eingebunden werden.

Installation

Nach der Veröffentlichung auf NuGet.org:

dotnet add package PeterSpoenemann.HelpService

Für Avalonia-Anwendungen wird stattdessen das Avalonia-Paket installiert:

dotnet add package PeterSpoenemann.HelpService.Avalonia

Für eine Oberfläche ohne WPF kann ausschließlich der Kern installiert werden:

dotnet add package PeterSpoenemann.HelpService.Core

Die beiden UI-Pakete referenzieren das Core-Paket automatisch. Eine Anwendung installiert entweder das WPF- oder das Avalonia-Paket; eine zusätzliche Core-Referenz ist nicht erforderlich.

Plattformneutralen Core verwenden

HelpContentProvider lädt die Themen und liefert mit GetAllTopics() die stabil sortierten Daten für ein Inhaltsverzeichnis. MarkdownHelpDocumentBuilder erzeugt aus dem ausgewählten Thema ein vollständiges HTML-Dokument. Beide APIs verwenden dieselben Namespaces wie im WPF-Paket:

using PeterSpoenemann.HelpService;
using PeterSpoenemann.HelpService.Services;

var content = new HelpContentProvider("Help/ContextHelp.en.md", HelpLanguageCodes.English);
var renderer = new MarkdownHelpDocumentBuilder();

var tableOfContents = content.GetAllTopics();
var topic = content.GetTopic("settings");
var html = renderer.BuildHtml(topic.Markdown, HelpLanguageCodes.English);

tableOfContents enthält pro Thema ID, Titel, Markdown-Inhalt und Gruppenname. Eine Weboberfläche kann daraus Navigation und Suche aufbauen und html direkt in ihrer Inhaltsansicht ausgeben. Für Anwendungen mit Logging steht zusätzlich der bisherige Konstruktor mit ILogger<HelpContentProvider> zur Verfügung.

Lokale Bilder sollten immer über den HelpContentProvider geladen werden, wie im Beispiel oben. Er löst ihre relativen Pfade auf und bettet die Dateien als Data-URI in das Themen-Markdown ein. Ein direkt mit beliebigem Markdown aufgerufener MarkdownHelpDocumentBuilder liest dagegen keine lokalen Dateien; absolute lokale, UNC- und file:-Bildpfade werden nicht übernommen. Wer den Builder ohne HelpContentProvider verwendet, muss lokale Bilder daher selbst als Data-URI bereitstellen.

HTML-Theme auswählen

MarkdownHelpDocumentBuilder bettet Basis und Theme vollständig in das erzeugte HTML ein. Neben dem bisherigen hellen Standard stehen ein dunkles und ein systemabhängiges Theme zur Verfügung:

var light = new MarkdownHelpDocumentBuilder();
var dark = new MarkdownHelpDocumentBuilder(HelpDocumentTheme.Dark);
var system = new MarkdownHelpDocumentBuilder(HelpDocumentTheme.System);

Zusätzliche CSS-Regeln werden nach dem Theme eingebettet und können dessen CSS-Variablen oder Regeln überschreiben:

var customCss = File.ReadAllText("Help/my-theme.css");
var custom = new MarkdownHelpDocumentBuilder(HelpDocumentTheme.Dark, customCss);

Das HTML benötigt dadurch auch mit eigenem Theme keine externe CSS-Datei zur Laufzeit.

Einbindung

Das WPF-Anwendungsprojekt referenziert PeterSpoenemann.HelpService und registriert die Dienste im DI-Container:

services.AddPeterSpoenemannHelpService(options =>
{
    options.RootHelpFile = Path.Combine("Help", "ContextHelp.de.md");
    options.ApplicationName = "MeineAnwendung";
    options.Theme = HelpDocumentTheme.System;
    options.AdditionalStyleSheetPath = Path.Combine("Help", "my-theme.css");
});

Ein Avalonia-Projekt verwendet nach der Installation von PeterSpoenemann.HelpService.Avalonia dieselbe Registrierung. Auch die konsumierenden Interfaces und der Aufruf bleiben gleich; nur der optionale Owner ist dort ein Avalonia.Controls.Window statt eines WPF-Fensters:

using PeterSpoenemann.HelpService.Services;

var helpService = serviceProvider.GetRequiredService<IContextHelpService>();
helpService.ShowHelp("settings", mainWindow);

Die bisherige Eigenschaft RootHelpFile bleibt vollständig unterstützt und konfiguriert die deutsche Hilfe. Deutsch (de) ist die Standardsprache.

Theme unterstützt Light, Dark und System; ohne Konfiguration bleibt die bisherige helle Darstellung erhalten. AdditionalStyleSheetPath ist optional und wird bei relativen Pfaden gegen AppContext.BaseDirectory aufgelöst. Die CSS-Datei muss daher wie die Markdown-Hilfe in die Ausgabe der Anwendung kopiert werden. Ihre Regeln werden direkt in das vom Core erzeugte HTML eingebettet.

Das Theme kann außerdem zur Laufzeit umgeschaltet werden. Ein bereits geöffnetes Hilfefenster wird dabei automatisch neu gerendert:

var themeService = serviceProvider.GetRequiredService<IHelpThemeService>();
themeService.SetTheme(HelpDocumentTheme.Dark);

Das Sample verbindet diese API mit der Auswahl „System“, „Hell“ und „Dunkel“ auf der Registerkarte „Einstellungen“.

Vollständige HTML-Hilfeseite erzeugen

Über IHelpPageBuilder kann der Core alle geladenen Themen zu einer eigenständigen HTML-Seite zusammenfassen. Sie enthält ein gruppiertes Inhaltsverzeichnis und einen Abschnitt pro Thema:

var html = pageBuilder.BuildPageHtml(
    contentProvider.GetAllTopics(),
    languageService.CurrentLanguage,
    "Hilfe zu meiner Anwendung");

File.WriteAllText("help.html", html);

Links wie [Auswertung](topic:reports) werden dabei in interne Sprungmarken umgewandelt. Auch Verweise auf Überschriften wie topic:reports#details und lokale Links wie #details bleiben funktionsfähig. Sämtliche Styles und lokalen Bilder sind in der HTML-Datei eingebettet. Das Sample demonstriert den Export über die Schaltfläche „HTML anzeigen“.

Mehrsprachige Hilfe

Für Deutsch, Englisch und Polnisch werden mehrere Wurzeldateien nach Sprachcode registriert:

services.AddPeterSpoenemannHelpService(options =>
{
    options.RootHelpFiles[HelpLanguageCodes.German] =
        Path.Combine("Help", "ContextHelp.de.md");
    options.RootHelpFiles[HelpLanguageCodes.English] =
        Path.Combine("Help", "ContextHelp.en.md");
    options.RootHelpFiles[HelpLanguageCodes.Polish] =
        Path.Combine("Help", "ContextHelp.pl.md");
    options.Language = HelpLanguageCodes.German;
    options.ApplicationName = "MeineAnwendung";
});

Die Sprache kann anschließend ohne Neustart gewechselt werden. Ein bereits geöffnetes Hilfefenster aktualisiert dabei Oberfläche, Inhaltsverzeichnis und aktives Hilfethema:

var languageService = serviceProvider.GetRequiredService<IHelpLanguageService>();

languageService.SetLanguage(HelpLanguageCodes.English);
languageService.SetLanguage(HelpLanguageCodes.Polish);
languageService.SetLanguage(HelpLanguageCodes.German);

IHelpLanguageService.CurrentLanguage enthält die aktive Sprache und SupportedLanguages die tatsächlich konfigurierten Sprachen. Über LanguageChanged kann die einbindende Anwendung ihre eigene Oberfläche gleichzeitig aktualisieren.

Relative Wurzelpfade werden gegen AppContext.BaseDirectory aufgelöst. Die Anwendung muss ihre Hilfequellen in die Ausgabe kopieren, beispielsweise:

<ItemGroup>
  <None Update="Help\**\*">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </None>
</ItemGroup>

Anwendungscode verwendet IContextHelpService.ShowHelp(topicId, owner) zum Öffnen und IHelpContentProvider.HasTopic(topicId) zum Ein-/Ausblenden kontextbezogener Hilfe-Schaltflächen. F1 und die konkrete Gestaltung der Hilfe-Schaltfläche bleiben Aufgabe der einbindenden Anwendung.

Syntax der Programmhilfe

Die Hilfetexte werden mit Markdig und dessen UseAdvancedExtensions()-Pipeline in HTML umgewandelt. Damit stehen CommonMark und die unten beschriebenen erweiterten Markdown-Elemente zur Verfügung. Eingebettetes Roh-HTML ist aus Sicherheitsgründen deaktiviert und wird als Text angezeigt.

Themen und Inhaltsverzeichnis

Die Wurzeldatei ist ContextHelp.de.md. Sie enthält ausschließlich !include-Zeilen, eine je Themendatei unter Topics/. Jedes eigentliche Hilfethema beginnt mit einer Themen-ID und einem Titel:

# collection | Sammlung

Eine Themendatei kann mehrere Themen enthalten (mehrere # id | Titel-Überschriften hintereinander). Diese Überschrift ist Metadaten-Syntax der Anwendung: Sie bestimmt Themen-ID und Navigationstitel und wird nicht an Markdig übergeben. Inhaltliche Überschriften innerhalb eines Themas beginnen daher mit ##.

Die Themen-ID entspricht üblicherweise einem Navigationseintrag, einer Seite oder einem Dialog der einbindenden Anwendung und wird dort an ShowHelp übergeben.

Verweise auf andere Themen

Ein Verweis auf ein anderes Thema (z. B. im Abschnitt "Siehe auch") wird als normaler Markdown-Link mit dem Schema topic: geschrieben:

Siehe [Sammlung](topic:collection).

Der topic:-Präfix ist keine echte URL, sondern wird von WebView2Html (Behaviors) über NavigationStarting abgefangen, bevor Chromium versucht, sie aufzulösen: Ein Klick wechselt im selben Hilfefenster direkt zum angegebenen Thema. Benutzerinitiierte externe http(s)-Links werden im Standardbrowser geöffnet. Andere URL-Schemata werden vom WPF-Hilfefenster nicht geöffnet.

Markdown-Syntax

Die wichtigsten unterstützten Elemente sind:

Normaler Absatz mit **fettem**, *kursivem* und ***fett-kursivem*** Text.
Auch ~~durchgestrichener~~ Text und `Quelltext` werden von Markdig gerendert.

## Abschnitt {#stabile-abschnitts-id}

- Erster Punkt
- Zweiter Punkt

- [x] Erledigter Punkt
- [ ] Offener Punkt

1. Erster Schritt
2. Zweiter Schritt

| Spalte A | Spalte B |
|----------|----------|
| Wert 1   | Wert 2   |

Begriff
:   Eine Definition in einer Definitionsliste.

Ein Text mit Fußnote.[^hinweis]

[^hinweis]: Der zugehörige Fußnotentext.

Eine normale URL wird automatisch verlinkt: https://example.org

> Ein normales Zitat bleibt ein normales Zitat.

> [!TIP]
> Ein hervorgehobener Hinweis mit **Formatierung**.

> [!WARNING]
> Ein hervorgehobener Hinweis auf tatsächliches Risiko, z. B. Datenverlust oder einen irreführenden Scan-Stand.

![Beschreibung](images/beispiel.png)

!include ../Shared/weiterer-text.md
!include <../Shared/datei mit leerzeichen.md>

Markdig unterstützt die Alert-Typen NOTE, TIP, IMPORTANT, WARNING und CAUTION. Für Hinweise und Risiken sollen bevorzugt TIP beziehungsweise WARNING verwendet werden.

Überschriften erhalten durch Markdig automatisch stabile HTML-IDs. Mit {#eigene-id} kann eine ID explizit festgelegt werden. Darüber hinaus aktiviert die Pipeline unter anderem Aufgabenlisten, Definitionslisten, Fußnoten, automatische Links, Pipe- und Grid-Tabellen sowie zusätzliche Hervorhebungen.

Anwendungsspezifische Erweiterungen

!include und die Themenüberschrift # id | Titel sind keine Markdig-Syntax, sondern werden vor dem Markdown-Rendering vom HelpContentProvider verarbeitet. Markdig selbst bietet keine Dateieinbindung oder Verwaltung anwendungsspezifischer Themen-IDs.

Include- und lokale Bildpfade müssen relativ zu der Markdown-Datei angegeben werden, in der sie stehen. Absolute Pfade, laufwerksbezogene Pfade, UNC-Pfade und file:-URLs sind dafür nicht zulässig. Auch verschachtelte Includes und ..-Segmente sind möglich, solange das aufgelöste Ziel innerhalb des Ordners der jeweiligen ContextHelp*.md-Wurzeldatei bleibt. Daher funktionieren beispielsweise !include ../Shared/text.md oder ![Bild](../Images/bild.png), wenn Shared beziehungsweise Images noch innerhalb dieses Ordners liegen.

Der HelpContentProvider liest zulässige lokale Bilder beim Laden und schreibt sie als Data-URI in das Themen-Markdown. Dadurch enthalten BuildHtml und BuildPageHtml bei der üblichen Kombination aus Provider und Builder weiterhin vollständige lokale Bilder. Fehlt eine Bilddatei, bleibt der relative Markdown-Verweis erhalten und der Browser zeigt gegebenenfalls den Alternativtext an. Externe Bild-URLs und bereits vorhandene Data-URIs werden unverändert weitergegeben.

Ordnerstruktur

Help/
    ContextHelp.de.md   -- deutsche !include-Liste
    ContextHelp.en.md   -- englische !include-Liste
    ContextHelp.pl.md   -- polnische !include-Liste
    Topics/
        Start.md
        Einstellungen.md

Für Inhalte, die von mehreren Themen gemeinsam genutzt werden (z. B. ein Glossar oder eine Fehlerbehebungs-Tabelle), kann ein Shared/-Unterordner angelegt und per !include in die betroffenen Themendateien eingebunden werden, statt Inhalte zu duplizieren.

Fehlertolerantes Laden

Jede !include-Zeile der Wurzeldatei bildet eine eigene Fehlergrenze. Schlägt eine Themendatei fehl (fehlende Datei, zirkuläres Include, Pfad außerhalb von Help/, ungültige Themenüberschrift, doppelte Themen-ID), werden nur deren Themen übersprungen - alle anderen Themendateien bleiben vollständig verfügbar. Der Fehler wird mit Datei- und Zeilenangabe protokolliert (HelpContentProvider, Anwendungsprotokoll).

Eine Themen-ID, für die zur Laufzeit kein passender Eintrag existiert (z. B. wegen eines fehlgeschlagenen Includes oder eines fehlenden Themas), zeigt einen generischen Hinweistext statt eines Fehlers. Der Hilfe-Button in der Anwendung wird für eine Seite ohne hinterlegtes Thema ausgeblendet (IHelpContentProvider.HasTopic).

Lokal bauen und testen

Benötigt wird das .NET 10 SDK:

dotnet restore
dotnet build --configuration Release --no-restore
dotnet test --configuration Release --no-build
dotnet pack src/HelpService.Core/PeterSpoenemann.HelpService.Core.csproj --configuration Release --no-build --output artifacts
dotnet pack src/HelpService/PeterSpoenemann.HelpService.csproj --configuration Release --no-build --output artifacts
dotnet pack src/HelpService.Avalonia/PeterSpoenemann.HelpService.Avalonia.csproj --configuration Release --no-build --output artifacts

Die erzeugten .nupkg- und .snupkg-Dateien liegen danach in artifacts.

Software Bill of Materials (SBOM)

Jedes über einen Release-Tag veröffentlichte NuGet-Paket enthält eine SPDX-2.2-JSON-SBOM unter sbom/manifest.spdx.json. Dieselbe SBOM wird zusätzlich als <PackageId>.<Version>.spdx.json am GitHub-Release bereitgestellt.

Für die lokale SBOM-Erzeugung werden zusätzlich die .NET-8-Laufzeit und das festgepinnte Repository-Tool benötigt:

dotnet tool restore
$version = "0.7.0"
./build/Pack-WithSbom.ps1 -Project src/HelpService.Core/PeterSpoenemann.HelpService.Core.csproj -PackageId PeterSpoenemann.HelpService.Core -Version $version
./build/Pack-WithSbom.ps1 -Project src/HelpService/PeterSpoenemann.HelpService.csproj -PackageId PeterSpoenemann.HelpService -Version $version
./build/Pack-WithSbom.ps1 -Project src/HelpService.Avalonia/PeterSpoenemann.HelpService.Avalonia.csproj -PackageId PeterSpoenemann.HelpService.Avalonia -Version $version

Sample-Anwendung

Unter samples/PeterSpoenemann.HelpService.Sample liegt eine kleine WPF-Anwendung mit zwei Registerkarten und kontextsensitiver Hilfe. Die aktive Hilfeseite wird über die Schaltfläche am unteren Fensterrand oder mit F1 geöffnet. Über die Sprachauswahl kann die komplette Sample-Oberfläche einschließlich eines bereits geöffneten Hilfefensters zur Laufzeit zwischen Deutsch, Englisch und Polnisch wechseln.

dotnet run --project samples/PeterSpoenemann.HelpService.Sample/PeterSpoenemann.HelpService.Sample.csproj

Das entsprechende Avalonia-Desktop-Sample liegt unter samples/PeterSpoenemann.HelpService.Avalonia.Sample. Es verwendet dieselben Hilfedateien und demonstriert ebenfalls F1, kontextsensitive Themen, Sprachwechsel und Themewechsel. Die Farbschema-Auswahl schaltet dabei sowohl das Avalonia-App-Theme als auch das Theme des geöffneten Hilfefensters um:

dotnet run --project samples/PeterSpoenemann.HelpService.Avalonia.Sample/PeterSpoenemann.HelpService.Avalonia.Sample.csproj

VS-Code-Vorschau

Unter vscode-extension liegt eine passende VS-Code-Extension. Ihre Vorschau verwendet den .NET-Core dieses Projekts und zeigt daher !include, Themenüberschriften, relative Bilder sowie die Markdig-Advanced-Extensions genauso wie die Anwendung an. Eine geöffnete ContextHelp*.md-Datei oder eine von ihr eingebundene Themendatei kann über HelpService: Vorschau öffnen angezeigt werden. Bau- und Installationshinweise stehen in der Extension-Dokumentation.

Ein Tooltip zeigt an jedem gerenderten Markdown-Block die ursprüngliche Datei und Zeile an. Über das Kontextmenü HelpService: Quelldatei öffnen springt VS Code direkt zu dieser Stelle; bei eingebundenem Inhalt wird die tatsächliche !include-Datei geöffnet.

Die jeweils aktuelle fertige Extension kann direkt bei GitHub heruntergeladen werden:

PeterSpoenemann.HelpService.Preview.vsix herunterladen

Danach lässt sie sich über die VS-Code-Oberfläche oder auf der Kommandozeile installieren:

code --install-extension .\PeterSpoenemann.HelpService.Preview.vsix

Lizenz

Dieses Projekt steht unter der MIT-Lizenz. Copyright © 2026 Peter Spönemann.

Product Compatible and additional computed target framework versions.
.NET net10.0-windows7.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.7.0 85 9/1/2026
0.6.2 93 8/31/2026
0.6.1 100 8/27/2026
0.6.0 106 8/10/2026
0.5.0 85 8/10/2026
0.4.0 99 8/10/2026
0.3.0 97 8/9/2026
0.2.0 97 8/9/2026
0.1.0 93 8/9/2026