Skip to content

Visualizing the grid with Avalonia, LINQ, and Reactive Architecture. (Switzerland consumption)

Notifications You must be signed in to change notification settings

DevStackJunior/Real-Time-Load-Analytics-Dashboard

Repository files navigation

📊 Dynamic Energy Load Chart - Avalonia C#

Initial Target Sample Overview :

image

Official Target Sample Overview :

image

🧭 Description

This project implements a graphical visualization application in C# using the Avalonia framework.
The goal is to display an interactive and scalable chart representing the energy load (“Total Load”) on different time scales:

  • Daily view → Dynamic data (real-time API)
  • Monthly/annual view → Historical data imported locally
  • Functional view → Visualization of dynamic mathematical functions
  • Simultaneous display of multiple time series on the same chart

The whole thing is based on LINQ, custom C# extensions, and a clean MVVM architecture.


⚙️ Main features

🔹 1. Daily view (real time)

🔹 2. Monthly/annual view (history)

  • Data loaded from a local CSV/XLSX file
  • Option to switch between Day/Month/Year views
  • Transformed and grouped data (day/month/year)
  • Automatic data consistency check
  • Import error handling (malformed file, missing columns)
  • User error message displayed in the UI
  • Tested with multiple CSV files to validate robustness

🔹 3. Functional view (math functions)

  • A dedicated tab allows you to switch between “Series” mode and “Functions” mode
  • Three built-in mathematical functions:
    • f(x) = x²
    • f(x) = sin(x)
    • f(x) = x * sin(x)
  • Point generation via C# extensions translating functions into delegates (Func<double, double>)
  • Simultaneous graphical visualization of the 3 functions
  • Dynamically adjusted labels, colors, and axes

🧩 Project architecture

📁 Chart_Energy
├── 📁 .vs
│   └── ...                           → Visual Studio configuration and metadata
│
├── 📁 ViewModelsSamples
│   └── 📁 Axes
│       └── 📁 Paging                 → ViewModels for chart paging, scaling, and time-based navigation
│           └── ChartPagingViewModel.cs
│
├── 📁 ViewModels
│   ├── MainWindowViewModel.cs        → Central ViewModel (handles UI state, mode switching, commands)
│   ├── ChartViewModel.cs             → Core chart logic: manages data, axes, and time series collections
│   ├── FunctionViewModel.cs          → Generates and manages mathematical functions (x², sin(x), etc.)
│   ├── ImportViewModel.cs            → Handles CSV/XLSX import workflow, parsing, and error handling
│   └── ApiDataViewModel.cs           → Handles API fetching (HTTP requests, parsing, caching)
│
├── 📁 Views
│   ├── MainWindow.axaml              → Main container window (tabs, chart area, import button, legend)
│   ├── MainWindow.axaml.cs           → Code-behind for interaction logic (navigation, binding setup)
│   ├── ChartView.axaml               → UI for displaying multiple time series on a shared chart
│   ├── ChartView.axaml.cs            → Optional chart-level code-behind (dynamic refresh)
│   ├── FunctionView.axaml            → Function plotting view (switch between series/functions)
│   ├── FunctionView.axaml.cs
│   └── ImportDialog.axaml            → File picker dialog for loading CSV/XLSX files
│
├── 📁 Services
│   ├── 📄 ApiService.cs              → Handles API connection to ENTSO-E (HTTPClient, JSON parsing, async fetch)
│   ├── 📄 CsvDataLoader.cs           → Loads and parses CSV files using CsvHelper
│   ├── 📄 ExcelDataLoader.cs         → Handles XLSX files via ClosedXML
│   ├── 📄 DataCacheService.cs        → Optional local caching for faster reloads / offline mode
│   ├── 📄 DataTransformationService.cs → Centralized LINQ transformations and aggregation logic
│   └── 📄 ErrorHandlerService.cs     → Basic error reporting for import and API operations
│
├── 📁 Extensions
│   ├── EnumerableExtensions.cs       → LINQ helper extensions (SafeAverage, MinMaxBy, etc.)
│   ├── DateTimeExtensions.cs         → TruncateToHour(), GetMonthRange(), etc.
│   ├── FunctionExtensions.cs         → Converts function strings ("x*sin(x)") to delegates
│   └── HttpResponseExtensions.cs     → Simplifies API response validation and deserialization
│
├── 📁 Models
│   ├── LoadRecord.cs                 → Represents one energy load record (Timestamp, Value)
│   ├── ApiLoadResponse.cs            → DTO for API JSON deserialization
│   ├── ChartSeriesModel.cs           → Describes each chart series (label, color, data source)
│   └── ImportResult.cs               → Represents parsed and validated file import
│
├── 📁 Assets
│   ├── sample_day.csv
│   ├── sample_monthly.xlsx
│   ├── sample_yearly.csv
│   └── icons/                        → Optional app icons or chart markers
│
├── 📁 bin
│   └── 📁 Debug
│       └── 📁 net9.0                 → Compiled output
│
├── 📁 obj                            → Build intermediates (auto-generated)
│
├── 📄 App.axaml                      → Global Avalonia app definition (resources, styles, themes)
├── 📄 App.axaml.cs                   → App startup logic (AppBuilder configuration)
├── 📄 Program.cs                     → Application entry point
├── 📄 Chart_Energy.csproj            → Project definition and dependencies
├── 📄 GlobalUsings.cs                → Centralized using directives
├── 📄 app.manifest                   → Windows manifest metadata
├── 📄 README.md                      → English project documentation
└── 📄 Aperçu.md                      → French project documentation

🧠 Technologies used

Component Description
Language C# (.NET 8.0)
UI Framework Avalonia UI
Graphics Library LiveCharts2 for Avalonia
CSV/XLSX management CsvHelper / ClosedXML
Web requests HttpClient (async/await)
LINQ Aggregation, filtering, transformation
C# Extensions Facilitating processing (functions, dates, averages)
Compatibility Classic Windows desktop

🔄 Data import & transformation

Key steps:

  1. Dialog box for selecting a CSV file:
   var dialog = new OpenFileDialog { Filters = { new FileDialogFilter { Name =CSV Files”, Extensions = { “csv” } } } };
   var result = await dialog.ShowAsync(window);
  1. Parsing CSV in memory via CsvHelper

LINQ transformation:

var grouped = records
    .GroupBy(r => r.Timestamp.TruncateToHour())
    .Select(g => new { Time = g.Key, Value = g.Average(x => x.Load) });
  1. Error handling during import
try {
    var data = CsvDataLoader.Load(filePath);
} catch (FormatException ex) {
    ShowError(Import error: malformed file.);
}
  1. Test on multiple CSV files to verify robustness and consistency.

About

Visualizing the grid with Avalonia, LINQ, and Reactive Architecture. (Switzerland consumption)

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages