Changelog¶
Every version, with its breaking changes. EasyBI follows Semantic Versioning: while in 0.x,
breaking changes bump the minor version. The report format (easybi/v1) stays backward compatible: a newer version
opens older reports, and a report using a newer feature cannot be opened by an older version.
0.6.0-beta.1 — 2026-10-28¶
Added¶
- .NET Framework and .NET Standard: the WPF packages (
EasyBI.Wpf, renderers, themes) also target .NET Framework 4.6.2, andEasyBI.AbstractionsandEasyBI.Coretarget .NET Standard 2.0, besides .NET 8. On these older targets, they depend on Microsoft's packages that bring the newer APIs (System.Text.Json,Microsoft.Bcl.AsyncInterfaces,Microsoft.Bcl.HashCode,System.ValueTuple) and onPortable.System.DateTimeOnlyforDateOnly; on .NET 8 they have no new dependency. EF Core 8 needs .NET 8: on .NET Framework, a model runs over anotherIQueryable(in memory, EF Core 3.1...) (#76). - Data sources at the level of the visual: a visual asks its model for its data (
ISemanticModel.GetDataAsync, aVisualDataRequestin, aVisualDataout) rather than running queries, so that a model can answer it from anywhere (a server, a cache...).QuerySemanticModelis the base of models that runAnalyticQuerys, from which EasyBI composes comparisons with a year earlier, year-to-date totals and matrices;QueryableSemanticModel<T>derives from it.VisualPipeline.Preparedraws data obtained otherwise (#77). - Data format for remote sources:
DataSerializerwrites and reads, as transport-neutral JSON, what travels between an application and a data source it reaches remotely: theVisualDataRequestof a visual, itsVisualData, a model'sModelMetadataand the distinct values of a dimension, with dates, date periods and numbers keeping their type. The sample gets the results of its visuals from an ASP.NET Core server (samples/EasyBI.Sample.Server).ModelMetadata.DimensionsandMeasuresare not serialized (#78). - Value filters like Excel: every value checked at first, a (Select all) box checked, unchecked or partly checked, (Select all search results) and Add current selection to filter while searching. Lists of thousands of values (suppliers...) open and search without delay, and checking them all changes the filter once (#80).
- Long lists of values: a filter lists up to 10,000 values of a dimension instead of 1,000, says when there are
more, and then searches them in the model (
DistinctValuesRequest.Search), translated to SQL by EF Core. The sample has 2,500 customers to filter on (#80). - Variables, written as formulas in the formula editor (
VariableFormula): parameters (10 BETWEEN 3 AND 25, a slider;"Web" IN ("Web"; "Store"), a list; a text, a date, yes/no), sets of a dimension's values (SELECT TOP [@N] [Customer] WHERE [Region] = "North" ORDER BY [Revenue] DESC, conditions on dimensions keeping rows and on measures keeping values;SELECT [Customer] IN (...)) and values computed once (AVERAGE([Revenue]), or by a dimension:MAX([Revenue] BY [Customer])), saved with the report (ReportDefinition.Variables) with the values the end user gave. Visuals use them in their Top (VisualDefinition.TopVariable), their formulas ([@Rate]), their titles and texts ({N}), and sets dragged onto Filters (their values) or onto Axis and Legend (the set's values and the others,FieldRef.Set); dragged onto a dashboard, a variable shows its control or its values, and a set filters or groups the visual it is dropped on. The newVariablevisual type (VariableView) shows a parameter's control, a computed value or a set's values. Models never see variables:VariableContext(EasyBIContext.Variables) replaces them before asking for data, inside theIQueryable. See Variables (#81).
Fixed¶
- Designer: typing the name or the formula of a calculated measure no longer freezes an application being debugged; checking a formula throws no exception anymore, where it threw one per key typed (#79).
Breaking changes¶
FilterContext.SetFilterkeeps a filterInwithout values, which keeps no row (every value unchecked), instead of removing it; a filterNotInwithout values is still removed. A value filter is saved as the shorter list of values,InorNotIn, whatever operator it was created with (#80).ISemanticModel.GetDistinctValuesAsync(string field)becomesGetDistinctValuesAsync(DistinctValuesRequest request)and returnsDistinctValues(the values and whether there are more): a model gives at mostrequest.Limitvalues, those containingrequest.Searchfor a dimension of texts when it is given.DataSerializer.SerializeValuesbecomesSerialize(DistinctValues),DeserializeValuesreturnsDistinctValues, andSerialize(DistinctValuesRequest)/DeserializeValuesRequestcarry the request (#80).ISemanticModel.ExecuteAsync(AnalyticQuery)is replaced byGetDataAsync(VisualDataRequest). A model that runs queries derives fromQuerySemanticModeland overridesExecuteAsyncas before (withoverride); code that queried a model directly callsExecuteAsyncon aQuerySemanticModel(QueryableSemanticModel<T>is one), orGetDataAsync.TimeCalculations.ExecuteWithTimeAsyncandMatrixBuilder.ExecuteAsynctake aQuerySemanticModel(#77).- Sets of the public API are
IReadOnlyCollection<T>instead ofIReadOnlySet<T>, which .NET Standard 2.0 and .NET Framework lack:RendererCapabilities.Types,VisualPipeline.TypesOf,DashboardLayoutEngine.Extract,MaterialDesignTheme.KeptKeysandWpfUiTheme.KeptKeys. Code passing aHashSet<T>compiles as before; code calling set methods (IsSubsetOf...) on them uses LINQ instead (#76). IDropHandler.RefusalReasonhas no default implementation anymore (.NET Framework does not support them): a handler that does not explain its refusals returnsnull(#76).
0.5.0-beta.1 — 2026-10-26¶
Added¶
- Cross-filtering: several selections with Ctrl+click, highlighted in their visual (#41).
- Numeric filters: number dimensions and the measures of a visual compared with numbers (≥, <, between...) (#42).
- Matrix crossing rows with columns, with totals at every level (#43).
- Conditional formatting: rules, color scales, data bars and icons on the values of a measure (#44); chart points colored by them, and the zones of rules shaded (#45).
- Donut, gauge and waterfall visual types (#46).
- Tooltips customized by the end user (extra measures, template) and the developer (
EasyBIContext.TooltipOpening) (#47). - Legends: position chosen per visual, long legends paged (#48).
- Several axis fields shown as groups, and dimension values relabeled per visual (#50).
- Formulas with dimensions:
SUM,AVERAGE,MIN,MAX,COUNT,DISTINCTCOUNTandIF, with conditions (SUM([Revenue]; [Region] = "North")) (#53). - Measures declared in code editable in the application:
QueryableSemanticModel.Formula(...), and any model measure redefined in a report, with Restore (#54). - Redesigned calculated measure editor: colored formula, located problems, smart suggestions, catalog in tabs, operator keypad (#55).
- Measures used in other formulas: a calculated measure can use the report's other measures; loops are refused (#56).
- This documentation site, with a version per release.
- Designer rules: every change of the visual being designed passes the designer's
Rules, which look at the change (VisualChange:Changes(v => ...),FieldsChanged) and refuse it with a message; what they would refuse is shown unavailable beforehand. Also declared as behaviors:LockVisualTypeBehavior,LockFieldsBehavior,ReadOnlyDesignerBehavior, or one of the application's derived fromDesignerRuleBehavior(#65). - Visual types described by their definition:
VisualTypeDefinitiongives a type's name, gallery section, wells (used, number of fields, name), tooltips, format and rules, andVisualTypeCatalogholds EasyBI's; the designer, the validation and the fields added to a visual follow it. The designer refuses a second category on a pie or a donut (#59). - Custom visual types: an application declares its own types (
EasyBIContext.AddVisualType, or a renderer'sRendererCapabilities.VisualTypes), with their wells, settings (VisualTypeDefinition.Options, read withGetTypeOption) and rules, and an icon by key ({bi:VisualTypeIconKey company.type}, a default one otherwise); it hides or changes EasyBI's types inEasyBIContext.VisualTypes. The designer refuses a measure beyond what a type takes (a second value on a pie), a visual tells which well misses or has too many fields, and a matrix takes four row fields as documented (#60). - Failed visuals explained: a visual whose query or renderer throws says it could not be displayed, with Retry and
the details of what happened (to copy into a bug report) instead of the exception's message;
EasyBIContext.VisualFailedlets the application log the failure, change the message or hide the details (#73).
Fixed¶
- LiveCharts2: the labels under groups turn like other category labels instead of being skipped (#51).
- Designer: the measure preview no longer cancels a query on every keystroke (#52).
- Comparisons with the previous year: a period under way (this year, the last months, a range ending later, the current year or month clicked) is compared with the same days a year earlier, not with the whole period; a range without an end no longer takes in this year's data (#62).
- Charts: an axis drawing bars starts at zero also when a line shares it (a year in bars and the year before as a line), and ends at zero for negative bars; OxyPlot no longer cuts negative bars (#63).
- Theming: an
EasyBIThemeMappingthat mapsChartPaletteKeygives charts the design system's palette instead of EasyBI's (#64). - Nullable dates (
DateTime?,DateOnly?,DateTimeOffset?) by year, quarter, month or day: EF Core can translate the query again (it failed with SQL Server, SQLite...), and missing dates form an empty period instead of the year 1; a missing date has no previous year.
Breaking changes¶
ReportDesigner.Visualis two-way, likeDashboardView.Document: setting it loads a visual (null starts a new one) and it receives every change of the end user;EditandClearare gone (#65).FilterContext.SelectionbecameSelections(one per visual), withSelectionOf,ClearSelection(visualId)andDescribeSelections;CrossFilterholdsElements(SelectedElement), itsValuesand filter-based constructor are gone andFiltersis computed (#41).- The
MarkTypeenum becameVisualType, a type identified by itsId, so that applications can add their own; EasyBI's are static properties (VisualType.Bar...) listed inVisualType.BuiltIn, and code that switched on them compares them instead (type == VisualType.Bar). Renamed with it:VisualDefinition.Mark→Type,MeasureRef.MarkandChartSeries.Mark→SeriesType,RendererCapabilities.Marks→Types,VisualPipeline.SeriesMarkandMarksOf→SeriesTypeandTypesOf, and in the designerSelectedMark,MarkOptions,MarkGroups,SelectedMarkOption→SelectedType,TypeOptions,TypeGroups,SelectedTypeOption,MarkOptionViewModel→VisualTypeOptionViewModel,VisualTypeIcon.Mark→Type, theSeriesMarkchip property →SeriesType.MarkGroupbecameVisualTypeGroupand moved withFormatTargettoEasyBI.Abstractions(#59). - Report JSON: a visual's
markbecametypeand a measure'smarkbecameseriesType. The schema stayseasybi/v1while EasyBI is in beta: in a report saved by an earlier version, rename these properties, otherwise its visuals open as bars (#59). ChartLegendmoved fromEasyBI.CoretoEasyBI.Abstractionsand gainedAuto,TopandLeft;ChartFitting.BottomLegendHeightwas removed (#48).ModelField.IsEditableis true for every measure (the model's ones can be redefined); useIsReportMeasurefor the report's own measures.MeasureContext.Setmatches a measure by model and name (#54).- A formula using a measure that the report redefines now reads the report's version, the model's
Formulameasures included (#56). FieldDescriptorgained an optionalFormulapositional parameter: source compatible, recompile (#54).
Report format¶
easybi/v1, backward compatible: AnyOf filters with alternatives; comparison operators (GreaterThan, Range...);
the Matrix, Donut, Gauge and Waterfall marks with an optional gauge; format on a measure; showOnChart on a
rule; tooltip, legendPosition and labels on a visual. A redefinition is a measures entry named like the
model's measure. Formulas may use functions and other measures.
0.4.0-beta.1 — 2026-10-21¶
Added¶
- Modernized designer: a properties panel on the right for the selected field, filter or visual (extensible through
DesignerViewModel.PropertiesBuilding), chips summed up by badges, a visual type gallery, wells that follow the visual type, undo / redo and keyboard shortcuts for the chips. - Customizable components: slots to add, replace or hide parts of the designer, filter bar, field list, filter editor and dashboard; the five components are lookless controls with replaceable templates.
- Renderer options: renderers declare their own options, edited in the designer and saved with the visual; LiveCharts2 charts can scroll.
- Designer: sort and Top N, search in the field list and in a filter's values, a message explaining why a field is refused.
- Dashboard: item selection with the mouse and the keyboard, copy and paste with the layout (also between dashboards), moving and extending items with the keyboard, fewer columns on a narrow dashboard, only the visuals in or near view are queried.
Breaking changes¶
ReportDesigner,FieldList,FilterBar,FilterEditorandDashboardViewderive fromControlinstead ofUserControl: code relying on their former named elements uses the new properties (ReportDesigner.ViewModel,FieldList.Dimensions...) and routed commands (FilterBar.AddFilterCommand...).ReportDesignerhas a new default template: theReportDesignerSlots.SortandRendererOptionsslots are replaced byProperties; chip settings moved to the properties panel.DesignerViewModel.CanDroprefuses fields on a well the visual type does not use.
Report format¶
easybi/v1 is unchanged: renderer settings live in the existing extensions of a visual. v0.3 files load as they are.
0.3.0-beta.1 — 2026-10-19¶
Added¶
- Calculated measures:
Ratio(...)/Calculated(g => ...)for developers, and formulas end users write from the field list ([Margin] / [Revenue]), saved with the report. - Period filters: between two dates, or relative to today (this month, last 12 months, last year), in the designer and the filter bar.
- Comparisons over time: previous year, change, % change, year to date per measure; KPI trends (▲ / ▼).
- Data refresh and performance:
EasyBIContext.RefreshData(model); leaner SQLGROUP BY(1.3× to 1.7× faster on SQLite with 5 million rows).
Breaking changes¶
VisualPipeline.PrepareAsynchas a new optionalmeasuresparameter before the cancellation token: pass the token by name (cancellationToken: token).FieldDescriptor,AnalyticQueryandModelFieldgained optional positional parameters: source compatible, recompile code built against v0.2.
Report format¶
easybi/v1 stays backward compatible: new optional measures (report) and time (measure) properties, new filter
operators Between, Current, Last, Previous. Files using them cannot be opened by v0.2.
0.2.0-beta.1 — 2026-10-19¶
Added¶
- Dashboard built from a panel, a layout API and behaviors (#10), laid out with greedy items and no gaps (#14); visuals built by dragging fields onto it (#15).
- Combined charts: a chart type per measure, with a secondary value axis (#11).
- Drag and drop infrastructure, reusable by applications (#13).
- Themes: EasyBI light and dark, following WPF UI and Material Design (#17).
Fixed¶
- Small LiveCharts2 and OxyPlot charts stay readable (#12).
Breaking changes¶
- Dashboards are laid out with greedy items in rows and columns instead of a grid with gaps (#14).
0.1.0-beta.1 — 2026-10-16¶
First published version.
- Semantic models over
IQueryable, query engine pushing filters, grouping, aggregates, sort and top to the provider. - Designer, visuals, LiveCharts2 and OxyPlot connectors.
- Global filters and cross-filtering (#2).
- English and French, with runtime language switching (#4).
- NuGet packages published with Trusted Publishing (#3, #5).