Add Cell edit for datagrid

This commit is contained in:
chinboy
2025-07-16 17:07:34 +08:00
parent f79cbeffb8
commit e5cc862701
7 changed files with 54 additions and 83 deletions
+10 -21
View File
@@ -17,43 +17,32 @@ internal static class InstancedBindingFactory
return InstancedBinding.OneTime(observable, priority);
}
return InstancedBinding.OneTime(Observable.Return(source), priority);
} else if (mode == BindingMode.OneWay)
}
if (mode == BindingMode.OneWay)
{
if (source is IObservable<object?> observable)
{
return InstancedBinding.OneWay(observable, priority);
}
else
{
throw new ArgumentException("source type must be IObservable<object?>.");
}
throw new ArgumentException("source type must be IObservable<object?>.");
}
else if (mode == BindingMode.OneWayToSource)
if (mode == BindingMode.OneWayToSource)
{
if (source is IObserver<object?> observer)
{
return InstancedBinding.OneWayToSource(observer, priority);
}
else
{
throw new ArgumentException("source type must be IObserver<object?>.");
}
throw new ArgumentException("source type must be IObserver<object?>.");
}
else if (mode == BindingMode.TwoWay)
if (mode == BindingMode.TwoWay)
{
if (source is IObserver<object?> observer)
if (source is IObserver<object?> observer && source is IObservable<object?> observable)
{
return InstancedBinding.OneWayToSource(observer, priority);
return InstancedBinding.TwoWay(observable, observer, priority);
}
else
{
throw new ArgumentException("source type must be IObserver<object?>.");
}
}
else
{
throw new ArgumentException("mode must be OneTime, OneWay or OneWayToSource.");
throw new ArgumentException("source type must be IObserver<object?> and IObservable<object?>.");
}
throw new ArgumentException("mode must be OneTime, OneWay or OneWayToSource.");
}
}
@@ -106,9 +106,13 @@ internal class CellEditBinding : ICellEditBinding
if (value is BindingNotification notification)
{
if (notification.ErrorType != BindingErrorType.None)
{
OnValidationError(notification);
}
else
{
OnValidValue(value);
}
}
else
{
@@ -121,6 +125,7 @@ internal class CellEditBinding : ICellEditBinding
_subscription?.Dispose();
_subscription = null;
}
protected override void Initialize()
{
_subscription = _sourceSubject.Subscribe(OnSourceValueUpdated);
@@ -130,10 +135,12 @@ internal class CellEditBinding : ICellEditBinding
{
throw new NotImplementedException();
}
void IObserver<object?>.OnError(Exception error)
{
throw new NotImplementedException();
}
void IObserver<object?>.OnNext(object? value)
{
OnControlValueUpdated(value);
@@ -15,7 +15,6 @@ using Avalonia.Controls.Primitives;
using Avalonia.Controls.Shapes;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Rendering;
namespace AtomUI.Controls;
@@ -386,9 +385,4 @@ public class DataGridCell : ContentControl
_compositeDisposable.Dispose();
_compositeDisposable.Clear();
}
// public bool HitTest(Point point)
// {
// return true;
// }
}
@@ -112,27 +112,13 @@ public class DataGridTextColumn : DataGridBoundColumn
set => SetValue(ForegroundProperty, value);
}
#endregion
private readonly Lazy<ControlTheme?> _cellTextBoxTheme;
private readonly Lazy<ControlTheme?> _cellTextBlockTheme;
/// <summary>
/// Initializes a new instance of the <see cref="T:AtomUI.Controls.DataGridTextColumn" /> class.
/// </summary>
public DataGridTextColumn()
{
BindingTarget = TextBox.TextProperty;
_cellTextBoxTheme = new Lazy<ControlTheme?>(() =>
{
Debug.Assert(OwningGrid != null);
return OwningGrid.TryFindResource("DataGridCellTextBoxTheme", out var theme) ? (ControlTheme?)theme : null;
});
_cellTextBlockTheme = new Lazy<ControlTheme?>(() =>
{
Debug.Assert(OwningGrid != null);
return OwningGrid.TryFindResource("DataGridCellTextBlockTheme", out var theme) ? (ControlTheme?)theme : null;
});
BindingTarget = LineEdit.TextProperty;
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
@@ -156,7 +142,7 @@ public class DataGridTextColumn : DataGridBoundColumn
/// <param name="uneditedValue">The previous, unedited value in the cell being edited.</param>
protected override void CancelCellEdit(Control editingElement, object uneditedValue)
{
if (editingElement is TextBox textBox)
if (editingElement is LineEdit textBox)
{
string? uneditedString = uneditedValue as string;
textBox.Text = uneditedString ?? string.Empty;
@@ -171,18 +157,12 @@ public class DataGridTextColumn : DataGridBoundColumn
/// <returns>A new <see cref="T:AtomUI.Controls.TextBox" /> control that is bound to the column's <see cref="P:AtomUI.Controls.DataGridBoundColumn.Binding" /> property value.</returns>
protected override Control GenerateEditingElementDirect(DataGridCell cell, object dataItem)
{
var textBox = new TextBox
var lineEdit = new LineEdit
{
Name = "CellTextBox"
};
if (_cellTextBoxTheme.Value is { } theme)
{
textBox.Theme = theme;
}
SyncProperties(textBox);
return textBox;
SyncProperties(lineEdit);
return lineEdit;
}
/// <summary>
@@ -197,10 +177,6 @@ public class DataGridTextColumn : DataGridBoundColumn
{
Name = "CellTextBlock"
};
if (_cellTextBlockTheme.Value is { } theme)
{
textBlockElement.Theme = theme;
}
SyncProperties(textBlockElement);
@@ -219,22 +195,22 @@ public class DataGridTextColumn : DataGridBoundColumn
/// <returns>The unedited value. </returns>
protected override object PrepareCellForEdit(Control editingElement, RoutedEventArgs editingEventArgs)
{
if (editingElement is TextBox textBox)
if (editingElement is LineEdit lineEdit)
{
string uneditedText = textBox.Text ?? String.Empty;
string uneditedText = lineEdit.Text ?? string.Empty;
int len = uneditedText.Length;
if (editingEventArgs is KeyEventArgs keyEventArgs && keyEventArgs.Key == Key.F2)
{
// Put caret at the end of the text
textBox.SelectionStart = len;
textBox.SelectionEnd = len;
lineEdit.SelectionStart = len;
lineEdit.SelectionEnd = len;
}
else
{
// Select all text
textBox.SelectionStart = 0;
textBox.SelectionEnd = len;
textBox.CaretIndex = len;
lineEdit.SelectionStart = 0;
lineEdit.SelectionEnd = len;
lineEdit.CaretIndex = len;
}
return uneditedText;
@@ -1181,7 +1181,7 @@ public sealed class DataGridCollectionView : IDataGridCollectionView, IDataGridE
{
throw new InvalidOperationException(GetOperationNotAllowedText(nameof(CancelEdit), nameof(AddNew)));
}
else if (!CanCancelEdit)
if (!CanCancelEdit)
{
throw new InvalidOperationException("CancelEdit is not supported for the current edit item.");
}
@@ -1504,7 +1504,7 @@ public partial class DataGrid
private bool BeginCellEdit(RoutedEventArgs editingEventArgs)
{
if (CurrentColumnIndex == -1 || !GetRowSelection(CurrentSlot))
if (CurrentColumnIndex == -1)
{
return false;
}
@@ -1554,7 +1554,6 @@ public partial class DataGrid
if (e.Cancel
|| currentRowIndex != CurrentSlot
|| currentColumnIndex != CurrentColumnIndex
|| !GetRowSelection(CurrentSlot)
|| (EditingRow == null && !BeginRowEdit(dataGridRow)))
{
// If either BeginningEdit was canceled, currency/selection was changed in the event handler,
@@ -4256,26 +4255,30 @@ public partial class DataGrid
action = DataGridSelectionAction.AddCurrentToSelection;
}
}
var updateSelection = true;
var column = ColumnsInternal[columnIndex];
if (column is DataGridSelectionColumn selectionColumn)
{
var row = DisplayData.GetDisplayedElement(slot) as DataGridRow;
Debug.Assert(row != null);
var dataGridCell = row.Cells[columnIndex];
updateSelection = selectionColumn.NotifyAboutToUpdateSelection(pointerPressedEventArgs, dataGridCell);
if (updateSelection)
{
action = selectionColumn.GetSelectionAction(dataGridCell);
}
}
}
else
{
action = DataGridSelectionAction.SelectCurrent;
}
var updateSelection = true;
var column = ColumnsInternal[columnIndex];
if (column is DataGridSelectionColumn selectionColumn)
{
var row = DisplayData.GetDisplayedElement(slot) as DataGridRow;
Debug.Assert(row != null);
var dataGridCell = row.Cells[columnIndex];
updateSelection = selectionColumn.NotifyAboutToUpdateSelection(pointerPressedEventArgs, dataGridCell);
if (updateSelection)
{
UpdateSelectionAndCurrency(columnIndex, slot, action, scrollIntoView: false);
action = selectionColumn.GetSelectionAction(dataGridCell);
}
}
if (updateSelection)
{
UpdateSelectionAndCurrency(columnIndex, slot, action, scrollIntoView: false);
}
}
finally
{
@@ -55,7 +55,9 @@
</Setter>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="ClipToBounds" Value="False"/>
<Setter Property="Background" Value="Transparent"/>