diff --git a/src/Spectre.Console/Extensions/TableExtensions.cs b/src/Spectre.Console/Extensions/TableExtensions.cs
index 8f0776d..eb96933 100644
--- a/src/Spectre.Console/Extensions/TableExtensions.cs
+++ b/src/Spectre.Console/Extensions/TableExtensions.cs
@@ -189,6 +189,56 @@ namespace Spectre.Console
return table;
}
+ ///
+ /// Updates a tables cell.
+ ///
+ /// The table to update.
+ /// The index of row to update.
+ /// The index of column to update.
+ /// New cell data.
+ /// The same instance so that multiple calls can be chained.
+ public static Table UpdateCell(this Table table, int rowIndex, int columnIndex, IRenderable cellData)
+ {
+ if (table is null)
+ {
+ throw new ArgumentNullException(nameof(table));
+ }
+
+ if (cellData is null)
+ {
+ throw new ArgumentNullException(nameof(cellData));
+ }
+
+ table.Rows.Update(rowIndex, columnIndex, cellData);
+
+ return table;
+ }
+
+ ///
+ /// Updates a tables cell.
+ ///
+ /// The table to update.
+ /// The index of row to update.
+ /// The index of column to update.
+ /// New cell data.
+ /// The same instance so that multiple calls can be chained.
+ public static Table UpdateCell(this Table table, int rowIndex, int columnIndex, string cellData)
+ {
+ if (table is null)
+ {
+ throw new ArgumentNullException(nameof(table));
+ }
+
+ if (cellData is null)
+ {
+ throw new ArgumentNullException(nameof(cellData));
+ }
+
+ table.Rows.Update(rowIndex, columnIndex, new Markup(cellData));
+
+ return table;
+ }
+
///
/// Inserts a row in the table at the specified index.
///
diff --git a/src/Spectre.Console/Widgets/Table/TableRowCollection.cs b/src/Spectre.Console/Widgets/Table/TableRowCollection.cs
index f189392..29f6128 100644
--- a/src/Spectre.Console/Widgets/Table/TableRowCollection.cs
+++ b/src/Spectre.Console/Widgets/Table/TableRowCollection.cs
@@ -89,6 +89,55 @@ namespace Spectre.Console
}
}
+ ///
+ /// Update a table cell at the specified index.
+ ///
+ /// Index of cell row.
+ /// index of cell column.
+ /// The new cells details.
+ public void Update(int row, int column, IRenderable cellData)
+ {
+ if (cellData is null)
+ {
+ throw new ArgumentNullException(nameof(cellData));
+ }
+
+ lock (_lock)
+ {
+ if (row < 0)
+ {
+ throw new IndexOutOfRangeException("Table row index cannot be negative.");
+ }
+ else if (row >= _list.Count)
+ {
+ throw new IndexOutOfRangeException("Table row index cannot exceed the number of rows in the table.");
+ }
+
+ var tableRow = _list.ElementAtOrDefault(row);
+
+ var currentRenderables = tableRow.ToList();
+
+ if (column < 0)
+ {
+ throw new IndexOutOfRangeException("Table column index cannot be negative.");
+ }
+ else if (column >= currentRenderables.Count)
+ {
+ throw new IndexOutOfRangeException("Table column index cannot exceed the number of rows in the table.");
+ }
+
+ currentRenderables.RemoveAt(column);
+
+ currentRenderables.Insert(column, cellData);
+
+ var newTableRow = new TableRow(currentRenderables);
+
+ _list.RemoveAt(row);
+
+ _list.Insert(row, newTableRow);
+ }
+ }
+
///
/// Removes a row at the specified index.
///
diff --git a/test/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row.verified.txt b/test/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row.verified.txt
new file mode 100644
index 0000000..157cc59
--- /dev/null
+++ b/test/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row.verified.txt
@@ -0,0 +1,7 @@
+┌───────────┬───────────┬───────────┐
+│ Column #1 │ Column #2 │ Column #3 │
+├───────────┼───────────┼───────────┤
+│ 1 │ │ │
+│ 2 │ │ │
+│ 3 │ 4 │ 5 │
+└───────────┴───────────┴───────────┘
diff --git a/test/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row_With_Renderable.verified.txt b/test/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row_With_Renderable.verified.txt
new file mode 100644
index 0000000..157cc59
--- /dev/null
+++ b/test/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row_With_Renderable.verified.txt
@@ -0,0 +1,7 @@
+┌───────────┬───────────┬───────────┐
+│ Column #1 │ Column #2 │ Column #3 │
+├───────────┼───────────┼───────────┤
+│ 1 │ │ │
+│ 2 │ │ │
+│ 3 │ 4 │ 5 │
+└───────────┴───────────┴───────────┘
diff --git a/test/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row_With_String.verified.txt b/test/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row_With_String.verified.txt
new file mode 100644
index 0000000..157cc59
--- /dev/null
+++ b/test/Spectre.Console.Tests/Expectations/TableRowCollectionTests.TheUpdateMethod.Should_Update_Row_With_String.verified.txt
@@ -0,0 +1,7 @@
+┌───────────┬───────────┬───────────┐
+│ Column #1 │ Column #2 │ Column #3 │
+├───────────┼───────────┼───────────┤
+│ 1 │ │ │
+│ 2 │ │ │
+│ 3 │ 4 │ 5 │
+└───────────┴───────────┴───────────┘
diff --git a/test/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionTests.cs b/test/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionTests.cs
index 15f931f..752baf1 100644
--- a/test/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionTests.cs
+++ b/test/Spectre.Console.Tests/Unit/Widgets/Table/TableRowCollectionTests.cs
@@ -222,5 +222,145 @@ namespace Spectre.Console.Tests.Unit
result.ShouldBe(0);
}
}
+
+ [UsesVerify]
+ public sealed class TheUpdateMethod
+ {
+ [Fact]
+ public Task Should_Update_Row_With_String()
+ {
+ // Given
+ var console = new TestConsole();
+ var table = new Table();
+ table.AddColumn("Column #1");
+ table.AddColumn("Column #2");
+ table.AddColumn("Column #3");
+ table.Rows.Add(new[] { new Text("1") });
+ table.Rows.Add(new[] { new Text("2") });
+ table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
+
+ table.UpdateCell(2, 2, "5");
+
+ // When
+ console.Write(table);
+
+ // Then
+ return Verifier.Verify(console.Output);
+ }
+
+ [Fact]
+ public Task Should_Update_Row_With_Renderable()
+ {
+ // Given
+ var console = new TestConsole();
+ var table = new Table();
+ table.AddColumn("Column #1");
+ table.AddColumn("Column #2");
+ table.AddColumn("Column #3");
+ table.Rows.Add(new[] { new Text("1") });
+ table.Rows.Add(new[] { new Text("2") });
+ table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
+
+ table.UpdateCell(2, 2, new Markup("5"));
+
+ // When
+ console.Write(table);
+
+ // Then
+ return Verifier.Verify(console.Output);
+ }
+
+ [Fact]
+ public void Should_Throw_If_Index_Is_Larger_Than_Number_Of_Rows()
+ {
+ // Given
+ var console = new TestConsole();
+ var table = new Table();
+ table.AddColumn("Column #1");
+ table.AddColumn("Column #2");
+ table.AddColumn("Column #3");
+ table.Rows.Add(new[] { new Text("1") });
+ table.Rows.Add(new[] { new Text("2") });
+ table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
+ table.UpdateCell(2, 2, "5");
+
+
+ // When
+ var result = Record.Exception(() => table.UpdateCell(5, 2, "5"));
+
+ // Then
+ result.ShouldBeOfType()
+ .Message.ShouldBe("Table row index cannot exceed the number of rows in the table.");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Index_Is_Larger_Than_Number_Of_Columns()
+ {
+ // Given
+ var console = new TestConsole();
+ var table = new Table();
+ table.AddColumn("Column #1");
+ table.AddColumn("Column #2");
+ table.AddColumn("Column #3");
+ table.Rows.Add(new[] { new Text("1") });
+ table.Rows.Add(new[] { new Text("2") });
+ table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
+ table.UpdateCell(2, 2, "5");
+
+
+ // When
+ var result = Record.Exception(() => table.UpdateCell(2, 5, "5"));
+
+ // Then
+ result.ShouldBeOfType()
+ .Message.ShouldBe("Table column index cannot exceed the number of rows in the table.");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Index_Row_Is_Negative()
+ {
+ // Given
+ var console = new TestConsole();
+ var table = new Table();
+ table.AddColumn("Column #1");
+ table.AddColumn("Column #2");
+ table.AddColumn("Column #3");
+ table.Rows.Add(new[] { new Text("1") });
+ table.Rows.Add(new[] { new Text("2") });
+ table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
+ table.UpdateCell(2, 2, "5");
+
+
+ // When
+ var result = Record.Exception(() => table.UpdateCell(-1, 2, "5"));
+
+ // Then
+ result.ShouldBeOfType()
+ .Message.ShouldBe("Table row index cannot be negative.");
+ }
+
+ [Fact]
+ public void Should_Throw_If_Index_Column_Is_Negative()
+ {
+ // Given
+ var console = new TestConsole();
+ var table = new Table();
+ table.AddColumn("Column #1");
+ table.AddColumn("Column #2");
+ table.AddColumn("Column #3");
+ table.Rows.Add(new[] { new Text("1") });
+ table.Rows.Add(new[] { new Text("2") });
+ table.Rows.Add(new[] { new Text("3"), new Text("4"), new Text("8") });
+ table.UpdateCell(2, 2, "5");
+
+
+ // When
+ var result = Record.Exception(() => table.UpdateCell(2, -1, "5"));
+
+ // Then
+ result.ShouldBeOfType()
+ .Message.ShouldBe("Table column index cannot be negative.");
+ }
+ }
}
}