Skip to content

Support more fields in GridView SortExpression #1730

@holajan

Description

@holajan

Change GridViewDataSet ApplySortingToQueryable method to support more fields in SortExpression separated by a comma.

Used for example like this:

<dot:GridViewTextColumn ValueBinding="{value: CeleJmeno}" AllowSorting="true" SortExpression="Prijmeni,Jmeno" HeaderText="Jméno zaměstnance" />

GridViewDataSet ApplySortingToQueryable method will be:

public virtual IQueryable<T> ApplySortingToQueryable(IQueryable<T> queryable)
{
    if (this.SortingOptions?.SortExpression == null)
    {
        return queryable;
    }

    var parameterExpression = Expression.Parameter(typeof(T), "p");
    Expression? sortExpression = null;

    foreach (string propertySortExpression in (this.SortingOptions.SortExpression ?? "").Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
    {
        Expression sortByExpression = parameterExpression;

        foreach (string prop in propertySortExpression.Trim().Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries))
        {
            var property = sortByExpression.Type.GetTypeInfo().GetProperty(prop);
            if (property == null)
            {
                throw new Exception($"Could not sort by property '{prop}', since it does not exists.");
            }
            if (property.GetCustomAttribute<BindAttribute>() is BindAttribute bind && bind.Direction == Direction.None)
            {
                throw new Exception($"Cannot sort by an property '{prop}' that has [Bind(Direction.None)].");
            }
            if (property.GetCustomAttribute<ProtectAttribute>() is ProtectAttribute protect && protect.Settings == ProtectMode.EncryptData)
            {
                throw new Exception($"Cannot sort by an property '{prop}' that is encrypted.");
            }

            sortByExpression = Expression.Property(sortByExpression, property);
        }

        if (sortByExpression == parameterExpression)
        {
            continue;
        }

        var lambdaExpression = Expression.Lambda(sortByExpression, parameterExpression);
        var methodCallExpression = Expression.Call(typeof(Queryable), GetSortingMethodName(sortExpression == null),
            new[] { parameterExpression.Type, sortByExpression.Type },
            sortExpression ?? queryable.Expression,
            Expression.Quote(lambdaExpression));

        sortExpression = methodCallExpression;
    }

    if (sortExpression == null) //No sorting
    {
        return queryable;
    }

    return queryable.Provider.CreateQuery<T>(sortExpression);
}

private string GetSortingMethodName(bool isFirst)
{
    return isFirst ?
        this.SortingOptions.SortDescending ? "OrderByDescending" : "OrderBy" :
        this.SortingOptions.SortDescending ? "ThenByDescending" : "ThenBy";
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions