using System; using System.Collections.Generic; using System.Linq; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq.Expressions; using System.Reflection; using AntDesign.Internal; using AntDesign.TableModels; using Microsoft.AspNetCore.Components; using System.Text.Json; using AntDesign.Core.Helpers; namespace AntDesign { public partial class Column : ColumnBase, IFieldColumn { [CascadingParameter(Name = "AntDesign.Column.Blocked")] public bool Blocked { get; set; } [CascadingParameter(Name = "ItemType")] public Type ItemType { get; set; } [Parameter] public EventCallback FieldChanged { get; set; } [Parameter] public Expression> FieldExpression { get; set; } [Parameter] public TData Field { get { return GetValue != null ? GetValue(RowData) : _field; } set { if (GetValue == null) { _field = value; } } } private TData _field; public override string Title { get => base.Title ?? DisplayName ?? FieldName; set => base.Title = value; } [Parameter] public string DataIndex { get; set; } [Parameter] public string Format { get; set; } [Parameter] public bool Sortable { get; set; } [Parameter] public Func SorterCompare { get; set; } [Parameter] public int SorterMultiple { get; set; } [Parameter] public bool ShowSorterTooltip { get; set; } = true; [Parameter] public SortDirection[] SortDirections { get; set; } [Parameter] public SortDirection DefaultSortOrder { get; set; } [Parameter] public Func> OnCell { get; set; } [Parameter] public Func> OnHeaderCell { get; set; } private bool _filterable; private bool _hasFilterableAttribute; [Parameter] public bool Filterable { get => _filterable; set { _filterable = value; _hasFilterableAttribute = true; } } private IEnumerable _filters; private bool _hasFiltersAttribute; [Parameter] public IEnumerable> Filters { get => _filters as IEnumerable>; set { _filters = value; _hasFiltersAttribute = true; } } [Parameter] public bool FilterMultiple { get; set; } = true; /// /// Function that determines if the row is displayed when filtered /// /// Parameter 1: The value of the filter item /// /// /// Parameter 2: The value of the column /// /// [Parameter] public Expression> OnFilter { get; set; } [Parameter] public virtual RenderFragment> CellRender { get; set; } private TableFilterType _columnFilterType; private Type _columnDataType; public string DisplayName { get; private set; } public string FieldName { get; private set; } public ITableSortModel SortModel { get; private set; } public ITableFilterModel FilterModel { get; private set; } private SortDirection _sortDirection; protected Func GetValue { get; set; } protected LambdaExpression GetFieldExpression { get; set; } void IFieldColumn.ClearSorter() { SetSorter(SortDirection.None); if (FieldExpression == null) { StateHasChanged(); } } private static readonly EventCallbackFactory _callbackFactory = new(); private bool _filterOpened; private bool _hasFilterSelected; private string[] _selectedFilterValues; protected override void OnInitialized() { base.OnInitialized(); Sortable = Sortable || SorterMultiple != default || SorterCompare != default || DefaultSortOrder != default || SortDirections?.Any() == true; if (IsHeader) { if (FieldExpression != null) { if (FieldExpression.Body is not MemberExpression memberExp) { throw new ArgumentException("'Field' parameter must be child member"); } var paramExp = Expression.Parameter(ItemType); var bodyExp = Expression.MakeMemberAccess(paramExp, memberExp.Member); GetFieldExpression = Expression.Lambda(bodyExp, paramExp); } else if (DataIndex != null) { (_, GetFieldExpression) = ColumnDataIndexHelper.GetDataIndexConfig(this); } if (GetFieldExpression != null) { var member = ColumnExpressionHelper.GetReturnMemberInfo(GetFieldExpression); DisplayName = member?.GetCustomAttribute(true)?.DisplayName ?? member?.GetCustomAttribute(true)?.GetName() ?? member?.Name; FieldName = DataIndex ?? member?.Name; } if (Sortable && GetFieldExpression != null) { SortModel = new SortModel(this, GetFieldExpression, FieldName, SorterMultiple, DefaultSortOrder, SorterCompare); } } else if (IsBody) { SortModel = Context.HeaderColumns[ColIndex] is IFieldColumn fieldColumn ? fieldColumn.SortModel : null; if (DataIndex != null) { (GetValue, _) = ColumnDataIndexHelper.GetDataIndexConfig(this); } } SortDirections ??= Table.SortDirections; Sortable = Sortable || SortModel != null; _sortDirection = SortModel?.SortDirection ?? DefaultSortOrder ?? SortDirection.None; if (IsHeader) { if (_hasFiltersAttribute) { if (!_hasFilterableAttribute) Filterable = true; _columnFilterType = TableFilterType.List; } else if (_hasFilterableAttribute) { _columnDataType = THelper.GetUnderlyingType(); if (_columnDataType == typeof(bool)) { _columnFilterType = TableFilterType.List; _filters = new List(); var trueFilterOption = GetNewFilter(); trueFilterOption.Text = Table.Locale.FilterOptions.True; trueFilterOption.Value = true; ((List)_filters).Add(trueFilterOption); var falseFilterOption = GetNewFilter(); falseFilterOption.Text = Table.Locale.FilterOptions.False; falseFilterOption.Value = false; ((List)_filters).Add(falseFilterOption); } else if (_columnDataType.IsEnum && _columnDataType.GetCustomAttribute() == null) { _columnFilterType = TableFilterType.List; _filters = new List(); foreach (var enumValue in Enum.GetValues(_columnDataType)) { var enumName = Enum.GetName(_columnDataType, enumValue); var filterOption = GetNewFilter(); // use DisplayAttribute only, DisplayNameAttribute is not valid for enum values filterOption.Text = _columnDataType.GetMember(enumName)[0].GetCustomAttribute()?.Name ?? enumName; filterOption.Value = enumValue; ((List)_filters).Add(filterOption); } } else { _columnFilterType = TableFilterType.FieldType; InitFilters(); } if (_columnFilterType == TableFilterType.List && THelper.IsTypeNullable()) { var nullFilterOption = GetNewFilter(); nullFilterOption.Text = Table.Locale.FilterOptions.IsNull; nullFilterOption.Value = null; ((List)_filters).Add(nullFilterOption); } } Context.HeaderColumnInitialed(this); } ClassMapper .If("ant-table-column-has-sorters", () => Sortable) .If($"ant-table-column-sort", () => Sortable && SortModel != null && SortModel.SortDirection.IsIn(SortDirection.Ascending, SortDirection.Descending)); } protected override void OnParametersSet() { base.OnParametersSet(); if (IsHeader) { FilterModel = _filterable && _filters?.Any(x => x.Selected) == true ? new FilterModel(this, GetFieldExpression, FieldName, OnFilter, _filters.Where(x => x.Selected).ToList(), _columnFilterType) : null; } } protected override bool ShouldRender() { if (Blocked) return false; return true; } private string NumberFormatter(object value) { if (value == null) return null; return Convert.ToDouble(value).ToString(Format); } private void HandleSort() { if (Sortable) { SetSorter(NextSortDirection()); Table.ColumnSorterChange(this); } } private string SorterTooltip { get { var next = NextSortDirection(); return next?.Value switch { 0 => Table.Locale.CancelSort, 1 => Table.Locale.TriggerAsc, 2 => Table.Locale.TriggerDesc, _ => Table.Locale.CancelSort }; } } private SortDirection NextSortDirection() { if (_sortDirection == SortDirection.None) { return SortDirections[0]; } else { var index = Array.IndexOf(SortDirections, _sortDirection); if (index >= SortDirections.Length - 1) { return SortDirection.None; } return SortDirections[index + 1]; } } private void SetSorter(SortDirection sortDirection) { _sortDirection = sortDirection; SortModel?.SetSortDirection(sortDirection); } private void SetFilterCompareOperator(TableFilter filter, TableFilterCompareOperator compareOperator) { filter.FilterCompareOperator = compareOperator; } private void SetFilterCondition(TableFilter filter, TableFilterCondition filterCondition) { filter.FilterCondition = filterCondition; } private void SetFilterValue(TableFilter filter, object value) { filter.Value = value; } private void FilterSelected(TableFilter filter) { if (_columnFilterType == TableFilterType.FieldType) return; if (!FilterMultiple) { _filters.ForEach(x => x.Selected = false); filter.Selected = true; } else { filter.Selected = !filter.Selected; } _selectedFilterValues = _filters.Where(x => x.Selected).Select(x => x.Value?.ToString()).ToArray(); StateHasChanged(); } private void FilterConfirm(bool isReset = false) { _filterOpened = false; if (!isReset && _columnFilterType == TableFilterType.FieldType) { _filters?.ForEach(f => { f.Selected = f.Value != null || f.FilterCompareOperator == TableFilterCompareOperator.IsNotNull || f.FilterCompareOperator == TableFilterCompareOperator.IsNull; }); } _hasFilterSelected = _filters?.Any(x => x.Selected) == true; FilterModel = _hasFilterSelected ? new FilterModel(this, GetFieldExpression, FieldName, OnFilter, _filters.Where(x => x.Selected).ToList(), _columnFilterType) : null; Table?.ReloadAndInvokeChange(); } private void ResetFilters() { if (_columnFilterType == TableFilterType.List) { _filters.ForEach(x => x.Selected = false); } else { InitFilters(); } FilterConfirm(true); } private void AddFilter() { ((List)_filters).Add(GetNewFilter()); } private void RemoveFilter(TableFilter filter) { ((List)_filters).Remove(filter); } private TableFilter GetNewFilter() { if (_columnFilterType == TableFilterType.FieldType) { return new TableFilter() { FilterCondition = TableFilterCondition.And, FilterCompareOperator = _columnDataType == typeof(string) ? TableFilterCompareOperator.Contains : TableFilterCompareOperator.Equals }; } else { return new TableFilter() { FilterCondition = TableFilterCondition.Or, FilterCompareOperator = TableFilterCompareOperator.Equals }; } } private void InitFilters() { _filters = new List() { GetNewFilter() }; } void IFieldColumn.ClearFilters() => ResetFilters(); void IFieldColumn.SetFilterModel(ITableFilterModel filterModel) { foreach (var filter in filterModel.Filters) { if (filter.Value is JsonElement jsonElement) { filter.Value = JsonElementHelper.GetValue(jsonElement); } } if (_columnFilterType == TableFilterType.List) { foreach (var filter in filterModel.Filters.Where(filter => filterModel.Filters.Any(x => x.Value == filter.Value))) { filter.Selected = true; } } else { _filters = filterModel.Filters; } FilterModel = new FilterModel(this, GetFieldExpression, FieldName, OnFilter, _filters.Where(x => x.Selected).ToList(), _columnFilterType); _hasFilterSelected = true; } void IFieldColumn.SetSortModel(ITableSortModel sortModel) { SortModel = new SortModel(this, GetFieldExpression, FieldName, SorterMultiple, SortDirection.Parse(sortModel.Sort), SorterCompare); this.SetSorter(SortDirection.Parse(sortModel.Sort)); } } }