Angular Gauge

View model
using System.Collections.Generic;
using LiveChartsCore;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Extensions;
using LiveChartsCore.VisualElements;
using LiveChartsCore.SkiaSharpView.VisualElements;
using LiveChartsCore.Defaults;
using CommunityToolkit.Mvvm.Input;
using System;
namespace ViewModelsSamples.Pies.AngularGauge;
public partial class ViewModel
{
private readonly Random _random = new();
public IEnumerable<ISeries> Series { get; set; }
public IEnumerable<VisualElement> VisualElements { get; set; }
public NeedleVisual Needle { get; set; }
public ViewModel()
{
var sectionsOuter = 130;
var sectionsWidth = 20;
Needle = new NeedleVisual
{
Value = 45
};
Series = GaugeGenerator.BuildAngularGaugeSections(
new GaugeItem(60, s => SetStyle(sectionsOuter, sectionsWidth, s)),
new GaugeItem(30, s => SetStyle(sectionsOuter, sectionsWidth, s)),
new GaugeItem(10, s => SetStyle(sectionsOuter, sectionsWidth, s)));
VisualElements =
[
new AngularTicksVisual
{
Labeler = value => value.ToString("N1"),
LabelsSize = 16,
LabelsOuterOffset = 15,
OuterOffset = 65,
TicksLength = 20
},
Needle
];
}
[RelayCommand]
public void DoRandomChange()
{
// modifying the Value property updates and animates the chart automatically
Needle.Value = _random.Next(0, 100);
}
private static void SetStyle(
double sectionsOuter, double sectionsWidth, PieSeries<ObservableValue> series)
{
series.OuterRadiusOffset = sectionsOuter;
series.MaxRadialColumnWidth = sectionsWidth;
series.CornerRadius = 0;
}
}
Form code behind
using System.Windows.Forms;
using LiveChartsCore.SkiaSharpView.WinForms;
using ViewModelsSamples.Pies.AngularGauge;
namespace WinFormsSample.Pies.AngularGauge;
public partial class View : UserControl
{
private readonly PieChart pieChart;
public View()
{
InitializeComponent();
Size = new System.Drawing.Size(50, 50);
var viewModel = new ViewModel();
pieChart = new PieChart
{
Series = viewModel.Series,
VisualElements = viewModel.VisualElements,
InitialRotation = -225,
MaxAngle = 270,
MinValue = 0,
MaxValue = 100,
// out of livecharts properties...
Location = new System.Drawing.Point(0, 0),
Size = new System.Drawing.Size(50, 50),
Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom
};
Controls.Add(pieChart);
var b1 = new Button { Text = "Update", Location = new System.Drawing.Point(0, 0) };
b1.Click += (object sender, System.EventArgs e) => viewModel.DoRandomChange();
Controls.Add(b1);
b1.BringToFront();
}
}
Custom needle
You can inherit from NeedleGeometry
to change the aspect of the needle, for example in the next code snippet,
the SmallNeedle
class inherits from NeedleGeometry
, then in the constructor it sets the ScaleTransform
property to 0.6
in the X
and Y
axis, this will make the needle 40% smaller.
using LiveChartsCore.SkiaSharpView.Drawing.Geometries;
namespace ViewModelsSamples.Pies.AngularGauge;
public class SmallNeedle : NeedleGeometry
{
public SmallNeedle()
{
ScaleTransform = new(0.6f, 0.6f);
}
}
Finally we need to use this new needle in our gauge, in the example above change the type NeedleVisual
to NeedleVisual<SmallNeedle>
.
public partial class ViewModel
{
// ...
public NeedleVisual<SmallNeedle> Needle { get; set; }
public ViewModel()
{
Needle = new NeedleVisual<SmallNeedle>
{
Value = 45
};
// ...
}
// ...
}
Run the app again, now the needle is 40% smaller.
You can also override the Draw()
method and use SkiaSharp to create your own needle, in the next snippet,
we are drawing a rectangle using SkiaSharp to represent the needle:
using LiveChartsCore.SkiaSharpView.Drawing;
using LiveChartsCore.SkiaSharpView.Drawing.Geometries;
namespace ViewModelsSamples.Pies.AngularGauge;
public class CustomNeedle : NeedleGeometry
{
public override void Draw(SkiaSharpDrawingContext context)
{
var paint = context.ActiveSkiaPaint;
context.Canvas.DrawRect(X - Width * 0.5f, Y, Width, Radius, paint);
}
}
Finally we need to use this new needle in our gauge:"
public partial class ViewModel
{
// ...
public NeedleVisual<CustomNeedle> Needle { get; set; }
public ViewModel()
{
Needle = new NeedleVisual<CustomNeedle>
{
Value = 45
};
// ...
}
// ...
}
Run the app again, now there is a rectangle as our needle:

You can draw anything with SkiaSharp, this article does not explain how to do it. If you need help, you can see the default NeedleGeometry source code, or you can follow any SkiaSharp guide.