NuGet, mach Diagramm!
Best of NuGet, Teil 2

Das manuelle Programmieren von Diagrammen gehört zu den herausforderndsten Aufgaben, denen man sich im Rahmen der Programmierausbildung stellen kann. Für die meisten gängigen Diagrammtypen stellt jedoch die Verwendung einer etablierten Chartbibliothek einen in der Praxis wesentlich geeigneteren Weg dar, das gewünschten Ergebnis zu erreichen.
Mit ScottPlot steht hierzu ein seit vielen Jahren genutztes Produkt zur Verfügung, das wir uns in den folgenden Schritten näher ansehen wollen. Ziel ist dabei die Realisierung eines Diagramm-Viewers, den wir in einem Folgeartikel mit einer .NET-Mathematikbibliothek verdrahten wollen.
Inbetriebnahme der Arbeitsumgebung
Aufgrund der langen Entwicklungsgeschichte unterstützt das ScottPlot-Entwicklerteam so gut wie jeden GUI-Stack, der im Bereich der .NET-Welt existiert. Es gibt sogar eine Stand-alone-Version für Kommandozeilen-Applikationen, die sich auf die Generierung von Dateien (Stichwort: Versand per E-Mail) spezialisiert hat.
Unsere Beispielapplikation entsteht auf Basis der Vorlage .NET MAUI-App. Der Autor vergibt als Name NMGScottDemo1, als .NET-Version verwenden wir 8.0. Als Nächstes folgt der bekannte Wechsel in die NuGet-Konsole, wo wir das Paket ScottPlot.Maui als zu installieren markieren.
Zu beachten ist, dass es im Fall von populären Paketen mitunter „Trittbrettfahrer“ gibt – Bild 1 zeigt ein Beispiel. Dabei könnte es sich um unschuldige Namenskollisionen handeln; Supply-Chain-Attacken sind allerdings ebenfalls denkbar.

Augen auf beim Paketkauf! (Bild 1)
AutorZu beachten ist, dass NuGet-Pakete nach der Installation mitunter ein wenig Nachkonfiguration brauchen. Im Fall von ScottPlot ist es beispielsweise erforderlich, die Datei MauiProgram.cs zu öffnen und die für die Aktivierung der Bibliothek notwendige Methode zu platzieren:
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseScottPlot()
.ConfigureFonts(fonts =>
Anzeige der ersten Diagramme
Aufgrund möglicher Hakeleien bei der Integration ist es immer empfehlenswert, im ersten Schritt einen Rauchtest durchzuführen. Im Fall einer Diagrammbibliothek bietet sich das Anzeigen eines ersten Charts an. Hierzu gilt es, in die XAML-Datei zu wechseln und dort einen auf die soeben hinzugefügte Bibliothek verweisenden Namespace-Eintrag einzupflegen:
<ContentPage ... xmlns:ScottPlot="clr-namespace:ScottPlot.Maui;assembly=ScottPlot.Maui" x:Class="NMGScottDemo1.MainPage">
Für die eigentliche Anzeige des Diagramms ist dann eine Plot-Klasse erforderlich, die wir anstelle der von Visual Studio automatisch angelegten Struktur in der ContentPage unterbringen:
<ScottPlot:MauiPlot x:Name="MauiPlot1" /> </ContentPage>
Für ein erstes Diagramm ist dann folgender Code zuständig:
public MainPage() {
InitializeComponent();
double[] xs = { 1, 2, 3, 4, 5 };
double[] ys = { 1, 4, 9, 16, 25 };
MauiPlot1.Plot.Add.Scatter(xs, ys);
MauiPlot1.Refresh();
}
Die Realisierung von grafischen Objekten erfolgt durch das Einschreiben von Diagrammen in die als Plot bezeichneten Materobjekte. Wir nutzen hier die Arrays xs und ys, um einen klassischen – und für den Folgeartikel nützlichen – x-y-Plot zu erhalten. Der Aufruf von Refresh sorgt dann für eine Aktualisierung des GUI-Stacks, was zu dem in Bild 2 gezeigten Verhalten führt.

Das Liniendiagramm erscheint auf dem Bildschirm (Bild 2)
AutorDa unsere x-Achse äquidistante Abstände aufweist, können wir stattdessen auch auf einen Signal-Plot setzen. Die Datenreihen erzeugen wir unter Nutzung des im ScottPlot angelegten Generators, was zu folgendem Code führt:
public MainPage() {
InitializeComponent();
MauiPlot1.Plot.Add.Signal(Generate.Sin(50));
MauiPlot1.Plot.Add.Signal(Generate.Cos(50));
MauiPlot1.Refresh();
}
Als Ergebnis erhalten wir das in Bild 3 gezeigte Verhalten.

Oszilloskop lässt grüßen (Bild 3)
AutorFortgeschrittene Diagrammvisualisierungsoptionen
Ein Diagramm ohne Legende und ohne Achsenbeschriftung hat noch wenig Aussagekraft. Doch in dieser Hinsicht lässt sich unser bisher nur aus Sinus und Kosinus bestehendes Diagramm in ScottPlot mit nur wenig Aufwand ergänzen.
Im ersten Schritt machen wir uns die Möglichkeit von Scott Plot zunutze, eingefügte Diagrammobjekte „herauszuschreiben“. Durch Änderung des in LegendText abgelegten Strings können wir die Legendentexte festlegen:
var s1 = MauiPlot1.Plot.Add.Signal(Generate.Sin(50));
s1.LegendText = "Sinus";
var s2 = MauiPlot1.Plot.Add.Signal(Generate.Cos(50));
s2.LegendText = "Cosinus";
Die Anzeige der Legende erfolgt dann erstens durch Aufruf der Methode ShowLegend. Zweitens ist es empfehlenswert, über einige der Hilfseigenschaften die Achsenbeschreibungen anzuliefern:
MauiPlot1.Plot.ShowLegend();
MauiPlot1.Plot.Title("Funktionen!");
MauiPlot1.Plot.XLabel("X-Achse");
MauiPlot1.Plot.YLabel("Y-Achse");
MauiPlot1.Refresh();
}
Wie immer gilt, dass diese Enchillada vor dem letzten Aufruf von Refresh unterzubringen ist. Ergebnis ist dann das in Bild 4 gezeigte Diagramm
Ein weiteres nettes Feature ist die Möglichkeit, Bereiche im Diagramm hervorzuheben. Wir wollen dies mit einem vertikalen Bereich vorführen, der nach folgendem Schema in das Chart wandert:
MauiPlot1.Plot.Add.VerticalSpan(-0.1, 0.1); }

