Please note that this control has been deprecated and replaced with the Grid component, and as such, we recommend migrating to that control. This will not be receiving any new features, bug fixes will be deprioritized. For help or questions on migrating your codebase to the Data Grid, please contact support.
Blazor High Performance with Live Data
The Ignite UI for Blazor Data Table / Data Grid is optimized for high-performance with live data scenarios. With fast load time, smooth scrolling with zero lag time or screen flicker, you can seamlessly scroll through an unlimited number of rows and columns in your Blazor data grid application with full virtualization of grid's columns and rows.
Blazor High Performance with Live Data Example
This sample demonstrates this performance by binding thousands of financial records to the Blazor data grid, grouping them by 1 column (eg. Territory), and live-updating multiple columns every couple of milliseconds. You can change various options in real-time and the Data Grid performance with no lag, screen flicker, or visual delay
using System;
using System.Net.Http;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Text;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using IgniteUI.Blazor.Controls; // for registering Ignite UI modules
namespace Infragistics.Samples
{
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
// registering Ignite UI modules
builder.Services.AddIgniteUIBlazor(
typeof(IgbDataGridModule)
);
await builder.Build().RunAsync();
}
}
}
csusing IgniteUI.Blazor.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace Infragistics.Samples
{
public class SalesPerson
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Name { get; set; }
public string ImageName { get; set; }
public string Territory { get; set; }
public int Index { get; set; }
public double AvgSale { get; set; }
public double AvgSaleHeat { get; set; }
public double Change { get; set; }
public double PercentChange { get; set; }
public double YearToDateSales { get; set; }
public DateTime DateValue { get; set; }
public double KPI_0 { get; set; }
public double KPI_1 { get; set; }
public double KPI_2 { get; set; }
public double KPI_3 { get; set; }
public double KPI_4 { get; set; }
public double KPI_5 { get; set; }
public double KPI_6 { get; set; }
public double KPI_7 { get; set; }
}
public class SalesPersonData
{
public static List<SalesPerson> GenerateSalesPeople(int number)
{
string[] firstNames = new string[] {
"Kyle",
"Gina",
"Irene",
"Katie",
"Michael",
"Oscar",
"Ralph",
"Torrey",
"William",
"Bill",
"Daniel",
"Frank",
"Brenda",
"Danielle",
"Fiona",
"Howard",
"Jack",
"Larry",
"Holly",
"Jennifer",
"Liz",
"Pete",
"Steve",
"Vince",
"Zeke"
};
string[] lastNames = new string[] {
"Adams",
"Crowley",
"Ellis",
"Gable",
"Irvine",
"Keefe",
"Mendoza",
"Owens",
"Rooney",
"Waddell",
"Thomas",
"Betts",
"Doran",
"Fitzgerald",
"Holmes",
"Jefferson",
"Landry",
"Newberry",
"Perez",
"Spencer",
"Vargas",
"Grimes",
"Edwards",
"Stark",
"Cruise",
"Fitz",
"Chief",
"Blanc",
"Perry",
"Stone",
"Williams",
"Lane",
"Jobs"
};
string[] genders = new string[] {
"GUY",
"GIRL",
"GIRL",
"GIRL",
"GUY",
"GUY",
"GUY",
"GUY",
"GUY",
"GUY",
"GUY",
"GUY",
"GIRL",
"GIRL",
"GIRL",
"GUY",
"GUY",
"GUY",
"GIRL",
"GIRL",
"GIRL",
"GUY",
"GUY",
"GUY",
"GUY"
};
string[] territories = new string[]{
"Australia",
"Canada",
"Egypt",
"Greece",
"Italy",
"Kenya",
"Mexico",
"Oman",
"Qatar",
"Sweden",
"Uruguay",
"Yemen",
"Bulgaria",
"Denmark",
"France",
"Hungary",
"Japan",
"Latvia",
"Netherlands",
"Portugal",
"Russia",
"Turkey",
"Venezuela",
"Zimbabwe"
};
List<SalesPerson> items = new List<SalesPerson>();
Random r = new Random();
for (int i = 0; i < number; i++)
{
SalesPerson item = new SalesPerson();
int firstIndex = (int)Math.Round(r.NextDouble() * (firstNames.Length - 1));
item.Index = i;
item.FirstName = firstNames[firstIndex];
item.LastName = lastNames[(int)Math.Round(r.NextDouble() * (lastNames.Length - 1))];
item.Name = item.FirstName + item.LastName;
int randomIndex = (int)Math.Round(r.NextDouble() * (firstNames.Length - 1));
if (randomIndex == 0)
{
randomIndex = 1;
}
string value = randomIndex.ToString();
if (randomIndex < 10)
{
value = "0" + value;
}
item.ImageName = SalesPersonData.CreateUri(genders[firstIndex] + value + ".png");
item.Territory = territories[(int)Math.Round(r.NextDouble() * (territories.Length - 1))];
item.AvgSale = Math.Round((r.NextDouble() * 800)) + 200.0;
item.Change = (r.NextDouble() * 40.0) - 20.0;
item.PercentChange = 0;
item.YearToDateSales = Math.Round(r.NextDouble() * 50000);
item.DateValue = DateTime.Today.AddDays(number * -1);
for (int j = 0; j < 8; j++)
{
PropertyInfo info = typeof(SalesPerson).GetProperty("KPI_" + j.ToString());
info.SetValue(item, Math.Round(r.NextDouble() * 100));
}
items.Add(item);
}
return items;
}
public static string CreateUri(string value)
{
return "https://static.infragistics.com/xplatform/images/people/" + value;
}
}
}
cs
@using IgniteUI.Blazor.Controls
<div class="container vertical">
<div class="container vertical">
@if (Data != null)
{
<div style="overflow: hidden">
<IgbDataGrid Height="100%" Width="100%"
@ref="DataGridRef"
AutoGenerateColumns="false"
HeaderClickAction="@HeaderClickAction.SortByMultipleColumnsTriState"
RowHeight="40"
SelectionMode="@DataGridSelectionMode.MultipleRow"
DefaultColumnMinWidth="80"
SortDescriptionsChanged="OnSortDescriptionsChanged"
ColumnShowingAnimationMode="@ColumnShowingAnimationMode.Auto"
ColumnHidingAnimationMode="@ColumnHidingAnimationMode.Auto"
DataSource="Data"
IsRowHoverEnabled="false">
<IgbTextColumn Field="FirstName" HeaderText="First Name" Width="@("*>130")" />
<IgbTextColumn Field="LastName" HeaderText="Last Name" Width="@("*>130")" />
<IgbTextColumn Field="Territory" Width="@("*>130")" />
<IgbNumericColumn Field="YearToDateSales" HeaderText="YTD Sales" Width="@("*>130")"
PositivePrefix="$" ShowGroupingSeparator="true" />
<IgbTemplateColumn Field="AvgSale" HeaderText="Avg. Sale" Width="@("*>120")" HorizontalAlignment="@CellContentHorizontalAlignment.Right"
CellUpdatingScript="onAvgSaleCellUpdating" />
<IgbTemplateColumn Field="Change" Width="@("*>120")" HorizontalAlignment="@CellContentHorizontalAlignment.Right"
CellUpdatingScript="onChangeCellUpdating"/>
<IgbTemplateColumn Field="PercentChange" Width="@("*>140")" HorizontalAlignment="@CellContentHorizontalAlignment.Right"
HeaderText="Change (%)" CellUpdatingScript="onPercentChangeCellUpdating"/>
<IgbDateTimeColumn Field="DateValue" HeaderText="Date" Width="@("*>120")" />
@for (int i = 0; i < 8; i++)
{
string str = "KPI_" + i.ToString();
<IgbNumericColumn Width="@("*>150")" Field="@str" DataBoundScript="onKPIColumnDataBound"/>
}
</IgbDataGrid>
</div>
}
</div>
</div>
@code {
private void OnSortDescriptionsChanged(IgbGridSortDescriptionsChangedEventArgs args)
{
}
private List<SalesPerson> Data;
private IgbDataGrid _grid;
private IgbDataGrid DataGridRef
{
get { return _grid; }
set
{
_grid = value;
this.OnDataGridRef();
StateHasChanged();
}
}
private DateTime lastDataUpdate = new DateTime();
private int interval = 1000;
private Random random = new Random();
protected override void OnInitialized()
{
this.Data = SalesPersonData.GenerateSalesPeople(500);
}
private void OnDataGridRef()
{
var columnGroup = new IgbColumnGroupDescription();
columnGroup.Field = "Territory";
this.DataGridRef.GroupDescriptions.Add(columnGroup);
Task.Delay(1000).ContinueWith((t) => OnTimerTick());
}
private void OnTimerTick()
{
bool sortedBySales = false;
int toChange = (int)Math.Round(this.Data.Count / 10.0);
var toChangeIndexes = new List<bool>();
bool stillAnimating = false;
for (int i = 0; i < this.Data.Count; i++)
{
toChangeIndexes.Add(false);
SalesPerson item = this.Data[i];
if (item.AvgSaleHeat != 0)
{
stillAnimating = true;
}
}
var now = DateTime.Now;
bool intervalElapsed = false;
if ((now - lastDataUpdate).TotalMilliseconds > this.interval)
{
intervalElapsed = true;
}
bool useClear = false;
bool sortingByAvgSale = false;
for (int i = 0; i < this.DataGridRef.SortDescriptions.Count; i++)
{
if (this.DataGridRef.SortDescriptions[i].Field == "AvgSale" || this.DataGridRef.SortDescriptions[i].Field.IndexOf("Change") >= 0)
{
sortingByAvgSale = true;
}
}
bool changing = false;
if (intervalElapsed)
{
this.lastDataUpdate = new DateTime();
for (int i = 0; i < toChange; i++)
{
int index = (int)Math.Round(random.NextDouble() * (this.Data.Count - 1));
toChangeIndexes[index] = true;
}
}
for (int i = 0; i < toChangeIndexes.Count; i++)
{
var item = this.Data[i];
if (toChangeIndexes[i] == true)
{
if (sortingByAvgSale && !useClear)
{
this.DataGridRef.NotifyRemoveItem(this.Data, i, item);
this.RandomizeItem(item);
this.DataGridRef.NotifyInsertItem(this.Data, i, item);
}
else
{
this.RandomizeItem(item);
this.DataGridRef.NotifyUpdateItem(this.Data, i, item, true);
}
if (item.Change > 0)
{
item.AvgSaleHeat = 1;
}
else
{
item.AvgSaleHeat = -1;
}
}
else
{
if (item.AvgSaleHeat > 0)
{
item.AvgSaleHeat -= .06;
if (item.AvgSaleHeat < 0)
{
item.AvgSaleHeat = 0;
}
}
if (item.AvgSaleHeat < 0)
{
item.AvgSaleHeat += .06;
if (item.AvgSaleHeat > 0)
{
item.AvgSaleHeat = 0;
}
}
}
}
//if(sortingByAvgSale && useClear)
//{
// this.DataGridRef.ActualDataSource.QueueAutoRefresh();
//}
if (!sortingByAvgSale || !intervalElapsed)
{
this.DataGridRef.InvalidateVisibleRows();
}
Task.Delay(1000).ContinueWith((t) => OnTimerTick());
}
private void RandomizeItem(SalesPerson item)
{
item.Change = (random.NextDouble() * 40.0) - 20.0;
double prevSale = item.AvgSale;
item.AvgSale += item.Change;
item.PercentChange = ((item.AvgSale / prevSale) * 100.00);
}
}
razorfunction onAvgSaleCellUpdating(column, args) {
let row = args.cellInfo.rowItem;
let priceShiftUp = row.Change >= 0;
let templ = args.cellInfo;
let content = args.content;
let sp = null;
let icon = null;
if (content.childElementCount > 0) {
sp = content.children[0];
icon = content.children[1];
} else {
content.style.textAlign = "right";
sp = document.createElement("span");
icon = document.createElement("span");
sp.style.font = "13px Verdana";
sp.style.verticalAlign = "center";
content.appendChild(sp);
content.appendChild(icon);
icon.style.fontFamily = "Material Icons";
icon.style.fontSize = "13px";
icon.style.fontFeatureSettings = "liga";
icon.style.verticalAlign = "center";
}
sp.textContent = "$" + (+templ.value).toFixed(2);
if (priceShiftUp) {
icon.style.color = "#4EB862";
sp.style.color = "#4EB862";
} else {
icon.style.color = "#FF134A";
sp.style.color = "#FF134A";
}
}
function onChangeCellUpdating(column, args) {
let templ = args.cellInfo;
let priceShiftUp = templ.value >= 0;
let content = args.content;
let sp = null;
if (content.childElementCount > 0) {
sp = content.children[0];
} else {
content.style.textAlign = "right";
sp = document.createElement("span");
sp.style.font = "13px Verdana";
sp.style.verticalAlign = "center";
content.appendChild(sp);
}
sp.textContent = (+templ.value).toFixed(2);
if (priceShiftUp) {
sp.style.paddingRight = "5px";
sp.style.borderRight = "4px solid #4EB862";
} else {
sp.style.paddingRight = "5px";
sp.style.borderRight = "4px solid #FF134A";
}
}
function onPercentChangeCellUpdating(column, args) {
let templ = args.cellInfo;
let priceShiftUp = templ.value >= 0;
let content = args.content;
let sp = null;
if (content.childElementCount > 0) {
sp = content.children[0];
} else {
content.style.textAlign = "right";
sp = document.createElement("span");
sp.style.font = "13px Verdana";
sp.style.verticalAlign = "center";
content.appendChild(sp);
}
sp.textContent = (+templ.value).toFixed(2) + "%";
if (priceShiftUp) {
sp.style.paddingRight = "5px";
sp.style.borderRight = "4px solid #4EB862";
} else {
sp.style.paddingRight = "5px";
sp.style.borderRight = "4px solid #FF134A";
}
}
function onKPIColumnDataBound(column, args) {
let value = args.resolvedValue;
if (value < 20.0) {
if (args.cellInfo.background !== "red") {
args.cellInfo.background = "#FF134A";
}
}
if (value > 80.0) {
if (args.cellInfo.background !== "green") {
args.cellInfo.background = "#4EB862";
}
}
}
igRegisterScript("onAvgSaleCellUpdating", onAvgSaleCellUpdating, false);
igRegisterScript("onChangeCellUpdating", onChangeCellUpdating, false);
igRegisterScript("onPercentChangeCellUpdating", onPercentChangeCellUpdating, false);
igRegisterScript("onKPIColumnDataBound", onKPIColumnDataBound, false);
js/*
CSS styles are loaded from the shared CSS file located at:
https://static.infragistics.com/xplatform/css/samples/
*/
css