Plugin.MAUI.GoogleChartsView
2.0.1
dotnet add package Plugin.MAUI.GoogleChartsView --version 2.0.1
NuGet\Install-Package Plugin.MAUI.GoogleChartsView -Version 2.0.1
<PackageReference Include="Plugin.MAUI.GoogleChartsView" Version="2.0.1" />
<PackageVersion Include="Plugin.MAUI.GoogleChartsView" Version="2.0.1" />
<PackageReference Include="Plugin.MAUI.GoogleChartsView" />
paket add Plugin.MAUI.GoogleChartsView --version 2.0.1
#r "nuget: Plugin.MAUI.GoogleChartsView, 2.0.1"
#:package Plugin.MAUI.GoogleChartsView@2.0.1
#addin nuget:?package=Plugin.MAUI.GoogleChartsView&version=2.0.1
#tool nuget:?package=Plugin.MAUI.GoogleChartsView&version=2.0.1
Plugin.MAUI.GoogleChartsView
MAUI.GoogleChartsView is a user-friendly charting control designed for .NET MAUI applications. By harnessing the capabilities of Google Charts, it offers customizable data visualizations to suit a wide range of data types. This library is an ideal choice for developers who aim to create visually engaging and informative charts in their .NET MAUI applications while avoiding the complexities associated with building charting solutions from the ground up.
Note: An internet connection is required to render charts. The Google Charts library is loaded from Google's CDN (per Google's terms it cannot be bundled for offline use); your chart data itself never leaves the device. Loader failures (e.g. offline devices) are reported through the
ChartErrorevent, so you can show a fallback UI or retry.
What's New in v2.0.0
- Events are no longer dropped - callbacks are queued and acknowledged one at a time, so a tap that raises both
clickandselectdelivers both - Incremental updates - changing
DataorOptionsredraws the live chart instead of reloading the page, so the loader isn't re-fetched, animations don't replay and scroll/zoom position survives. NewUpdateChartAsync() - Zoom actually works -
ZoomEnablednow drives the viewport meta and the native WebView (AndroidWebSettings, WKWebView pinch recogniser, WebView2 pinch/zoom settings, including Ctrl+wheel on Windows) - Typed options -
LegendPosition,LegendAlignment,LineCurveType,ChartOrientation,StackMode,SeriesType,TrendlineType; string overloads still work - Richer options -
Series(...),VAxes(...)for dual axes,Trendline(...),Annotations(...),MapsApiKey(...), andHAxis/VAxiswithFormat/LogScale - Fractional axis bounds -
HAxis/VAxistakedouble?(breaking: wasint?) - Richer selection data -
ChartSelectionEventArgs.Valueand.ColumnLabel - Cancellable export -
GetChartImageAsyncaccepts a timeout and aCancellationToken - Clear data errors -
ChartDataBuilder.Build()rejects rows whose cell count doesn't match the column count, naming the row - Leak fix - the auto-refresh timer stops when the view is unloaded and resumes when it returns
- Gallery fixes - Android 21-28 requests storage permission, Apple platforms request add-only photo access, Windows falls back to Pictures for unpackaged apps
RequestChartImageis obsolete; useGetChartImageAsync
What's New in v1.1.0
- Native date support in builders -
DateTime,DateOnly,TimeOnlyvalues are automatically converted to the Google Charts date format - Reliable PNG export - Export uses direct JavaScript evaluation (no more URL-length limits), with correct support detection (corechart types + GeoChart)
- Resize handling - Charts redraw automatically on rotation and window resize
- Offline detection - Loader failures raise
ChartErrorinstead of failing silently - Localization - New
Languageproperty for locale-aware chart formatting - ChartTitle now works - Applied to the chart when options don't already define a title
- Hardened rendering - Chart type validation, batched re-renders, user options are never silently overwritten
Features
- Supports all Google Charts types including Line, Bar, Pie, Area, Sankey, Timeline, Gauge, and more
- Type-safe ChartType enum with automatic package loading
- Fluent API builders for easy data and options construction
- Customizable chart options to fit your design needs
- Seamless integration with .NET MAUI
- Interactive features like tooltips and animations
- Export charts as images (PNG format) on all platforms
- Save charts directly to device gallery (Android, iOS, MacCatalyst, Windows)
- Responsive chart rendering for different screen sizes
- Event-driven architecture for chart interactions
Supported Platforms
- Android 5.0+ (API 21)
- iOS 15.0+
- MacCatalyst 15.0+
- Windows 10.0.17763+
Getting Started
Installation
Install the Plugin.MAUI.GoogleChartsView NuGet package in your .NET MAUI project:
dotnet add package Plugin.MAUI.GoogleChartsView
Usage Examples
1. Basic Chart Setup
Add the GoogleChartsView control to your page:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:charts="clr-namespace:MAUI.GoogleChartsView;assembly=MAUI.GoogleChartsView"
x:Class="MyApp.MainPage">
<StackLayout>
<charts:GoogleChartsView x:Name="MyChart"
WidthRequest="400"
HeightRequest="300"
ChartReady="OnChartReady"
ChartSelected="OnChartSelected"
ChartError="OnChartError" />
<Button Text="Export to Gallery" Clicked="OnExportClicked" />
</StackLayout>
</ContentPage>
2. Configure Chart Data and Options (Using Builders)
using MAUI.GoogleChartsView;
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
SetupChart();
}
private void SetupChart()
{
// Use ChartDataBuilder for easy data construction
var data = ChartDataBuilder.Create()
.AddStringColumn("Year")
.AddNumberColumn("Sales")
.AddNumberColumn("Expenses")
.AddRow("2021", 1000, 400)
.AddRow("2022", 1170, 460)
.AddRow("2023", 660, 1120)
.AddRow("2024", 1030, 540)
.Build();
// Use ChartOptionsBuilder for easy options configuration
var options = ChartOptionsBuilder.Create()
.Title("Company Performance")
.SmoothLines()
.Legend("bottom")
.BackgroundColor("#f5f5f5")
.Colors("#2196F3", "#FF5722")
.HAxis(title: "Year")
.VAxis(title: "Amount")
.Build();
MyChart.Data = data;
MyChart.SetChartType(ChartType.LineChart); // Type-safe!
MyChart.Options = options;
MyChart.EnableAnimation = true;
MyChart.AnimationDuration = 1000;
}
private void OnChartReady(object sender, EventArgs e)
{
Console.WriteLine("Chart is ready!");
}
private void OnChartSelected(object sender, ChartSelectionEventArgs e)
{
Console.WriteLine($"Selected: Row {e.Row}, Column {e.Column}");
}
private void OnChartError(object sender, ChartErrorEventArgs e)
{
Console.WriteLine($"Error: {e.ErrorType} - {e.Message}");
}
private async void OnExportClicked(object sender, EventArgs e)
{
try
{
// Save to device gallery
var path = await ChartImageSaver.SaveToGalleryAsync(
await MyChart.GetChartImageAsync(),
"MyChart.png");
await DisplayAlert("Success", $"Chart saved to: {path}", "OK");
}
catch (Exception ex)
{
await DisplayAlert("Error", ex.Message, "OK");
}
}
}
3. Export Charts as Images
PNG export via getImageURI() is supported for corechart types (Line, Bar, Pie, Area, Column, Scatter, Combo, SteppedArea, Bubble, Histogram, Candlestick) and GeoChart only (Google docs). Wait for the ChartReady event before exporting.
// Method 1: Get image as data URI
var imageDataUri = await myChart.GetChartImageAsync();
// Method 2: Save to specific file path
await myChart.SaveChartImageAsync("/path/to/chart.png");
// Method 3: Save to device gallery (platform-specific)
var savedPath = await ChartImageSaver.SaveToGalleryAsync(imageDataUri, "chart.png");
// Method 4: Get raw bytes for custom handling
byte[] imageBytes = ChartImageSaver.GetImageBytes(imageDataUri);
// Method 5: Get as stream
Stream imageStream = ChartImageSaver.GetImageStream(imageDataUri);
Properties
| Property | Type | Default | Description |
|---|---|---|---|
| ChartTypeName | string | null | Google Charts type as string (LineChart, PieChart, BarChart, etc.). Prefer SetChartType(ChartType) for type safety |
| CurrentChartType | ChartType? | null | Read-only: the enum value set via SetChartType |
| Data | object | null | Chart data in Google Charts DataTable format |
| Options | object | null | Chart configuration options |
| EnableAnimation | bool | true | Apply a startup animation (unless Options already define one) |
| AnimationDuration | int | 1000 | Animation duration in milliseconds |
| ChartTitle | string | null | Chart title (applied unless Options already define a title) |
| RefreshIntervalMinutes | int | 10 | Auto-refresh interval (must be greater than 0) |
| ZoomEnabled | bool | true | Enable/disable zoom functionality |
| AdditionalPackages | string[] | null | Extra Google Charts packages to load when using ChartTypeName |
| Language | string | null | Locale for chart formatting (e.g. "de", "fr", "ja") |
| IsChartReady | bool | false | Read-only: indicates if chart has finished rendering |
Events
| Event | EventArgs | Description |
|---|---|---|
| ChartReady | EventArgs | Fired when chart finishes rendering |
| ChartSelected | ChartSelectionEventArgs | Fired when user selects a chart element |
| ChartClicked | ChartClickEventArgs | Fired when user clicks on chart |
| ChartError | ChartErrorEventArgs | Fired when an error occurs |
| ChartImageReady | ChartImageEventArgs | Fired when image export completes |
Supported Chart Types
Use the ChartType enum for type-safe chart selection with automatic package loading:
// Type-safe chart selection
myChart.SetChartType(ChartType.LineChart);
myChart.SetChartType(ChartType.Sankey); // Auto-loads sankey package
myChart.SetChartType(ChartType.Timeline); // Auto-loads timeline package
CoreChart Package (corechart)
Standard chart types - all loaded with a single package:
| Chart Type | Description |
|---|---|
| LineChart | Line graphs with optional smooth curves |
| AreaChart | Filled area under lines |
| ColumnChart | Vertical bar charts |
| BarChart | Horizontal bar charts |
| PieChart | Pie/donut charts (use PieHole for donut) |
| ScatterChart | X-Y scatter plots |
| ComboChart | Mix of bars and lines |
| SteppedAreaChart | Stepped/staircase area charts |
| BubbleChart | Scatter with bubble sizes |
| Histogram | Distribution frequency charts |
| CandlestickChart | Financial OHLC charts |
Individual Package Chart Types
Each loads its own package automatically:
| Chart Type | Package | Description |
|---|---|---|
| Gauge | gauge | Speedometer-style gauges |
| Sankey | sankey | Flow diagrams showing relationships |
| Table | table | Interactive sortable data tables |
| TreeMap | treemap | Hierarchical data as nested rectangles |
| Calendar | calendar | Heat map calendar visualization |
| Gantt | gantt | Project timeline with dependencies |
| OrgChart | orgchart | Organizational hierarchy diagrams |
| GeoChart | geochart | Geographic data on maps |
| Timeline | timeline | Event timelines |
| WordTree | wordtree | Word relationship trees |
Chart Options Reference
| Option | Description | Supported Types |
|---|---|---|
| title | Chart title displayed above | All |
| curveType | Line curve style ("function" for smooth) | LineChart |
| legend | Legend configuration | All |
| backgroundColor | Chart background color | All |
| colors | Array of series colors | All |
| fontSize | Default font size | All |
| fontName | Default font family | All |
| lineWidth | Line width in pixels | LineChart, AreaChart |
| pointSize | Point diameter in pixels | LineChart, AreaChart |
| hAxis | Horizontal axis configuration | All |
| vAxis | Vertical axis configuration | All |
| chartArea | Drawing area size/position | All |
| tooltip | Tooltip configuration | All |
| animation | Animation settings | All |
| is3D | Enable 3D rendering | PieChart, BarChart |
| pieHole | Donut chart hole size (0-1) | PieChart |
| orientation | Chart orientation | BarChart |
| explorer | Pan/zoom configuration | LineChart, AreaChart |
| trendlines | Trendline configuration | ScatterChart, ColumnChart |
Platform Permissions
Android
Add to AndroidManifest.xml for gallery saving:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
iOS / MacCatalyst
Add to Info.plist for photo library access:
<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app saves chart images to your photo library.</string>
Data Builders
Use the fluent API builders for easy chart construction:
ChartDataBuilder
// Simple usage
var data = ChartDataBuilder.Create()
.AddStringColumn("Category")
.AddNumberColumn("Value")
.AddRow("A", 100)
.AddRow("B", 200)
.Build();
// Dates are converted automatically to the Google Charts format
var series = ChartDataBuilder.Create()
.AddDateColumn("Date")
.AddNumberColumn("Value")
.AddRow(new DateTime(2024, 1, 1), 3)
.AddRow(new DateTime(2024, 1, 2), 7)
.Build();
// With formatted values
var row = new ChartRow()
.AddCell(1000, "$1,000")
.AddCell(2000, "$2,000");
// From collection
var salesData = ChartDataBuilder.Create()
.AddStringColumn("Product")
.AddNumberColumn("Sales")
.AddRows(products, p => new object[] { p.Name, p.Sales })
.Build();
ChartOptionsBuilder
var options = ChartOptionsBuilder.Create()
.Title("Sales Report")
.Subtitle("Q1 2024")
.BackgroundColor("#ffffff")
.Colors("#4285F4", "#EA4335", "#FBBC05", "#34A853")
.FontSize(14)
.FontName("Arial")
.Legend("bottom", "center")
.HAxis(title: "Month", minValue: 0, maxValue: 12)
.VAxis(title: "Revenue ($)")
.SmoothLines() // For line charts
.LineWidth(3)
.PointSize(5)
.PieHole(0.4) // For donut charts
.Is3D() // For 3D pie charts
.Stacked() // For stacked bar/column
.ChartArea("80%", "70%", "10%", "10%")
.Tooltip(showColorCode: true, trigger: "focus")
.Explorer() // Enable pan/zoom
.Build();
Special Package Chart Examples
Some chart types require specific data formats. Here are examples for each:
Gauge Chart
var data = ChartDataBuilder.Create()
.AddStringColumn("Label")
.AddNumberColumn("Value")
.AddRow("Memory", 80)
.AddRow("CPU", 55)
.AddRow("Network", 68)
.Build();
var options = ChartOptionsBuilder.Create()
.Set("width", 400)
.Set("height", 300)
.Set("redFrom", 90)
.Set("redTo", 100)
.Set("yellowFrom", 75)
.Set("yellowTo", 90)
.Set("minorTicks", 5)
.Build();
MyChart.Data = data;
MyChart.SetChartType(ChartType.Gauge);
MyChart.Options = options;
Sankey Diagram
var data = ChartDataBuilder.Create()
.AddStringColumn("From")
.AddStringColumn("To")
.AddNumberColumn("Weight")
.AddRow("A", "X", 5)
.AddRow("A", "Y", 7)
.AddRow("A", "Z", 6)
.AddRow("B", "X", 2)
.AddRow("B", "Y", 9)
.AddRow("B", "Z", 4)
.Build();
var options = ChartOptionsBuilder.Create()
.Set("width", 600)
.Set("height", 400)
.Build();
MyChart.Data = data;
MyChart.SetChartType(ChartType.Sankey);
MyChart.Options = options;
Organization Chart
var data = ChartDataBuilder.Create()
.AddStringColumn("Name")
.AddStringColumn("Manager")
.AddStringColumn("Tooltip")
.AddRow("Mike", "", "The President")
.AddRow("Jim", "Mike", "VP")
.AddRow("Alice", "Mike", "VP")
.AddRow("Bob", "Jim", "Manager")
.AddRow("Carol", "Alice", "Manager")
.Build();
var options = ChartOptionsBuilder.Create()
.Set("allowHtml", true)
.Set("size", "large")
.Build();
MyChart.Data = data;
MyChart.SetChartType(ChartType.OrgChart);
MyChart.Options = options;
TreeMap
var data = ChartDataBuilder.Create()
.AddStringColumn("Location")
.AddStringColumn("Parent")
.AddNumberColumn("Size")
.AddNumberColumn("Color")
.AddRow("Global", null, 0, 0)
.AddRow("Americas", "Global", 0, 0)
.AddRow("Europe", "Global", 0, 0)
.AddRow("USA", "Americas", 52, 31)
.AddRow("Mexico", "Americas", 24, 12)
.AddRow("France", "Europe", 42, -11)
.AddRow("Germany", "Europe", 31, -2)
.Build();
var options = ChartOptionsBuilder.Create()
.Set("minColor", "#f00")
.Set("midColor", "#ddd")
.Set("maxColor", "#0d0")
.Set("headerHeight", 15)
.Set("showScale", true)
.Build();
MyChart.Data = data;
MyChart.SetChartType(ChartType.TreeMap);
MyChart.Options = options;
Table Chart
var data = ChartDataBuilder.Create()
.AddStringColumn("Name")
.AddNumberColumn("Salary")
.AddBooleanColumn("Full Time")
.AddRow("Mike", 10000, true)
.AddRow("Jim", 8000, false)
.AddRow("Alice", 12500, true)
.Build();
var options = ChartOptionsBuilder.Create()
.Set("showRowNumber", true)
.Set("page", "enable")
.Set("pageSize", 10)
.Build();
MyChart.Data = data;
MyChart.SetChartType(ChartType.Table);
MyChart.Options = options;
Calendar Chart (Using Anonymous Object)
Calendar charts require JavaScript Date objects. Use anonymous objects for date handling:
var data = new
{
cols = new object[]
{
new { id = "", label = "Date", type = "date" },
new { id = "", label = "Value", type = "number" }
},
rows = new object[]
{
new { c = new object[] { new { v = "Date(2024, 0, 1)" }, new { v = 3 } } },
new { c = new object[] { new { v = "Date(2024, 0, 2)" }, new { v = 7 } } },
new { c = new object[] { new { v = "Date(2024, 0, 15)" }, new { v = 10 } } },
new { c = new object[] { new { v = "Date(2024, 1, 1)" }, new { v = 5 } } },
new { c = new object[] { new { v = "Date(2024, 1, 14)" }, new { v = 8 } } }
}
};
var options = ChartOptionsBuilder.Create()
.Title("Daily Activity")
.Set("height", 350)
.Set("calendar", new { cellSize = 15 })
.Set("colorAxis", new { minValue = 0, colors = new[] { "#ffffff", "#4285F4" } })
.Build();
MyChart.Data = data;
MyChart.SetChartType(ChartType.Calendar);
MyChart.Options = options;
Gantt Chart (Using Anonymous Object)
Gantt charts require a specific 7-column format with dates:
var data = new
{
cols = new object[]
{
new { id = "Task ID", label = "Task ID", type = "string" },
new { id = "Task Name", label = "Task Name", type = "string" },
new { id = "Start", label = "Start", type = "date" },
new { id = "End", label = "End", type = "date" },
new { id = "Duration", label = "Duration", type = "number" },
new { id = "Percent Complete", label = "Percent Complete", type = "number" },
new { id = "Dependencies", label = "Dependencies", type = "string" }
},
rows = new object[]
{
new { c = new object[] {
new { v = "Research" },
new { v = "Find sources" },
new { v = "Date(2024, 0, 1)" },
new { v = "Date(2024, 0, 5)" },
new { v = (object?)null },
new { v = 100 },
new { v = (object?)null }
}},
new { c = new object[] {
new { v = "Write" },
new { v = "Write paper" },
new { v = (object?)null },
new { v = "Date(2024, 0, 9)" },
new { v = 3 * 24 * 60 * 60 * 1000 }, // 3 days in milliseconds
new { v = 25 },
new { v = "Research" }
}},
new { c = new object[] {
new { v = "Complete" },
new { v = "Hand in paper" },
new { v = (object?)null },
new { v = "Date(2024, 0, 10)" },
new { v = 1 * 24 * 60 * 60 * 1000 },
new { v = 0 },
new { v = "Write" }
}}
}
};
var options = ChartOptionsBuilder.Create()
.Set("height", 300)
.Set("gantt", new
{
trackHeight = 30,
criticalPathEnabled = true,
criticalPathStyle = new { stroke = "#e64a19", strokeWidth = 2 }
})
.Build();
MyChart.Data = data;
MyChart.SetChartType(ChartType.Gantt);
MyChart.Options = options;
Auto-Refresh
// Start auto-refreshing every 5 minutes
myChart.RefreshIntervalMinutes = 5;
myChart.StartAutoRefresh();
// Stop auto-refresh
myChart.StopAutoRefresh();
Resource Cleanup
The control implements IDisposable. For proper cleanup:
// In your page's OnDisappearing or cleanup code
myChart.Dispose();
Contributing
Contributions are always welcome!
License
Plugin.MAUI.GoogleChartsView is licensed under the MIT license.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-android35.0 is compatible. net9.0-browser was computed. net9.0-ios was computed. net9.0-ios18.0 is compatible. net9.0-maccatalyst was computed. net9.0-maccatalyst18.0 is compatible. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net9.0-windows10.0.19041 is compatible. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- Microsoft.Maui.Controls (>= 9.0.60)
-
net9.0-android35.0
- Microsoft.Maui.Controls (>= 9.0.60)
-
net9.0-ios18.0
- Microsoft.Maui.Controls (>= 9.0.60)
-
net9.0-maccatalyst18.0
- Microsoft.Maui.Controls (>= 9.0.60)
-
net9.0-windows10.0.19041
- Microsoft.Maui.Controls (>= 9.0.60)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
v2.0.0:
- BREAKING: HAxis/VAxis bounds are now double? instead of int?, so fractional axis limits are expressible
- BREAKING: RequestChartImage is obsolete; use the awaitable GetChartImageAsync
- Fixed event loss: chart events are queued and acknowledged one at a time, so 'click' and 'select' raised in the same tick both arrive
- Fixed ZoomEnabled being CSS-only; the viewport meta now matches it and the platform WebView is configured directly (Android WebSettings, WKWebView pinch recogniser, WebView2 pinch/zoom settings)
- Fixed the auto-refresh timer outliving the view; it stops on Unloaded and resumes on Loaded
- Fixed empty column id/pattern being sent to Google Charts
- Fixed gallery saving: Android 21-28 now requests storage permission, iOS/MacCatalyst request add-only photo access, Windows falls back to Pictures when StorageLibrary is unavailable (unpackaged apps)
- Added incremental updates: changing Data or Options redraws in place instead of reloading the page, so the loader is not re-fetched and animations do not replay
- Added UpdateChartAsync
- Added ChartSelectionEventArgs.Value and .ColumnLabel
- Added CancellationToken and timeout overloads to GetChartImageAsync/SaveChartImageAsync
- Added typed options: LegendPosition, LegendAlignment, LineCurveType, ChartOrientation, StackMode, SeriesType, TrendlineType
- Added Series, VAxes (dual axis), Trendline, Annotations and MapsApiKey option builders
- Added row/column arity validation in ChartDataBuilder.Build() with an actionable message
- Added a unit test project covering builders, chart-type metadata and data-URI decoding; tests now gate publishing
v1.1.0:
- Fixed DateTime/DateOnly/TimeOnly serialization to Google Charts "Date(...)" format in ChartDataBuilder
- Fixed image export support detection (getImageURI only supports corechart types and GeoChart)
- Fixed event handler leaks in GetChartImageAsync; export now uses direct JavaScript evaluation (no URL-length limits)
- Fixed ChartTitle and EnableAnimation silently overwriting user-supplied options
- Added chart redraw on WebView resize/rotation
- Added Google Charts loader failure detection (offline scenarios raise ChartError)
- Added Language property for localized chart formatting
- Added chart type name validation (prevents script injection)
- Batched property changes into a single render
- Accept iOS 14+ "Limited" photo library permission when saving to gallery
- Enabled SourceLink, deterministic builds, symbol packages and XML documentation