EasyBI.Core 0.1.0-beta.1

This is a prerelease version of EasyBI.Core.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package EasyBI.Core --version 0.1.0-beta.1
                    
NuGet\Install-Package EasyBI.Core -Version 0.1.0-beta.1
                    
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="EasyBI.Core" Version="0.1.0-beta.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EasyBI.Core" Version="0.1.0-beta.1" />
                    
Directory.Packages.props
<PackageReference Include="EasyBI.Core" />
                    
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 EasyBI.Core --version 0.1.0-beta.1
                    
#r "nuget: EasyBI.Core, 0.1.0-beta.1"
                    
#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 EasyBI.Core@0.1.0-beta.1
                    
#: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=EasyBI.Core&version=0.1.0-beta.1&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=EasyBI.Core&version=0.1.0-beta.1&prerelease
                    
Install as a Cake Tool

EasyBI

A self-service BI library for WPF. The developer declares what can be analyzed, end users build their visuals by drag-and-drop, and rendering is delegated to interchangeable connectors (LiveCharts2, OxyPlot, ...).

 Source (IQueryable) ─▶ Semantic model ─▶ AnalyticQuery ─▶ ResultSet ─▶ ChartData ─▶ IVisualRenderer
                         (developer)       (end user)       (engine)     (pivot)      (connector)

Projects

Project Role Dependencies
EasyBI.Abstractions The contract: model, query, ResultSet, VisualDefinition, ReportDefinition none
EasyBI.Core Model builder, query engine over IQueryable (expression trees), pivot, filtering, JSON Abstractions
EasyBI.Wpf IVisualRenderer, EasyBIContext, VisualView, ReportDesigner, FilterBar, built-in KPI and Table renderers Core
EasyBI.Renderers.LiveCharts2 LiveCharts2 connector (bars, lines, pies) Wpf + LiveCharts2
EasyBI.Renderers.OxyPlot OxyPlot connector (bars, lines, pies) Wpf + OxyPlot
samples/EasyBI.Sample Demo: dashboard + designer + renderer switch + JSON save/load
tests/EasyBI.Core.Tests Engine, filtering and serialization tests
tests/EasyBI.Wpf.Tests Designer tests

Installation

dotnet add package EasyBI.Wpf
dotnet add package EasyBI.Renderers.LiveCharts2   # and/or EasyBI.Renderers.OxyPlot

EasyBI.Wpf brings EasyBI.Core and EasyBI.Abstractions. Every public WPF type is available under a single XAML namespace:

xmlns:bi="https://github.com/TheoCvg/EasyBI"

For the WPF developer

var model = SemanticModel.For(dbContext.Sales, "sales", "Sales")
    .Dimension(s => s.Date, "Date")
    .Dimension(s => s.Region, "Region")
    .Dimension(s => s.Product.Category, "Category")
    .Measure(s => s.Amount, "Revenue", format: "#,##0 €")
    .Count("Number of sales");

Context = EasyBIContext.Create()
    .AddModel(model)
    .UseRenderer(new LiveCharts2Renderer())
    .UseRenderer(new OxyPlotRenderer());

With EF Core, prefer a context factory: each query opens its own DbContext, and the visuals of a dashboard run in parallel. On a shared IQueryable (other than LINQ to objects), queries run one after another, because a DbContext does not support concurrent operations.

var model = SemanticModel.For(() => dbFactory.CreateDbContext(), db => db.Sales, "sales", "Sales")
    .Dimension(s => s.Region, "Region") /* ... */;
<bi:ReportDesigner Context="{Binding Context}" />                             
<bi:VisualView Context="{Binding Context}" Definition="{Binding Visual}" />   

Filtering: global filters and cross-filtering

A FilterContext holds the filtering state of a dashboard. Set once on the container (it is an inherited property), it is used by the FilterBar and by every VisualView:

<DockPanel bi:VisualView.FilterContext="{Binding Filters}">
    <bi:FilterBar DockPanel.Dock="Top" Context="{Binding Context}" />
    
</DockPanel>
  • Global filters (slicers): added from the FilterBar, they apply to every visual of the same model and are saved with the report (ReportDefinition.Filters).
  • Cross-filtering: clicking a bar, a point, a slice or a table row filters the other visuals of the same model on the element's dimensions (axis, plus legend for a bar). Clicking the same element again clears the selection. The source visual is not filtered and shows the current selection. Periods (quarter, month...) filter through FilterSpec.Grain.

