SortDescriptors.Expression column names not 'escaped' properly

4 posts, 0 answers
  1. Micah
    Micah avatar
    2 posts
    Member since:
    Jun 2012

    Posted 14 Nov 2012 Link to this post

    When I retrieve a SortDescriptors.Expression from my RadGridView the column names are not escaped when they have a space in the name. The FilterDescriptors.Expression does this correctly (IMO) or at least returns what I expect.

    For example, I have a RadGridView bound to a DataTable with the following columns: ID, Unit ID, Name
    I have the grid sorted by the column 'Unit ID' and also filtered to include only records where 'Unit ID'=1 at run-time.
    I then run the following commands:
    string sort = this.myRadGridView.SortDescriptors.Expression;
    Console.WriteLine(sort);
     
    string filter = this.myRadGridView.FilterDescriptors.Expression;
    Console.WriteLine(filter);

    I get the following output:
    Unit ID ASC
    ([Unit ID] = 1)

    With the FilterDescriptors.Expression value I can insert that string directly  back into a SQL query with no issues. With the SortDescriptors.Expression I have to run an addional routine on the result before I can use it in a query.

    I have a workaround I am using right now (simple string replace) but the inconsistant results were something I thought I should bring up here. Maybe the SortDescriptors could be changed to work more like the FilterDescriptors in the future? Anyway, this post is mainly an 'FYI' but if anyone has any comments or tips, they would be appreciated.
  2. Emanuel Varga
    Emanuel Varga avatar
    1336 posts
    Member since:
    May 2010

    Posted 15 Nov 2012 Link to this post

    Hello Micah,

    The difference you are talking about comes from the fact that for filters you have operators and values / custom filtering, and for sorting you do not have these, but you should not be using this if you need to get the fields on which you are sorting / filtering.

    You can get the right fields and other info from the SortDescriptors / FilterDescriptors, by doing the following:
    var sortDescriptors = grid.SortDescriptors;
    foreach (var sortDescriptor in sortDescriptors)
    {
        var propertyName = sortDescriptor.PropertyName;
        var sortDirection = sortDescriptor.Direction;
    }
    var filterDescriptors = grid.FilterDescriptors;
    foreach (var filterDescriptor in filterDescriptors)
    {
        var propertyName = filterDescriptor.PropertyName;
        var filterOperator = filterDescriptor.Operator;
        var expression = filterDescriptor.Expression;
        var filterValue = filterDescriptor.Value;
    }

    Hope this helps, If you have any other questions, please let me know.

    Best Regards,
    Emanuel Varga
    WinForms MVP
  3. UI for WinForms is Visual Studio 2017 Ready
  4. Micah
    Micah avatar
    2 posts
    Member since:
    Jun 2012

    Posted 15 Nov 2012 Link to this post

    I like that method for building a sorting expression; it will probably be faster than my regex replace.  I assume this is how the Expression field is built behind the scenes and was trying to get away without "re-inventing the wheel" so to speak.

    I still wonder about the inconsistancy of the results between the two descriptors. I don't use any custom filtering as you say (or as I understand it.) My grid starts initially with no sorting or filtering of any kind. Simply, To sort I click on the column headers and use the default sorting. For filters I click on the filter icon and click on the items I want.

    grid.EnableCustomFiltering = False;
    grid.EnableCustomSorting = False;
    grid.EnableFiltering = True;
    grid.EnableSorting = True;
    grid.ShowHeaderCellButtons = True;
    grid.ShowFilteringRow = False;

    Additionally, using the filter and sorting mentioned in my first post, both SortDescriptor.PropertyName and FilterDescriptor.PropertyName return the value "Unit ID". Yet, when they are built into an expression, only the filter descriptor adds the brackets around the property name.

    So while I understand it might be more beneficial to build my own sorting and filtering expressions from the descriptors, I then wonder why even have the Expression property on the collections if they are unusable in a practical manner?  I think this may be something that could be looked at in a future version of the library.
  5. Julian Benkov
    Admin
    Julian Benkov avatar
    1135 posts

    Posted 20 Nov 2012 Link to this post

    Hi Micah,

    The FilterDescriptors internally use an expression parser with escape functionality to support special symbols when building and executing filtering operations. The SortDescriptors use only simple method to parse and return expression string. Here is a code snippet used in the Expression property of SortDescriptorCollection:
    public static List<SortDescriptor> ParseSortString(string sortString)
    {
        List<SortDescriptor> list = new List<SortDescriptor>();
        char[] chArray = new char[] { ',' };
        string[] textArray = sortString.Split(chArray);
        for (int i = 0; i < textArray.Length; i++)
        {
            string sortText = textArray[i].Trim();
            int sortLength = sortText.Length;
            bool ascending = true;
     
            if ((sortLength >= 5) && (string.Compare(sortText, sortLength - 4, " ASC", 0, 4, true, System.Globalization.CultureInfo.InvariantCulture) == 0))
            {
                sortText = sortText.Substring(0, sortLength - 4).Trim();
            }
            else if ((sortLength >= 6) && (string.Compare(sortText, sortLength - 5, " DESC", 0, 5, true, System.Globalization.CultureInfo.InvariantCulture) == 0))
            {
                ascending = false;
                sortText = sortText.Substring(0, sortLength - 5).Trim();
            }
     
            if (sortText.StartsWith("["))
            {
                if (!sortText.EndsWith("]"))
                {
                    throw new ArgumentException("Invalid sort expression");
                }
     
                sortText = sortText.Substring(1, sortText.Length - 2);
            }
     
            list.Add(new SortDescriptor(sortText, ascending ? ListSortDirection.Ascending : ListSortDirection.Descending));
        }
     
        return list;
    }
     
    private string GetExpression()
    {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < this.Count; i++)
        {
            string direction = "ASC";
            if (this[i].Direction == ListSortDirection.Descending)
            {
                direction = "DESC";
            }
     
            string delimiter = "";
            if (this.Count > 1 && i < this.Count - 1)
            {
                delimiter = ",";
            }
            stringBuilder.Append(string.Format("{0} {1}{2}", this[i].PropertyName, direction, delimiter));
        }
     
        return stringBuilder.ToString();
    }


    /// <summary>
    /// Gets or sets the expression.
    /// </summary>
    /// <value>The expression.</value>
    public virtual string Expression
    {
        get
        {
            return this.GetExpression();
        }
        set
        {
            if (string.IsNullOrEmpty(value))
            {
                this.Clear();
                return;
            }
     
            this.ParseSortString(value);
            OnPropertyChanged(new PropertyChangedEventArgs("Expression"));
        }
    }
     
    private void ParseSortString(string sortString)
    {
        this.BeginUpdate();
        this.Clear();
     
        this.AddRange(DataStorageHelper.ParseSortString(sortString).ToArray());
     
        this.EndUpdate();
    }

    I hope this helps.

    Kind regards,
    Julian Benkov
    the Telerik team
    Q3’12 of RadControls for WinForms is available for download (see what's new). Get it today.
Back to Top