Die „didaktischen Erweiterungen“ verliefen erfolgreich (Bild 4)
Autor
Diese Funktion ist für Go/No-Go-Diagramme geradezu prädestiniert (Bild 5)
AutorWeitere Diagramme in Eigenregie
Die effizienteste Nutzung von Diagrammbibliotheken wie ScottPlot besteht in vielen Fällen darin, im ersten Schritt nach einer den hauseigenen Bedürfnissen entsprechenden Visualisierung zu suchen und diese anschließend an die Gegebenheiten des vorliegenden Programms anzupassen.
Das ScottPlot-Entwicklerteam unterstützt dies über die in Bild 6 auszugsweise gezeigte Diagrammgalerie. Die einzelnen Renderings lassen sich dabei anklicken und offenbaren danach Beispielcode, der die zur Erzeugung der jeweiligen Visualisierung notwendigen Parameter und Details beschreibt.
Histogramm im Eigenbau
ScottPlot unterscheidet sich von klassischen Diagrammbibliotheken insofern, als es im Bereich der Entwicklung der Diagramme einige Soziolekte zur Erweiterung der Funktionsfähigkeit gibt. Ein Klassiker wäre die Erzeugung eines Histogramms durch Ableitung aus einem Balkendiagramm.
Im ersten Schritt ist dabei ein gewöhnliches Balkendiagramm notwendig. Hierzu kommentieren wir den bisher verwendeten Signalcode als Ganzes aus und ersetzen ihn durch die folgenden vier Zeilen:
double[] values = { 5, 10, 7, 13 };
MauiPlot1.Plot.Add.Bars(values);
MauiPlot1.Plot.Axes.Margins(bottom: 0);
MauiPlot1.Refresh();
}
Ergebnis der Programmausführung ist das in der Bild 7 gezeigte Diagramm.
Die Umrüstung auf ein klassisches Histogramm erfolgt dann nach folgendem Schema:

Visuelle Ähnlichkeiten zum Histogramm sind rein zufällig (Bild 7)
Autor
double[] heights = SampleData.MaleHeights();
var hist = ScottPlot.Statistics.Histogram.WithBinCount(20, heights);
var barPlot = MauiPlot1.Plot.Add.Bars(hist.Bins, hist.Counts);
MauiPlot1.Refresh();
}
Zu beachten ist, dass das ScottPlot-Entwicklerteam in der SampleData-Klasse Dutzende von vorgefertigten „Datenquellen“ zur Verfügung stellt. Hier verwenden wir beispielsweise eine Größenverteilung von Männern, die sich für die Generierung von Histogrammen geradezu hervorragend eignet.
Der eigentliche Binning-Algorithmus liegt dann in der Methode WithBinCount. Wichtig ist hier vor allem die übergebene Zahl, die die Anzahl der zu erzeugenden Bins festlegt. Als Ergebnis erhalten wir das in Bild 8 gezeigte Diagramm.
Eine Verbesserung der Darstellung lässt sich dadurch erreichen, dass die Breite der individuellen Balken angepasst wird. Hierzu ist ein kleiner Eingriff in die für die Darstellung verwendeten Elemente erforderlich, was am bequemsten über eine foreach-Schleife realisieren lässt:
double[] heights = SampleData.MaleHeights();
var hist = ScottPlot.Statistics.Histogram.WithBinCount(20, heights);
var barPlot = MauiPlot1.Plot.Add.Bars(hist.Bins, hist.Counts);
foreach (var bar in barPlot.Bars)
{
bar.Size = hist.FirstBinSize * 1;
}
MauiPlot1.Refresh();

Das Histogramm steht bereit (Bild 8)
Autor
Das finale Histogramm (Bild 9)
AutorAls optimiertes Ergebnis erhalten wir das in Bild 9 gezeigte Diagramm.
Fazit
Dass das Kopieren von vorhandenen Lösungen der schnellste Weg zum Lernen ist, wusste man schon in der chinesischen Antike. Mit ScottPlot steht ein leistungsfähiges Werkzeug zur Verfügung, das Entwicklerinnen und Entwicklern das Integrieren hochwertiger Diagramm-Visualisierungen erleichtert. Wer die Bibliothek nicht kennt, läuft leicht Gefahr, sich unnötig viel Arbeit zu machen.