mirror of
https://gitee.com/ant-design-blazor/ant-design-blazor.git
synced 2024-12-05 05:27:37 +08:00
fix(module: table): fix DataIndex Column with incorrect sorting and filter (#1295)
* refactor(module: table): Unify the behavior of Field and DataIndex * fix(module: table): Fix DataIndex Column doesn't refresh * doc(module: table): add DataIndex column filter demo * doc(module: table): fix Blazor table Co-authored-by: James Yeung <shunjiey@hotmail.com>
This commit is contained in:
parent
527f39456b
commit
3bf616b735
@ -102,11 +102,11 @@ else if (IsBody && RowSpan != 0 && ColSpan != 0)
|
|||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(Format))
|
if (!string.IsNullOrWhiteSpace(Format))
|
||||||
{
|
{
|
||||||
@(Formatter<TData>.Format(GetValue != null ? GetValue(RowData) : Field, Format))
|
@(Formatter<TData>.Format(Field, Format))
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@(GetValue != null ? GetValue(RowData) : Field)
|
@Field
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
using AntDesign.Core.Reflection;
|
using AntDesign.Core.Reflection;
|
||||||
using AntDesign.Internal;
|
using AntDesign.Internal;
|
||||||
using AntDesign.TableModels;
|
using AntDesign.TableModels;
|
||||||
@ -25,7 +27,22 @@ namespace AntDesign
|
|||||||
public RenderFragment<TData> CellRender { get; set; }
|
public RenderFragment<TData> CellRender { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public TData Field { get; set; }
|
public TData Field
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetValue != null ? GetValue(RowData) : _field;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (GetValue == null)
|
||||||
|
{
|
||||||
|
_field = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TData _field;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string DataIndex { get; set; }
|
public string DataIndex { get; set; }
|
||||||
@ -75,11 +92,9 @@ namespace AntDesign
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public Expression<Func<TData, TData, bool>> OnFilter { get; set; }
|
public Expression<Func<TData, TData, bool>> OnFilter { get; set; }
|
||||||
|
|
||||||
private PropertyReflector? _propertyReflector;
|
public string DisplayName { get; private set; }
|
||||||
|
|
||||||
public string DisplayName => _propertyReflector?.DisplayName;
|
public string FieldName { get; private set; }
|
||||||
|
|
||||||
public string FieldName => _propertyReflector?.PropertyName;
|
|
||||||
|
|
||||||
public ITableSortModel SortModel { get; private set; }
|
public ITableSortModel SortModel { get; private set; }
|
||||||
|
|
||||||
@ -89,12 +104,16 @@ namespace AntDesign
|
|||||||
|
|
||||||
public Func<RowData, TData> GetValue { get; private set; }
|
public Func<RowData, TData> GetValue { get; private set; }
|
||||||
|
|
||||||
|
public LambdaExpression GetFieldExpression { get; private set; }
|
||||||
|
|
||||||
void IFieldColumn.ClearSorter() => SetSorter(SortDirection.None);
|
void IFieldColumn.ClearSorter() => SetSorter(SortDirection.None);
|
||||||
|
|
||||||
private static readonly EventCallbackFactory _callbackFactory = new EventCallbackFactory();
|
private static readonly EventCallbackFactory _callbackFactory = new EventCallbackFactory();
|
||||||
|
|
||||||
private bool _filterOpened;
|
private bool _filterOpened;
|
||||||
|
|
||||||
private bool _hasFilterSelected;
|
private bool _hasFilterSelected;
|
||||||
|
|
||||||
private string[] _selectedFilterValues;
|
private string[] _selectedFilterValues;
|
||||||
|
|
||||||
private ElementReference _filterTriggerRef;
|
private ElementReference _filterTriggerRef;
|
||||||
@ -109,19 +128,26 @@ namespace AntDesign
|
|||||||
{
|
{
|
||||||
if (FieldExpression != null)
|
if (FieldExpression != null)
|
||||||
{
|
{
|
||||||
_propertyReflector = PropertyReflector.Create(FieldExpression);
|
var paramExp = Expression.Parameter(ItemType);
|
||||||
|
var member = ColumnExpressionHelper.GetReturnMemberInfo(FieldExpression);
|
||||||
|
var bodyExp = Expression.MakeMemberAccess(paramExp, member);
|
||||||
|
GetFieldExpression = Expression.Lambda(bodyExp, paramExp);
|
||||||
|
}
|
||||||
|
else if (DataIndex != null)
|
||||||
|
{
|
||||||
|
(_, GetFieldExpression) = ColumnDataIndexHelper<TData>.GetDataIndexConfig(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Sortable)
|
if (Sortable && GetFieldExpression != null)
|
||||||
{
|
{
|
||||||
if (_propertyReflector.HasValue)
|
SortModel = new SortModel<TData>(GetFieldExpression, SorterMultiple, DefaultSortOrder, SorterCompare);
|
||||||
{
|
}
|
||||||
SortModel = new SortModel<TData>(_propertyReflector.Value.PropertyInfo, SorterMultiple, DefaultSortOrder, SorterCompare);
|
|
||||||
}
|
if (GetFieldExpression != null)
|
||||||
else
|
{
|
||||||
{
|
var member = ColumnExpressionHelper.GetReturnMemberInfo(GetFieldExpression);
|
||||||
(GetValue, SortModel) = ColumnDataIndexHelper<TData>.GetDataIndexConfig(this);
|
DisplayName = member.GetCustomAttribute<DisplayNameAttribute>(true)?.DisplayName ?? member.Name;
|
||||||
}
|
FieldName = member.Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (IsBody)
|
else if (IsBody)
|
||||||
@ -137,8 +163,8 @@ namespace AntDesign
|
|||||||
_sortDirection = SortModel?.SortDirection ?? DefaultSortOrder ?? SortDirection.None;
|
_sortDirection = SortModel?.SortDirection ?? DefaultSortOrder ?? SortDirection.None;
|
||||||
|
|
||||||
ClassMapper
|
ClassMapper
|
||||||
.If("ant-table-column-has-sorters", () => Sortable)
|
.If("ant-table-column-has-sorters", () => Sortable)
|
||||||
.If($"ant-table-column-sort", () => Sortable && SortModel != null && SortModel.SortDirection.IsIn(SortDirection.Ascending, SortDirection.Descending));
|
.If($"ant-table-column-sort", () => Sortable && SortModel != null && SortModel.SortDirection.IsIn(SortDirection.Ascending, SortDirection.Descending));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleSort()
|
private void HandleSort()
|
||||||
@ -187,6 +213,7 @@ namespace AntDesign
|
|||||||
{
|
{
|
||||||
_sortDirection = sortDirection;
|
_sortDirection = sortDirection;
|
||||||
SortModel.SetSortDirection(sortDirection);
|
SortModel.SetSortDirection(sortDirection);
|
||||||
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FilterSelected(TableFilter<TData> filter)
|
private void FilterSelected(TableFilter<TData> filter)
|
||||||
@ -210,7 +237,7 @@ namespace AntDesign
|
|||||||
_filterOpened = false;
|
_filterOpened = false;
|
||||||
_hasFilterSelected = Filters?.Any(x => x.Selected) == true;
|
_hasFilterSelected = Filters?.Any(x => x.Selected) == true;
|
||||||
|
|
||||||
FilterModel = _hasFilterSelected ? new FilterModel<TData>(_propertyReflector.Value.PropertyInfo, OnFilter, Filters.Where(x => x.Selected).ToList()) : null;
|
FilterModel = _hasFilterSelected ? new FilterModel<TData>(GetFieldExpression, OnFilter, Filters.Where(x => x.Selected).ToList()) : null;
|
||||||
|
|
||||||
Table?.ReloadAndInvokeChange();
|
Table?.ReloadAndInvokeChange();
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,9 @@ namespace AntDesign.Internal
|
|||||||
|
|
||||||
private static ColumnCacheItem CreateDataIndexConfig(ColumnCacheKey key)
|
private static ColumnCacheItem CreateDataIndexConfig(ColumnCacheKey key)
|
||||||
{
|
{
|
||||||
var (itemType, propType, dataIndex, sortable, sort, sorterMultiple, sorterCompare) = key;
|
var (itemType, propType, dataIndex) = key;
|
||||||
Func<RowData, TProp> getValue = null;
|
Func<RowData, TProp> getValue = null;
|
||||||
ITableSortModel sortModel = null;
|
LambdaExpression getFieldExpression = null;
|
||||||
var properties = dataIndex?.Split(".");
|
var properties = dataIndex?.Split(".");
|
||||||
if (properties is {Length: > 0})
|
if (properties is {Length: > 0})
|
||||||
{
|
{
|
||||||
@ -40,21 +40,17 @@ namespace AntDesign.Internal
|
|||||||
var rowData1Exp = Expression.TypeAs(rowDataExp, rowData1Type);
|
var rowData1Exp = Expression.TypeAs(rowDataExp, rowData1Type);
|
||||||
var dataMemberExp = Expression.Property(rowData1Exp, nameof(RowData<object>.Data));
|
var dataMemberExp = Expression.Property(rowData1Exp, nameof(RowData<object>.Data));
|
||||||
|
|
||||||
Expression memberExp = canBeNull
|
var memberExp = canBeNull
|
||||||
? dataMemberExp.AccessNullableProperty(properties)
|
? dataMemberExp.AccessNullableProperty(properties)
|
||||||
: dataMemberExp.AccessProperty(properties);
|
: dataMemberExp.AccessProperty(properties);
|
||||||
getValue = Expression.Lambda<Func<RowData, TProp>>(memberExp, rowDataExp).Compile();
|
getValue = Expression.Lambda<Func<RowData, TProp>>(memberExp, rowDataExp).Compile();
|
||||||
|
|
||||||
if (sortable)
|
getFieldExpression = canBeNull
|
||||||
{
|
? itemType.BuildAccessNullablePropertyLambdaExpression(properties)
|
||||||
var propertySelector = canBeNull
|
: itemType.BuildAccessPropertyLambdaExpression(properties);
|
||||||
? itemType.BuildAccessNullablePropertyLambdaExpression(properties)
|
|
||||||
: itemType.BuildAccessPropertyLambdaExpression(properties);
|
|
||||||
sortModel = new DataIndexSortModel<TProp>(dataIndex, propertySelector, sorterMultiple, sort, sorterCompare);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ColumnCacheItem(getValue, sortModel);
|
return new ColumnCacheItem(getValue, getFieldExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal readonly struct ColumnCacheKey
|
internal readonly struct ColumnCacheKey
|
||||||
@ -65,39 +61,23 @@ namespace AntDesign.Internal
|
|||||||
|
|
||||||
internal readonly string DataIndex;
|
internal readonly string DataIndex;
|
||||||
|
|
||||||
internal readonly bool Sortable;
|
|
||||||
|
|
||||||
internal readonly SortDirection DefaultSortOrder;
|
|
||||||
|
|
||||||
internal readonly int SorterMultiple;
|
|
||||||
|
|
||||||
internal readonly Func<TProp, TProp, int> SorterCompare;
|
|
||||||
|
|
||||||
internal static ColumnCacheKey Create(Column<TProp> column)
|
internal static ColumnCacheKey Create(Column<TProp> column)
|
||||||
{
|
{
|
||||||
return new(column.ItemType, typeof(TProp), column.DataIndex, column.Sortable, column.DefaultSortOrder, column.SorterMultiple, column.SorterCompare);
|
return new(column.ItemType, typeof(TProp), column.DataIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal ColumnCacheKey(Type itemType, Type propType, string dataIndex, bool sortable, SortDirection defaultSortOrder, int sorterMultiple, Func<TProp, TProp, int> sorterCompare)
|
internal ColumnCacheKey(Type itemType, Type propType, string dataIndex)
|
||||||
{
|
{
|
||||||
ItemType = itemType;
|
ItemType = itemType;
|
||||||
PropType = propType;
|
PropType = propType;
|
||||||
DataIndex = dataIndex;
|
DataIndex = dataIndex;
|
||||||
Sortable = sortable;
|
|
||||||
DefaultSortOrder = defaultSortOrder;
|
|
||||||
SorterMultiple = sorterMultiple;
|
|
||||||
SorterCompare = sorterCompare;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Deconstruct(out Type itemType, out Type propType, out string dataIndex, out bool sortable, out SortDirection defaultSortOrder, out int sorterMultiple, out Func<TProp, TProp, int> sorterCompare)
|
internal void Deconstruct(out Type itemType, out Type propType, out string dataIndex)
|
||||||
{
|
{
|
||||||
itemType = ItemType;
|
itemType = ItemType;
|
||||||
propType = PropType;
|
propType = PropType;
|
||||||
dataIndex = DataIndex;
|
dataIndex = DataIndex;
|
||||||
sortable = Sortable;
|
|
||||||
defaultSortOrder = DefaultSortOrder;
|
|
||||||
sorterMultiple = SorterMultiple;
|
|
||||||
sorterCompare = SorterCompare;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,18 +85,18 @@ namespace AntDesign.Internal
|
|||||||
{
|
{
|
||||||
internal readonly Func<RowData, TProp> GetValue;
|
internal readonly Func<RowData, TProp> GetValue;
|
||||||
|
|
||||||
internal readonly ITableSortModel SortModel;
|
internal readonly LambdaExpression GetFieldExpression;
|
||||||
|
|
||||||
internal ColumnCacheItem(Func<RowData, TProp> getValue, ITableSortModel sortModel)
|
internal ColumnCacheItem(Func<RowData, TProp> getValue, LambdaExpression getFieldExpression)
|
||||||
{
|
{
|
||||||
GetValue = getValue;
|
GetValue = getValue;
|
||||||
SortModel = sortModel;
|
GetFieldExpression = getFieldExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Deconstruct(out Func<RowData, TProp> getValue, out ITableSortModel sortModel)
|
internal void Deconstruct(out Func<RowData, TProp> getValue, out LambdaExpression getFieldExpression)
|
||||||
{
|
{
|
||||||
getValue = GetValue;
|
getValue = GetValue;
|
||||||
sortModel = SortModel;
|
getFieldExpression = GetFieldExpression;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
37
components/table/Internal/ColumnExpressionHelper.cs
Normal file
37
components/table/Internal/ColumnExpressionHelper.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace AntDesign.Internal
|
||||||
|
{
|
||||||
|
internal static class ColumnExpressionHelper
|
||||||
|
{
|
||||||
|
internal static MemberInfo GetReturnMemberInfo(LambdaExpression expression)
|
||||||
|
{
|
||||||
|
var accessorBody = expression.Body;
|
||||||
|
|
||||||
|
if (accessorBody is UnaryExpression unaryExpression
|
||||||
|
&& unaryExpression.NodeType == ExpressionType.Convert
|
||||||
|
&& unaryExpression.Type == typeof(object))
|
||||||
|
{
|
||||||
|
accessorBody = unaryExpression.Operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accessorBody is ConditionalExpression conditionalExpression)
|
||||||
|
{
|
||||||
|
accessorBody = conditionalExpression.IfTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(accessorBody is MemberExpression memberExpression))
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"The type of the provided expression {accessorBody.GetType().Name} is not supported, it should be {nameof(MemberExpression)}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return memberExpression.Member;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -182,7 +182,7 @@ RenderFragment<(Table<TItem> table, IEnumerable<TItem> showItems, int level)> bo
|
|||||||
|
|
||||||
<tr @attributes="rowAttributes"
|
<tr @attributes="rowAttributes"
|
||||||
data-row-key="@(rowIndex-1)" class="ant-table-row ant-table-row-level-@level @(currentRowData.Selected ? "ant-table-row-selected" : "") @table.RowClassName(currentRowData) @rowAttributes?.GetValueOrDefault("class")">
|
data-row-key="@(rowIndex-1)" class="ant-table-row ant-table-row-level-@level @(currentRowData.Selected ? "ant-table-row-selected" : "") @table.RowClassName(currentRowData) @rowAttributes?.GetValueOrDefault("class")">
|
||||||
<CascadingValue Value="currentRowData" Name="RowData" IsFixed>
|
<CascadingValue Value="currentRowData" Name="RowData" IsFixed="false">
|
||||||
<CascadingValue Value="true" Name="IsBody" IsFixed>
|
<CascadingValue Value="true" Name="IsBody" IsFixed>
|
||||||
@table.ChildContent(data)
|
@table.ChildContent(data)
|
||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
|
|
||||||
namespace AntDesign.TableModels
|
|
||||||
{
|
|
||||||
public class DataIndexSortModel<TField> : ITableSortModel, IComparer<TField>
|
|
||||||
{
|
|
||||||
private readonly LambdaExpression _propertySelect;
|
|
||||||
|
|
||||||
private readonly Func<TField, TField, int> _comparer;
|
|
||||||
|
|
||||||
public int Priority { get; }
|
|
||||||
|
|
||||||
public string FieldName { get; }
|
|
||||||
|
|
||||||
public string Sort => _sortDirection?.Name;
|
|
||||||
|
|
||||||
SortDirection ITableSortModel.SortDirection => _sortDirection;
|
|
||||||
|
|
||||||
private SortDirection _sortDirection;
|
|
||||||
|
|
||||||
public DataIndexSortModel(string dataIndex, LambdaExpression propertySelect, int priority, SortDirection sortDirection, Func<TField, TField, int> comparer)
|
|
||||||
{
|
|
||||||
this.FieldName = dataIndex;
|
|
||||||
this._propertySelect = propertySelect;
|
|
||||||
this._comparer = comparer;
|
|
||||||
this.Priority = priority;
|
|
||||||
this._sortDirection = sortDirection ?? SortDirection.None;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ITableSortModel.SetSortDirection(SortDirection sortDirection)
|
|
||||||
{
|
|
||||||
_sortDirection = sortDirection;
|
|
||||||
}
|
|
||||||
|
|
||||||
IOrderedQueryable<TItem> ITableSortModel.SortList<TItem>(IQueryable<TItem> source)
|
|
||||||
{
|
|
||||||
if (_sortDirection == SortDirection.None)
|
|
||||||
{
|
|
||||||
return source as IOrderedQueryable<TItem>;
|
|
||||||
}
|
|
||||||
|
|
||||||
var lambda = (Expression<Func<TItem, TField>>)_propertySelect;
|
|
||||||
|
|
||||||
if (_sortDirection == SortDirection.Ascending)
|
|
||||||
{
|
|
||||||
return _comparer == null ? source.OrderBy(lambda) : source.OrderBy(lambda, this);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return _comparer == null ? source.OrderByDescending(lambda) : source.OrderByDescending(lambda, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public int Compare(TField x, TField y)
|
|
||||||
{
|
|
||||||
return _comparer?.Invoke(x, y) ?? 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace AntDesign.TableModels
|
namespace AntDesign.TableModels
|
||||||
{
|
{
|
||||||
@ -16,12 +15,12 @@ namespace AntDesign.TableModels
|
|||||||
|
|
||||||
public Expression<Func<TField, TField, bool>> OnFilter { get; set; }
|
public Expression<Func<TField, TField, bool>> OnFilter { get; set; }
|
||||||
|
|
||||||
private PropertyInfo _propertyInfo;
|
public LambdaExpression GetFieldExpression { get; set; }
|
||||||
|
|
||||||
public FilterModel(PropertyInfo propertyInfo, Expression<Func<TField, TField, bool>> onFilter, IList<TableFilter<TField>> filters)
|
public FilterModel(LambdaExpression getFieldExpression, Expression<Func<TField, TField, bool>> onFilter, IList<TableFilter<TField>> filters)
|
||||||
{
|
{
|
||||||
this._propertyInfo = propertyInfo;
|
this.GetFieldExpression = getFieldExpression;
|
||||||
this.FieldName = _propertyInfo.Name;
|
this.FieldName = GetFieldExpression.ReturnType.Name;
|
||||||
this.OnFilter = onFilter;
|
this.OnFilter = onFilter;
|
||||||
this.SelectedValues = filters.Select(x => x.Value.ToString());
|
this.SelectedValues = filters.Select(x => x.Value.ToString());
|
||||||
this.Filters = filters;
|
this.Filters = filters;
|
||||||
@ -34,14 +33,13 @@ namespace AntDesign.TableModels
|
|||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sourceExpression = Expression.Parameter(typeof(TItem));
|
var sourceExpression = GetFieldExpression.Parameters[0];
|
||||||
var propertyExpression = Expression.Property(sourceExpression, _propertyInfo);
|
|
||||||
|
|
||||||
Expression invocationExpression = Expression.Invoke((Expression<Func<bool>>)(() => false));
|
Expression invocationExpression = Expression.Constant(false, typeof(bool));
|
||||||
|
|
||||||
foreach (var filter in Filters)
|
foreach (var filter in Filters)
|
||||||
{
|
{
|
||||||
invocationExpression = Expression.OrElse(invocationExpression, Expression.Invoke(OnFilter, Expression.Constant(filter.Value), propertyExpression));
|
invocationExpression = Expression.OrElse(invocationExpression, Expression.Invoke(OnFilter, Expression.Constant(filter.Value), GetFieldExpression.Body));
|
||||||
}
|
}
|
||||||
|
|
||||||
var lambda = Expression.Lambda<Func<TItem, bool>>(invocationExpression, sourceExpression);
|
var lambda = Expression.Lambda<Func<TItem, bool>>(invocationExpression, sourceExpression);
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using AntDesign.Internal;
|
||||||
|
|
||||||
namespace AntDesign.TableModels
|
namespace AntDesign.TableModels
|
||||||
{
|
{
|
||||||
@ -16,16 +18,18 @@ namespace AntDesign.TableModels
|
|||||||
|
|
||||||
SortDirection ITableSortModel.SortDirection => _sortDirection;
|
SortDirection ITableSortModel.SortDirection => _sortDirection;
|
||||||
|
|
||||||
private readonly PropertyInfo _propertyInfo;
|
|
||||||
private readonly Func<TField, TField, int> _comparer;
|
private readonly Func<TField, TField, int> _comparer;
|
||||||
|
|
||||||
private SortDirection _sortDirection;
|
private SortDirection _sortDirection;
|
||||||
|
|
||||||
public SortModel(PropertyInfo propertyInfo, int priority, SortDirection defaultSortOrder, Func<TField, TField, int> comparer)
|
private LambdaExpression _getFieldExpression;
|
||||||
|
|
||||||
|
public SortModel(LambdaExpression getFieldExpression, int priority, SortDirection defaultSortOrder, Func<TField, TField, int> comparer)
|
||||||
{
|
{
|
||||||
this.Priority = priority;
|
this.Priority = priority;
|
||||||
this.FieldName = propertyInfo?.Name;
|
this._getFieldExpression = getFieldExpression;
|
||||||
this._propertyInfo = propertyInfo;
|
var member = ColumnExpressionHelper.GetReturnMemberInfo(_getFieldExpression);
|
||||||
|
this.FieldName = member.GetCustomAttribute<DisplayAttribute>(true)?.Name ?? member.Name;
|
||||||
this._comparer = comparer;
|
this._comparer = comparer;
|
||||||
this._sortDirection = defaultSortOrder ?? SortDirection.None;
|
this._sortDirection = defaultSortOrder ?? SortDirection.None;
|
||||||
}
|
}
|
||||||
@ -42,11 +46,7 @@ namespace AntDesign.TableModels
|
|||||||
return source as IOrderedQueryable<TItem>;
|
return source as IOrderedQueryable<TItem>;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sourceExpression = Expression.Parameter(typeof(TItem));
|
var lambda = (Expression<Func<TItem, TField>>)_getFieldExpression;
|
||||||
|
|
||||||
var propertyExpression = Expression.Property(sourceExpression, _propertyInfo);
|
|
||||||
|
|
||||||
var lambda = Expression.Lambda<Func<TItem, TField>>(propertyExpression, sourceExpression);
|
|
||||||
|
|
||||||
if (_sortDirection == SortDirection.Ascending)
|
if (_sortDirection == SortDirection.Ascending)
|
||||||
{
|
{
|
||||||
|
@ -87,8 +87,6 @@
|
|||||||
|
|
||||||
public async Task OnChange(QueryModel<WeatherForecast> queryModel)
|
public async Task OnChange(QueryModel<WeatherForecast> queryModel)
|
||||||
{
|
{
|
||||||
forecasts = await GetForecastAsync(queryModel.PageIndex, queryModel.PageSize);
|
|
||||||
_total = 50;
|
|
||||||
Console.WriteLine(JsonSerializer.Serialize(queryModel));
|
Console.WriteLine(JsonSerializer.Serialize(queryModel));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
<Table @ref=" table" TItem="TestData" DataSource="@testData">
|
@using AntDesign.TableModels
|
||||||
|
|
||||||
|
<Table TItem="TestData" DataSource="@testData">
|
||||||
<Column @bind-Field="@context.Id" Sortable/>
|
<Column @bind-Field="@context.Id" Sortable/>
|
||||||
<Column Title="DayOfWeek" @bind-Field="@context.DayOfWeek" Sortable/>
|
<Column Title="DayOfWeek" @bind-Field="@context.DayOfWeek" Sortable/>
|
||||||
<Column Title="DayOfWeek DataIndex" TData="int" DataIndex="DayOfWeek" Sortable SorterCompare="@((v1, v2) => v1 - v2)"/>
|
<Column Title="DayOfWeek DataIndex" TData="int" DataIndex="DayOfWeek" Sortable SorterCompare="@((v1, v2) => v1 - v2)" Filters="DayOfWeekFilter" OnFilter="(a, b) => a == b"/>
|
||||||
<Column Title="N1.N12.N2A DataIndex" TData="string" DataIndex=@("N1.N12[\"test\"].N2A") Sortable SorterCompare="@((v1, v2) => string.CompareOrdinal(v1, v2))"/>
|
<Column Title="N1.N12.N2A DataIndex" TData="string" DataIndex=@("N1.N12[\"test\"].N2A") Sortable/>
|
||||||
<Column Title="N1.N1A DataIndex Nullable" TData="int?" DataIndex="N1.N1A" Sortable SorterCompare="CompareNullableInt"/>
|
<Column Title="N1.N1A DataIndex Nullable" TData="int?" DataIndex="N1.N1A" Sortable SorterCompare="CompareNullableInt"/>
|
||||||
<Column Title="Time" TData="DateTime?" DataIndex=@(@"N1.N12[""test""].Time") Format="yyyy-MM-dd hh:mm:ss" Sortable SorterCompare="_dateTimeCompare"></Column>
|
<Column Title="Time" TData="DateTime?" DataIndex=@(@"N1.N12[""test""].Time") Format="yyyy-MM-dd hh:mm:ss" Sortable SorterCompare="_dateTimeCompare"></Column>
|
||||||
</Table>
|
</Table>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
|
||||||
ITable table;
|
|
||||||
|
|
||||||
TestData[] testData;
|
TestData[] testData;
|
||||||
|
|
||||||
public class TestData
|
public class TestData
|
||||||
@ -40,6 +40,17 @@
|
|||||||
public DateTime? Time { get; set; }
|
public DateTime? Time { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TableFilter<int>[] DayOfWeekFilter =
|
||||||
|
{
|
||||||
|
new() {Text = "Monday", Value = 1},
|
||||||
|
new() {Text = "Tuesday", Value = 2},
|
||||||
|
new() {Text = "Wednesdays", Value = 3},
|
||||||
|
new() {Text = "Thursday", Value = 4},
|
||||||
|
new() {Text = "Friday", Value = 5},
|
||||||
|
new() {Text = "Saturday", Value = 6},
|
||||||
|
new() {Text = "Sunday", Value = 7},
|
||||||
|
};
|
||||||
|
|
||||||
public string[] DayName = {"None", "Monday", "Tuesday", "Wednesdays", "Thursday", "Friday", "Saturday", "Sunday"};
|
public string[] DayName = {"None", "Monday", "Tuesday", "Wednesdays", "Thursday", "Friday", "Saturday", "Sunday"};
|
||||||
|
|
||||||
Func<DateTime?, DateTime?, int> _dateTimeCompare = (t1, t2) =>
|
Func<DateTime?, DateTime?, int> _dateTimeCompare = (t1, t2) =>
|
||||||
@ -63,7 +74,7 @@
|
|||||||
|
|
||||||
public TestData[] GetForecastAsync()
|
public TestData[] GetForecastAsync()
|
||||||
{
|
{
|
||||||
var rng = new Random();
|
var rng = new Random(42);
|
||||||
var startDate = new DateTime(DateTime.Today.Year - 5, 1, 1);
|
var startDate = new DateTime(DateTime.Today.Year - 5, 1, 1);
|
||||||
var range = (DateTime.Today - startDate).TotalSeconds;
|
var range = (DateTime.Today - startDate).TotalSeconds;
|
||||||
return Enumerable.Range(0, 5).Select(index =>
|
return Enumerable.Range(0, 5).Select(index =>
|
||||||
|
Loading…
Reference in New Issue
Block a user