The LiveDisplay renders content that can be updated in place without scrolling the console, perfect for dashboards, real-time monitoring, and dynamic status displays.
When to Use
Use LiveDisplay when you need to update arbitrary content in place without creating new output lines. Common scenarios:
- Custom dashboards: Display real-time metrics, server stats, or system monitors with any widget combination
- Dynamic tables: Build tables incrementally or update existing rows as data changes
- Status transitions: Show multi-step processes with changing panels or formatted text
- Real-time data: Update charts, gauges, or custom visualizations continuously
For progress tracking with multiple tasks, use Progress instead. For simple spinner animations, use Status.
Basic Usage
Create a live display by passing any renderable to AnsiConsole.Live(), then update it within the context.
public static void BasicLiveDisplayExample()
{
var table = new Table();
table.AddColumn("Status");
table.AddRow("Starting...");
AnsiConsole.Live(table)
.Start(ctx =>
{
Thread.Sleep(1000);
table.AddRow("Processing...");
ctx.Refresh();
Thread.Sleep(1000);
table.AddRow("Complete!");
ctx.Refresh();
Thread.Sleep(1000);
});
}
Updating Content
Modifying Mutable Renderables
Modify properties of mutable widgets like Table, then call ctx.Refresh() to update the display.
public static void LiveDisplayWithTableExample()
{
var table = new Table()
.AddColumn("Server")
.AddColumn("Status")
.AddColumn("Uptime");
AnsiConsole.Live(table)
.Start(ctx =>
{
var servers = new[]
{
("web-01", "[green]Online[/]", "99.9%"),
("web-02", "[green]Online[/]", "99.8%"),
("db-01", "[green]Online[/]", "100%"),
("cache-01", "[yellow]Degraded[/]", "95.2%"),
("api-01", "[green]Online[/]", "99.7%")
};
foreach (var (server, status, uptime) in servers)
{
table.AddRow(server, status, uptime);
ctx.Refresh();
Thread.Sleep(500);
}
});
}
Replacing the Target
Use ctx.UpdateTarget() to completely replace the displayed renderable with a different widget.
public static void LiveDisplayUpdateTargetExample()
{
AnsiConsole.Live(new Text("Initializing..."))
.Start(ctx =>
{
Thread.Sleep(1000);
// Replace with a panel
var panel = new Panel("Loading configuration...")
.Header("Step 1")
.BorderColor(Color.Blue);
ctx.UpdateTarget(panel);
Thread.Sleep(1000);
// Replace with a different panel
var panel2 = new Panel("Connecting to database...")
.Header("Step 2")
.BorderColor(Color.Yellow);
ctx.UpdateTarget(panel2);
Thread.Sleep(1000);
// Replace with final panel
var panel3 = new Panel("[green]Ready![/]")
.Header("Complete")
.BorderColor(Color.Green);
ctx.UpdateTarget(panel3);
Thread.Sleep(1000);
});
}
Displaying Panels
Wrap dynamic content in panels for polished status displays.
public static void LiveDisplayWithPanelExample()
{
var table = new Table()
.Border(TableBorder.None)
.AddColumn("Metric")
.AddColumn("Value");
var panel = new Panel(table)
.Header("System Monitor")
.BorderColor(Color.Cyan)
.RoundedBorder();
AnsiConsole.Live(panel)
.Start(ctx =>
{
for (int i = 0; i < 10; i++)
{
table.Rows.Clear();
table.AddRow("CPU Usage", $"{Random.Shared.Next(10, 80)}%");
table.AddRow("Memory", $"{Random.Shared.Next(2, 8)} GB / 16 GB");
table.AddRow("Network", $"{Random.Shared.Next(100, 999)} MB/s");
table.AddRow("Uptime", $"{i + 1} seconds");
ctx.Refresh();
Thread.Sleep(1000);
}
});
}
Handling Overflow
When content exceeds the console height, LiveDisplay provides several overflow strategies.
Ellipsis Mode
Show an ellipsis indicator when content is truncated.
public static void LiveDisplayOverflowEllipsisExample()
{
var table = new Table()
.AddColumn("Line");
AnsiConsole.Live(table)
.Overflow(VerticalOverflow.Ellipsis)
.Start(ctx =>
{
for (int i = 1; i <= 100; i++)
{
table.AddRow($"Line {i}");
ctx.Refresh();
Thread.Sleep(50);
}
});
}
Crop Mode
Silently crop content that doesn't fit, combined with cropping direction control.
public static void LiveDisplayOverflowCropExample()
{
var table = new Table()
.AddColumn("Line");
AnsiConsole.Live(table)
.Overflow(VerticalOverflow.Crop)
.Start(ctx =>
{
for (int i = 1; i <= 100; i++)
{
table.AddRow($"Line {i}");
ctx.Refresh();
Thread.Sleep(50);
}
});
}
Visible Mode
Allow content to scroll naturally when it exceeds console height.
public static void LiveDisplayOverflowVisibleExample()
{
var table = new Table()
.AddColumn("Line");
AnsiConsole.Live(table)
.Overflow(VerticalOverflow.Visible)
.Start(ctx =>
{
for (int i = 1; i <= 30; i++)
{
table.AddRow($"Line {i}");
ctx.Refresh();
Thread.Sleep(100);
}
});
}
Cropping Direction
Control which part of overflowing content remains visible.
Crop from Top
Keep the most recent content visible by removing old content from the top.
public static void LiveDisplayCroppingTopExample()
{
var table = new Table()
.AddColumn("Log Entry");
AnsiConsole.Live(table)
.Overflow(VerticalOverflow.Crop)
.Cropping(VerticalOverflowCropping.Top)
.Start(ctx =>
{
for (int i = 1; i <= 50; i++)
{
table.AddRow($"[dim]{DateTime.Now:HH:mm:ss}[/] Log entry {i}");
ctx.Refresh();
Thread.Sleep(100);
}
});
}
Crop from Bottom
Keep the initial content visible by removing new content from the bottom.
public static void LiveDisplayCroppingBottomExample()
{
var table = new Table()
.AddColumn("Task Queue");
AnsiConsole.Live(table)
.Overflow(VerticalOverflow.Crop)
.Cropping(VerticalOverflowCropping.Bottom)
.Start(ctx =>
{
for (int i = 1; i <= 50; i++)
{
table.AddRow($"Task {i}: Processing");
ctx.Refresh();
Thread.Sleep(100);
}
});
}
Auto Clear
Remove the live display from the console when the context completes.
public static void LiveDisplayAutoClearExample()
{
var spinner = new Table()
.AddColumn("Status")
.AddRow("[blue]Processing...[/]");
AnsiConsole.Live(spinner)
.AutoClear(true)
.Start(ctx =>
{
for (int i = 1; i <= 5; i++)
{
spinner.Rows.Clear();
spinner.AddRow($"[blue]Processing step {i}/5...[/]");
ctx.Refresh();
Thread.Sleep(800);
}
});
AnsiConsole.WriteLine("Display cleared - task complete!");
}
Async Operations
Use StartAsync() for asynchronous work within the live display context.
public static async Task LiveDisplayAsyncExample()
{
var status = new Table()
.AddColumn("Operation")
.AddColumn("Status");
await AnsiConsole.Live(status)
.StartAsync(async ctx =>
{
var operations = new[]
{
"Fetching data",
"Processing records",
"Updating database",
"Generating report",
"Sending notifications"
};
foreach (var operation in operations)
{
status.AddRow(operation, "[yellow]In Progress[/]");
ctx.Refresh();
await Task.Delay(1000);
status.Rows.Update(status.Rows.Count - 1, 1, new Text("[green]Complete[/]"));
ctx.Refresh();
}
});
}
Returning Values
Return results from the live display context using the generic Start<T>() method.
public static void LiveDisplayReturnValueExample()
{
var result = AnsiConsole.Live(new Text("Processing..."))
.Start(ctx =>
{
int total = 0;
for (int i = 1; i <= 10; i++)
{
total += i;
ctx.UpdateTarget(new Text($"Processing: {i}/10 (Total: {total})"));
Thread.Sleep(300);
}
ctx.UpdateTarget(new Text("[green]Complete![/]"));
Thread.Sleep(500);
return total;
});
AnsiConsole.WriteLine($"Final result: {result}");
}
Combining Widgets
Create sophisticated dashboards by combining multiple widgets in layouts.
public static void LiveDisplayCompositeExample()
{
// Create status table
var statusTable = new Table()
.Border(TableBorder.Rounded)
.BorderColor(Color.Cyan)
.AddColumn("Service")
.AddColumn("Status")
.AddColumn("Requests/sec");
// Create metrics table
var metricsTable = new Table()
.Border(TableBorder.Rounded)
.BorderColor(Color.Yellow)
.AddColumn("Metric")
.AddColumn("Current")
.AddColumn("Average");
// Create layout with both tables
var layout = new Layout("Root")
.SplitRows(
new Layout("Header"),
new Layout("Body").SplitColumns(
new Layout("Status"),
new Layout("Metrics")
)
);
layout["Header"].Update(
new Panel("[bold cyan]Real-Time Dashboard[/]")
.BorderColor(Color.Blue)
.Padding(1, 0)
);
layout["Status"].Update(new Panel(statusTable).Header("Services"));
layout["Metrics"].Update(new Panel(metricsTable).Header("System Metrics"));
AnsiConsole.Live(layout)
.Start(ctx =>
{
for (int i = 0; i < 15; i++)
{
// Update status table
statusTable.Rows.Clear();
statusTable.AddRow("API Gateway", "[green]Healthy[/]", $"{Random.Shared.Next(100, 500)}");
statusTable.AddRow("Auth Service", "[green]Healthy[/]", $"{Random.Shared.Next(50, 200)}");
statusTable.AddRow("Database", i > 10 ? "[yellow]Degraded[/]" : "[green]Healthy[/]", $"{Random.Shared.Next(200, 800)}");
statusTable.AddRow("Cache", "[green]Healthy[/]", $"{Random.Shared.Next(1000, 3000)}");
// Update metrics table
metricsTable.Rows.Clear();
metricsTable.AddRow("CPU", $"{Random.Shared.Next(20, 75)}%", "45%");
metricsTable.AddRow("Memory", $"{Random.Shared.Next(4, 12)} GB", "8 GB");
metricsTable.AddRow("Disk I/O", $"{Random.Shared.Next(10, 90)} MB/s", "45 MB/s");
metricsTable.AddRow("Network", $"{Random.Shared.Next(100, 500)} MB/s", "250 MB/s");
ctx.Refresh();
Thread.Sleep(1000);
}
});
}
API Reference
Represents a live display.
Constructors
LiveDisplay(IAnsiConsole console, IRenderable target)Initializes a new instance of the class.
Parameters:
console (IAnsiConsole)target (IRenderable)Properties
AutoClear
: boolGets or sets a value indicating whether or not the live display should be cleared when it's done. Defaults to false.
Cropping
: VerticalOverflowCroppingGets or sets the vertical overflow cropping strategy.
Overflow
: VerticalOverflowGets or sets the vertical overflow strategy.
Methods
Start(Action<LiveDisplayContext> action)Starts the live display.
Parameters:
action (Action<LiveDisplayContext>)T Start(Func<LiveDisplayContext, T> func)Parameters:
func (Func<LiveDisplayContext, T>)Task StartAsync(Func<LiveDisplayContext, Task> func)Starts the live display.
Parameters:
func (Func<LiveDisplayContext, Task>)Returns:
The result.
Task<T> StartAsync(Func<LiveDisplayContext, Task<T>> func)Parameters:
func (Func<LiveDisplayContext, Task<T>>)Extension Methods
LiveDisplay AutoClear(bool enabled)Sets whether or not auto clear is enabled. If enabled, the live display will be cleared when done.
Parameters:
enabled (bool)Returns:
The same instance so that multiple calls can be chained.
LiveDisplay Cropping(VerticalOverflowCropping cropping)Sets the vertical overflow cropping strategy.
Parameters:
cropping (VerticalOverflowCropping)Returns:
The same instance so that multiple calls can be chained.
LiveDisplay Overflow(VerticalOverflow overflow)Sets the vertical overflow strategy.
Parameters:
overflow (VerticalOverflow)Returns:
The same instance so that multiple calls can be chained.