Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sorting in data grid respecting the culture specific sorting rules. #154

Closed
OndrejUzovic opened this issue Jun 23, 2021 · 3 comments
Closed

Comments

@OndrejUzovic
Copy link
Contributor

Currently when data grid sorts text columns containing a string with diacritics, it displays it in incorrect order because it does not respect the culture specific sorting rules.

The solution for this problem could be to provide a 'Parameter' property Comparer (of type System.Collections.IComparer) into the data grid.
If the property is set then the comparer would be used in RadzenGrid.View as the second parameter when OrderBy(..) is called.

[Parameter]
public IComparer Comparer { get; set; }

public override IQueryable<TItem> View
    {
        get
        {
            var view = base.View.Where<TItem>(columns);

            if (!string.IsNullOrEmpty(orderBy))
            {
                if (typeof(TItem) == typeof(object))
                {
                    var firstItem = view.FirstOrDefault();
                    if (firstItem != null)
                    {
                       // comparer added
                        view = view.Cast(firstItem.GetType()).AsQueryable().OrderBy(orderBy, Comparer).Cast<TItem>();
                    }
                }
                else
                {
                    // comparer added
                    view = view.OrderBy(orderBy,, Comparer);
                }
            }

            return view;
        }
    }

Would you please consider this feature?

@enchev
Copy link
Collaborator

enchev commented Jun 25, 2021

Hey @OndrejUzovic ,

Maybe it will be better if we pass the current application culture instead exposing a property:
image

Not sure however how this will affect database sorting - should remain the same (performed by the database).

@OndrejUzovic
Copy link
Contributor Author

Hi @enchev ,

thanks for your response. The problem with the CurrentCulture is that it would be difficult (maybe impossible) to use in cases if you have multiple users with different cultures (each user wants to see the column ordered according to his culture rules).

However the problem seems a bit more complex that I thought when I wrote my original proposal. The problem is, it is not enough to just expose the property for IComparer because the comparer would just get the whole TItem and would not know which column(s) shall be compared. The implementation of IComparer would have to store the reference to DataGrid and then use Query.OrderBy to resolve that - which seems somehow complex for a general solution.

So finally I came to the idea that maybe better than IComparer will be to expose CultureInfo in DataGrid. The culture specific string comparer would be created internally by DataGrid and used only if string columns shall be sorted.

Here is my final workaround solution which reflex this idea and I am currently using:
(It creates System.StringComparer for sorting string columns.)

public class RadzenGridImprove<TItem> : RadzenGrid<TItem>
    {
        [Parameter]
        public CultureInfo Culture { get; set; }

        public override IQueryable<TItem> View
        {
            get
            {
                IQueryable<TItem> result;

                var comparer = TryCreateComparer(Culture, Query.OrderBy);
                if (comparer != null)
                {
                    result = base.View.OrderBy(Query.OrderBy, comparer);
                }
                else
                {
                    result = base.View;
                }

                return result;
            }
        }

        private IComparer TryCreateComparer(CultureInfo culture, string ordering)
        {
            IComparer result = null;

            if (culture != null && !string.IsNullOrEmpty(ordering))
            {
                var words = ordering.Trim().Split(null);
                if (words.Length > 0)
                {
                    // Get the property name
                    var propertyName = words[0];

                    // If the property is string type then create the culture specific string comparer.
                    var propertyInfo = typeof(TItem).GetProperty(propertyName);
                    if (propertyInfo != null && propertyInfo.PropertyType == typeof(string))
                    {
                        result = StringComparer.Create(culture, CompareOptions.StringSort);
                    }
                }
            }

            return result;
        }
    }

@javiercampos
Copy link
Contributor

javiercampos commented Sep 8, 2021

Hey @OndrejUzovic ,

Maybe it will be better if we pass the current application culture instead exposing a property:
image

Note that using CurrentCulture (which should be CurrentUICulture actually) might not be reliable enough because it's a thread local value and when changing it (using InvokeAsync or at events), the Blazor synchronization context doesn't pass it around (and it doesn't stick to a thread), so in dynamic culture scenarios that wouldn't be really reliable.

I've made a feature request here to actually have a Culture parameter on Radzen components directly (I was thinking on the templates, but could be used for this aswell), which should fallback to CurrentUICulture if not specified: this would work for the majority of cases (where the thread's and renderer culture is set by the ASP.NET localization middleware upon connection and it's not usually dynamically changed).

Not sure however how this will affect database sorting - should remain the same (performed by the database).

I'd leave the database ordering as is (performed by the database, or whatever provider you use), you typically use the database collation for those effects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants