Add ProcessFilter

This commit is contained in:
CHINBOY
2025-06-28 16:16:17 +08:00
parent b384f5c884
commit 7cd8ce766b
9 changed files with 138 additions and 17 deletions
@@ -248,9 +248,17 @@ public abstract partial class DataGridColumn : AvaloniaObject
public bool CanUserFilter
{
get => CanUserResizeInternal ??
OwningGrid?.CanUserFilterColumns ??
DataGrid.DefaultCanUserResizeColumns;
get
{
var canUserFilter = CanUserResizeInternal ??
OwningGrid?.CanUserFilterColumns ??
DataGrid.DefaultCanUserFilterColumns;
if (HasHeaderCell)
{
HeaderCell.CanUserFilter = canUserFilter;
}
return canUserFilter;
}
set
{
CanUserFilterInternal = value;
@@ -4,6 +4,7 @@
// All other rights reserved.
using System.Diagnostics;
using AtomUI.Controls.Data;
using Avalonia;
namespace AtomUI.Controls;
@@ -15,29 +16,111 @@ internal partial class DataGridColumnHeader
nameof(CanUserFilter),
o => o.CanUserFilter,
(o, v) => o.CanUserFilter = v);
private bool _canUserFilter = false;
internal bool CanUserFilter
{
get => _canUserFilter;
set => SetAndRaise(CanUserFilterProperty, ref _canUserFilter, value);
}
internal void InvokeProcessSort()
private DataGridFilterIndicator? _filterIndicator;
internal void InvokeProcessFilter(List<string> filterValues)
{
Debug.Assert(OwningGrid != null);
if (OwningGrid.WaitForLostFocus(InvokeProcessSort))
if (OwningGrid.WaitForLostFocus(() => InvokeProcessFilter(filterValues)))
{
return;
}
if (OwningGrid.CommitEdit(DataGridEditingUnit.Row, exitEditingMode: true))
{
Avalonia.Threading.Dispatcher.UIThread.Post(ProcessSort);
Avalonia.Threading.Dispatcher.UIThread.Post(() => ProcessFilter(filterValues));
}
}
internal void ProcessSort()
internal void ProcessFilter(List<string> filterValues)
{
if (OwningColumn != null &&
OwningGrid != null &&
OwningGrid.EditingRow == null &&
OwningColumn != OwningGrid.ColumnsInternal.FillerColumn &&
(OwningColumn.CanUserFilter || OwningGrid.CanUserFilterColumns))
{
var ea = new DataGridColumnEventArgs(OwningColumn);
OwningGrid.HandleColumnFiltering(ea);
if (!ea.Handled && OwningGrid.DataConnection.AllowFilter &&
OwningGrid.DataConnection.FilterDescriptions != null)
{
DataGrid owningGrid = OwningGrid;
DataGridFilterDescription? newFilter;
DataGridFilterDescription? filter = OwningColumn.GetFilterDescription();
IDataGridCollectionView? collectionView = owningGrid.DataConnection.CollectionView;
Debug.Assert(collectionView != null);
using (collectionView.DeferRefresh())
{
if (owningGrid.DataConnection.FilterDescriptions.Count == 0)
{
owningGrid.DataConnection.FilterDescriptions.Clear();
}
if (filter != null)
{
// 比较一下值,如果过滤的值不相等就重新添加
var oldFilterValues = filter.FilterConditions.ToHashSet();
var newFilterValues = filterValues.ToHashSet();
if (!oldFilterValues.SetEquals(newFilterValues))
{
newFilter = new DataGridFilterDescription()
{
PropertyPath = filter.PropertyPath,
Filter = filter.Filter,
FilterConditions = filterValues.Cast<object>().ToList(),
};
int oldIndex = owningGrid.DataConnection.FilterDescriptions.IndexOf(filter);
if (oldIndex >= 0)
{
owningGrid.DataConnection.FilterDescriptions.Remove(filter);
owningGrid.DataConnection.FilterDescriptions.Insert(oldIndex, newFilter);
}
else
{
owningGrid.DataConnection.FilterDescriptions.Add(newFilter);
}
}
}
else
{
string? propertyName = OwningColumn.GetFilterPropertyName();
if (string.IsNullOrEmpty(propertyName))
{
return;
}
newFilter = new DataGridFilterDescription()
{
PropertyPath = propertyName,
Filter = OwningColumn.OnFilter,
FilterConditions = filterValues.Cast<object>().ToList(),
};
owningGrid.DataConnection.FilterDescriptions.Add(newFilter);
}
}
}
}
}
private void ConfigureFilterIndicator()
{
if (_filterIndicator != null)
{
_filterIndicator.FilterRequest += HandleFilterRequest;
}
}
private void HandleFilterRequest(object? sender, DataGridColumnFilterEventArgs args)
{
InvokeProcessFilter(args.FilterValues);
}
}
@@ -201,7 +201,6 @@ internal partial class DataGridColumnHeader : ContentControl
private bool _desiredSeparatorVisibility = true;
private StackPanel? _indicatorsLayout;
private static Lazy<Cursor> _resizeCursor = new Lazy<Cursor>(() => new Cursor(StandardCursorType.SizeWestEast));
private DataGridFilterIndicator? _filterIndicator;
private Border? _frame;
static DataGridColumnHeader()
@@ -863,6 +862,8 @@ internal partial class DataGridColumnHeader : ContentControl
{
_filterIndicator.OwningColumn = OwningColumn;
}
ConfigureFilterIndicator();
if (_indicatorsLayout != null)
{
_indicatorsLayout.Children.CollectionChanged += HandleIndicatorLayoutChildrenChanged;
@@ -26,6 +26,8 @@ internal class DataGridFilterIndicator : IconButton
public static readonly StyledProperty<bool> FilterMultipleProperty =
AvaloniaProperty.Register<DataGridFilterIndicator, bool>(nameof(FilterMultiple));
public event EventHandler<DataGridColumnFilterEventArgs>? FilterRequest;
public bool IsFilterActivated
{
@@ -242,6 +244,11 @@ internal class DataGridFilterIndicator : IconButton
private void HandleFilterValuesSelected(object? sender, DataGridFilterValuesSelectedEventArgs args)
{
Debug.Assert(OwningColumn != null);
if (OwningColumn.FilterOnClose || args.IsConfirmed)
{
FilterRequest?.Invoke(this, new DataGridColumnFilterEventArgs(OwningColumn, args.Values));
}
}
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
@@ -101,6 +101,22 @@ internal class DataGridDataConnection
return CollectionView.CanSort;
}
}
/// <summary>
/// True if the collection view says it can filter.
/// </summary>
public bool AllowFilter
{
get
{
if (CollectionView == null ||
(EditableCollectionView != null && (EditableCollectionView.IsAddingNew || EditableCollectionView.IsEditingItem)))
{
return false;
}
return CollectionView.CanFilter;
}
}
public bool CommittingEdit { get; private set; }
@@ -8,8 +8,7 @@ public class DataGridFilterDescription
public string? PropertyPath { get; set; }
public bool HasPropertyPath => !string.IsNullOrEmpty(PropertyPath);
public StringComparison ComparisonType { get; } = StringComparison.InvariantCultureIgnoreCase;
public bool IsEnabled { get; set; }
public int ColumnIndex { get; set; }
public List<object> FilterConditions { get; set; } = new List<object>();
public Func<object, object, bool>? Filter { get; set; }
@@ -119,6 +119,11 @@ public partial class DataGrid
{
Sorting?.Invoke(this, e);
}
protected internal virtual void HandleColumnFiltering(DataGridColumnEventArgs e)
{
Filtering?.Invoke(this, e);
}
/// <summary>
/// Adjusts the widths of all columns with DisplayIndex >= displayIndex such that the total
+5
View File
@@ -718,6 +718,11 @@ public partial class DataGrid : TemplatedControl,
/// Occurs when the <see cref="DataGridColumn"/> sorting request is triggered.
/// </summary>
public event EventHandler<DataGridColumnEventArgs>? Sorting;
/// <summary>
/// Occurs when the <see cref="DataGridColumn"/> filtering request is triggered.
/// </summary>
public event EventHandler<DataGridColumnEventArgs>? Filtering;
/// <summary>
/// Occurs when a <see cref="T:AtomUI.Controls.DataGridRow" />
@@ -2,16 +2,13 @@ namespace AtomUI.Controls;
public class DataGridColumnFilterEventArgs : EventArgs
{
public DataGridFilterMode FilterMode { get; }
public List<string> FilterValues { get; }
public DataGridColumn Column { get; }
public DataGridColumnFilterEventArgs(DataGridColumn column, DataGridFilterMode filterMode,
List<string> filterValues)
public DataGridColumnFilterEventArgs(DataGridColumn column, List<string> filterValues)
{
Column = column;
FilterMode = filterMode;
FilterValues = filterValues;
}
}