From c1e72dee772d11d9704ab56abc5756808b7e7751 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 1 Nov 2024 16:25:55 +0100 Subject: [PATCH] WIP --- .../Models/TreeDataGrid/TextCell.cs | 38 +++++++++++-------- .../Primitives/TreeDataGridCell.cs | 7 ++++ .../Primitives/TreeDataGridTextCell.cs | 6 +++ .../Models/TextCellTests.cs | 14 +++---- 4 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/TextCell.cs b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/TextCell.cs index e33b9e7f..18afebe8 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/TextCell.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Models/TreeDataGrid/TextCell.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reactive.Subjects; using Avalonia.Data; @@ -12,11 +10,11 @@ namespace Avalonia.Controls.Models.TreeDataGrid public class TextCell : NotifyingBase, ITextCell, IDisposable, IEditableObject { private readonly ISubject>? _binding; + private readonly ITextCellOptions? _options; private readonly IDisposable? _subscription; - [AllowNull] private T? _value; - [AllowNull] private T? _cancelValue; + private string? _editText; + private T? _value; private bool _isEditing; - private ITextCellOptions? _options; public TextCell(T? value) { @@ -51,21 +49,29 @@ public string? Text { get { - if (_options?.StringFormat is { } format) + if (_isEditing) + return _editText; + else if (_options?.StringFormat is { } format) return string.Format(_options.Culture ?? CultureInfo.CurrentCulture, format, _value); else return _value?.ToString(); } - set { - if (string.IsNullOrEmpty(value)) + if (_isEditing) { - Value = default(T?); + _editText = value; } else { - Value = (T?)Convert.ChangeType(value, typeof(T)); + try + { + Value = (T?)Convert.ChangeType(value, typeof(T)); + } + catch + { + // TODO: Data validation errors. + } } } } @@ -87,7 +93,7 @@ public void BeginEdit() if (!_isEditing && !IsReadOnly) { _isEditing = true; - _cancelValue = Value; + _editText = Text; } } @@ -95,19 +101,19 @@ public void CancelEdit() { if (_isEditing) { - Value = _cancelValue; _isEditing = false; - _cancelValue = default; + _editText = null; } } public void EndEdit() { - if (_isEditing && !EqualityComparer.Default.Equals(_value, _cancelValue)) + if (_isEditing) { + var text = _editText; _isEditing = false; - _cancelValue = default; - _binding!.OnNext(_value!); + _editText = null; + Text = text; } } diff --git a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridCell.cs b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridCell.cs index dccb2b66..5a9822c4 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridCell.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridCell.cs @@ -93,7 +93,10 @@ protected void CancelEdit() protected void EndEdit() { if (EndEditCore() && Model is IEditableObject editable) + { editable.EndEdit(); + UpdateValue(); + } } protected void SubscribeToModelChanges() @@ -108,6 +111,10 @@ protected void UnsubscribeFromModelChanges() inpc.PropertyChanged -= OnModelPropertyChanged; } + protected virtual void UpdateValue() + { + } + protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e) { _treeDataGrid = this.FindLogicalAncestorOfType(); diff --git a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridTextCell.cs b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridTextCell.cs index 24367849..b56d09f5 100644 --- a/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridTextCell.cs +++ b/src/Avalonia.Controls.TreeDataGrid/Primitives/TreeDataGridTextCell.cs @@ -1,5 +1,6 @@ using System.ComponentModel; using System.Globalization; +using System.Reflection; using Avalonia.Controls.Models.TreeDataGrid; using Avalonia.Controls.Selection; using Avalonia.Media; @@ -85,6 +86,11 @@ public override void Unrealize() base.Unrealize(); } + protected override void UpdateValue() + { + Value = (Model as ITextCell)?.Text; + } + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); diff --git a/tests/Avalonia.Controls.TreeDataGrid.Tests/Models/TextCellTests.cs b/tests/Avalonia.Controls.TreeDataGrid.Tests/Models/TextCellTests.cs index f79239af..66d2c2d3 100644 --- a/tests/Avalonia.Controls.TreeDataGrid.Tests/Models/TextCellTests.cs +++ b/tests/Avalonia.Controls.TreeDataGrid.Tests/Models/TextCellTests.cs @@ -63,7 +63,7 @@ public void Modified_Value_Is_Written_To_Binding_On_EndEdit() target.Text = "new"; Assert.Equal("new", target.Text); - Assert.Equal("new", target.Value); + Assert.Equal("initial", target.Value); Assert.Equal(new[] { "initial"}, result); target.EndEdit(); @@ -86,7 +86,7 @@ public void Modified_Value_Is_Not_Written_To_Binding_On_CancelEdit() target.Text = "new"; Assert.Equal("new", target.Text); - Assert.Equal("new", target.Value); + Assert.Equal("initial", target.Value); Assert.Equal(new[] { "initial" }, result); target.CancelEdit(); @@ -104,7 +104,7 @@ public void Initial_Int_Value_Is_Formatted() var binding = new BehaviorSubject>(42); var target = new TextCell(binding, true, GetOptions()); - Assert.Equal("foo42", target.Text); + Assert.Equal("42.00", target.Text); Assert.Equal(42, target.Value); } @@ -112,7 +112,7 @@ public void Initial_Int_Value_Is_Formatted() public void Int_Value_Is_Formatted_After_Editing() { var binding = new BehaviorSubject>(42); - var target = new TextCell(binding, false); + var target = new TextCell(binding, false, GetOptions()); var result = new List(); binding.Subscribe(x => result.Add(x.Value)); @@ -121,17 +121,17 @@ public void Int_Value_Is_Formatted_After_Editing() target.Text = "43"; Assert.Equal("43", target.Text); - Assert.Equal(43, target.Value); + Assert.Equal(42, target.Value); Assert.Equal(new[] { 42 }, result); target.EndEdit(); - Assert.Equal("43.0", target.Text); + Assert.Equal("43.00", target.Text); Assert.Equal(43, target.Value); Assert.Equal(new[] { 42, 43 }, result); } - private ITextCellOptions? GetOptions(string format = "foo{0}") + private ITextCellOptions? GetOptions(string format = "{0:n2}") { return new TextColumnOptions { StringFormat = format }; }