diff --git a/src/Columns/TableViewNumberColumn.cs b/src/Columns/TableViewNumberColumn.cs index e46c7c9..e1ffee4 100644 --- a/src/Columns/TableViewNumberColumn.cs +++ b/src/Columns/TableViewNumberColumn.cs @@ -43,4 +43,4 @@ public override FrameworkElement GenerateEditingElement(TableViewCell cell, obje #endif return numberBox; } -} +} \ No newline at end of file diff --git a/src/Columns/TableViewTextColumn.cs b/src/Columns/TableViewTextColumn.cs index 5f02e16..5ff2432 100644 --- a/src/Columns/TableViewTextColumn.cs +++ b/src/Columns/TableViewTextColumn.cs @@ -1,5 +1,6 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; +using WinUI.TableView.Helpers; namespace WinUI.TableView; @@ -27,7 +28,7 @@ public override FrameworkElement GenerateElement(TableViewCell cell, object? dat } /// - /// Generates a TextBox element for editing the cell. + /// Generates a TextBox element for editing the cell with ESC/Enter key support. /// /// The cell for which the editing element is generated. /// The data item associated with the cell. @@ -35,10 +36,14 @@ public override FrameworkElement GenerateElement(TableViewCell cell, object? dat public override FrameworkElement GenerateEditingElement(TableViewCell cell, object? dataItem) { var textBox = new TextBox(); - textBox.SetBinding(TextBox.TextProperty, Binding); + + // Add ESC/Enter key handling + EditingHelper.AddKeyHandling(textBox, cell, dataItem, Binding.Path?.Path); + #if !WINDOWS textBox.DataContext = dataItem; #endif + return textBox; } } diff --git a/src/Helpers/EditingHelper.cs b/src/Helpers/EditingHelper.cs new file mode 100644 index 0000000..93f9f8c --- /dev/null +++ b/src/Helpers/EditingHelper.cs @@ -0,0 +1,133 @@ +using Microsoft.UI.Xaml.Controls; +using System; +using Windows.System; + +namespace WinUI.TableView.Helpers; + +/// +/// Helper class for handling ESC/Enter key functionality in editable columns +/// Only TextBox editing elements are supported +/// +internal static class EditingHelper +{ + /// + /// Adds ESC/Enter key handling to a TextBox editing element + /// + /// The TextBox editing element + /// The TableView cell + /// The data item + /// The property path for binding + public static void AddKeyHandling(TextBox textBox, TableViewCell cell, object? dataItem, string? propertyPath) + { + // Store original value for ESC cancellation + var originalValue = GetPropertyValue(dataItem, propertyPath); + textBox.Tag = originalValue; + + // Set initial text value + textBox.Text = originalValue?.ToString() ?? string.Empty; + + // Handle ESC and Enter key events + textBox.KeyDown += (sender, args) => + { + if (args.Key == VirtualKey.Escape) + { + // Cancel editing: restore original value + textBox.Text = textBox.Tag?.ToString() ?? string.Empty; + args.Handled = true; + EndEditing(cell); + } + else if (args.Key == VirtualKey.Enter) + { + // Commit changes: update data source manually + CommitTextValue(textBox, dataItem, propertyPath); + args.Handled = true; + EndEditing(cell); + } + }; + + // Commit changes when focus is lost + textBox.LostFocus += (sender, args) => + { + if (cell.TableView?.IsEditing == true) + { + CommitTextValue(textBox, dataItem, propertyPath); + } + }; + } + + /// + /// Ends editing mode and refreshes the cell + /// /// + private static void EndEditing(TableViewCell cell) + { + cell.TableView?.SetIsEditing(false); + cell.SetElement(); + } + + /// + /// Commits TextBox value to the data source + /// + private static void CommitTextValue(TextBox textBox, object? dataItem, string? propertyPath) + { + if (dataItem == null || string.IsNullOrEmpty(propertyPath)) + return; + + try + { + var property = dataItem.GetType().GetProperty(propertyPath); + if (property != null && property.CanWrite) + { + var convertedValue = ConvertValue(textBox.Text, property.PropertyType); + property.SetValue(dataItem, convertedValue); + } + } + catch + { + // Ignore conversion errors + } + } + + /// + /// Converts string value to target property type + /// + private static object? ConvertValue(string textValue, Type targetType) + { + if (string.IsNullOrEmpty(textValue)) + { + return targetType.IsValueType ? Activator.CreateInstance(targetType) : null; + } + + var underlyingType = Nullable.GetUnderlyingType(targetType) ?? targetType; + + if (underlyingType == typeof(string)) + return textValue; + + try + { + return Convert.ChangeType(textValue, underlyingType); + } + catch + { + return targetType.IsValueType ? Activator.CreateInstance(targetType) : null; + } + } + + /// + /// Helper method to get property value from data item + /// + private static object? GetPropertyValue(object? dataItem, string? propertyPath) + { + if (dataItem == null || string.IsNullOrEmpty(propertyPath)) + return null; + + try + { + var property = dataItem.GetType().GetProperty(propertyPath); + return property?.GetValue(dataItem); + } + catch + { + return null; + } + } +} \ No newline at end of file