A connector only has to call request.Select?.Invoke(new CategorySelection(category, series)) on click (or RowSelection for a table): Select is null when interactivity is disabled, for example in the designer preview.

Localization

EasyBI's own texts (designer, filter bar, messages, granularity and aggregation names, blank and boolean values) ship in English and French. The language can change at runtime: designer, filter bar and visuals update immediately.

EasyBILocalization.Culture = CultureInfo.GetCultureInfo("fr-FR"); // null = follow CurrentUICulture

The same culture formats numbers and dates. Your semantic model captions can follow the language too: call Localize with your own resources, and every caption becomes a resource key (a missing key falls back to the caption itself).

var model = SemanticModel.For(db.Sales, "sales", "Sales")
    .Dimension(s => s.Region, "Region")
    .Measure(s => s.Amount, "Revenue")
    .Localize(MyStrings.ResourceManager);

Your own XAML texts can follow it as well with LocalizedStrings and the Localize markup extension:

public static LocalizedStrings Texts { get; } = new(MyStrings.ResourceManager);
<Button Content="{bi:Localize Save, Source={x:Static local:App.Texts}}" />

Visual and report titles are user content: they are stored as typed and not translated.

Writing a connector

A connector implements a single interface. It receives already queried and pivoted data (request.Chart: categories + series) and the raw ResultSet if needed:

public sealed class MyRenderer : IVisualRenderer
{
    public string Name => "MyLib";
    public RendererCapabilities Capabilities { get; } = new(new HashSet<MarkType> { MarkType.Bar });
    public FrameworkElement Render(RenderRequest request) { /* request.Chart.Categories, request.Chart.Series */ }
}

EasyBIContext.ResolveRenderer negotiates capabilities: the active renderer if it supports the visual type, otherwise another plugged-in renderer, otherwise a built-in one. The designer disables the types that no renderer can draw.

Report format (easybi/v1)

{
  "schema": "easybi/v1",
  "title": "Dashboard",
  "visuals": [
    {
      "title": "Revenue by region and channel",
      "model": "sales",
      "mark": "Bar",
      "axis": [ { "field": "Region", "grain": "None" } ],
      "legend": { "field": "Channel", "grain": "None" },
      "values": [ { "measure": "Amount" } ],
      "filters": [ { "field": "Product.Category", "operator": "In", "values": [ "Services" ] } ]
    }
  ],
  "filters": [
    { "model": "sales", "filter": { "field": "Region", "operator": "In", "values": [ "North", null ] } }
  ]
}

null in values means a missing value. EasyBIContext.Validate(report) reports the unknown models and fields of a loaded report.

The same file renders identically with any connector.

Run

dotnet test
dotnet run --project samples/EasyBI.Sample

The demo starts in your system language (English or French) and has a language picker in its toolbar.

Contributing

See AGENTS.md for the code style, language rules and Git workflow.

Known limitations / roadmap

  • Cross-filtering: one selection at a time; the selected element is not yet highlighted in the source chart (a "Sélection : ..." banner shows it).
  • Designer and FilterBar filters: "one of" only, on non-date dimensions; no date ranges.
  • Top applies to aggregated rows, not to categories when a legend is present.
  • Grouping, sorting and Top are pushed down to the provider, and execution is asynchronous when the source implements IAsyncEnumerable (EF Core). EF Core's SQL translation (GroupBy on a composite key, sort on an aggregate, projection to object[]) still has to be validated against a real database.
  • At most 4 grouping dimensions (axis + legend).
  • No dark theme, no free-form dashboard layout.
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on EasyBI.Core:

Package Downloads
EasyBI.Wpf

Self-service BI for WPF: drag-and-drop report designer, visual view, filter bar with cross-filtering, built-in KPI and table renderers, pluggable chart connectors.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.6.0-beta.1 96 10/28/2026
0.5.0-beta.1 90 10/26/2026
0.4.0-beta.1 89 10/21/2026
0.3.0-beta.1 92 10/19/2026
0.2.0-beta.1 84 10/19/2026
0.1.0-beta.1 81 10/16/2026