GridQueryableCollectionViewWrapper converting my Dictionary<string,object> to Dictionary<string,string>

Hi there,

I'm implementing the suggestion below to bind a Dictionary to my SfDataGrid (v 19.1451.0.54) in Xamarin Forms.

I'm setting my grid ItemsSource like this:

grid.ItemsSource = new QueryableViewExt(rows, grid);

Where rows is an ObservableCollection of DynamicModel type based on this example: https://www.syncfusion.com/kb/7829/how-to-load-sfdatagrid-dynamically-with-json-data-without-poco-classes

The problem is in QueryableViewExt class. When this class gets initialized (constructor call) I see the source dictionary coming in as Dictionary(string,object) as expected but when I tap on my grid column to sort, when it gets to GetExpressionFunc method, I can see while debugging that source changes to Dictionary(string,string) for some reason and it's not sorting my integers properly.

Any ideas why the dictionary types are changing?

Class definition:
    public class QueryableViewExt : GridQueryableCollectionViewWrapper
    {
        public QueryableViewExt(IEnumerable source, SfDataGrid grid) : base(source, grid)
        {

        }

        public override Expression> GetExpressionFunc(string propertyName, DataOperation operation = DataOperation.Default, DataReflectionMode reflectionMode = DataReflectionMode.Default)
        {
            Expression> exp = base.GetExpressionFunc(propertyName, operation, reflectionMode);
            if (exp == null)
            {
                Func func;
                func = (propertyname, record) =>
                {
                    var provider = this.GetPropertyAccessProvider();
                    return provider.GetValue(record, propertyName);
                };
                exp = (propertyname, record) => func(propertyName, record);
            }
            return exp;
        }
    }

Thanks,
Adolfo

7 Replies 1 reply marked as answer

KK Karthikraja Kalaimani Syncfusion Team April 14, 2021 10:29 AM UTC

Hi Adolfo,

Based on the provided details, we have checked the reported issue “Sorting not working when bound dictionary as ItemSource to SfDataGrid”. Unfortunately, the reported issue is not reproducing in our side and the sorting as expected. We have attached the tested sample for your reference.

Sample link : https://www.syncfusion.com/downloads/support/directtrac/general/ze/DataGridDemo2111275296.zip 


 
Please check the sample and if you still face the same issue, please modify the attached sample based on the scenario you used to reproduce the issue. Also let us know the SfDataGrid and Xamarin forms versions. It will be helpful for us to validate the issue and provide you the solution at earlier. 


Regards,
Karthik Raja 



AD Adolfo April 14, 2021 02:59 PM UTC

Thanks Karthik

I was able to reproduce the issue making slight modifications to the project you sent. In MainPage.cs I commented out the Column addition section with logic iterating through the ViewModel Dynamic Collection's first item (because that's all I need to build the dynamic data template).

I need to use data template approach because my columns are variable and I cannot configure them ahead of time. I need to build the grid programmatically. If you do this, you'll notice that sorting of OrderID is alphabetical instead of numeric.

I changed the JsonData in ViewModel.cs to this:

        public const string JsonData = "[{\"OrderID\":13,\"EmployeeID\":100,\"FirstName\":'Gina',\"LastName\":'Gable'}," +
                                     "{\"OrderID\":1,\"EmployeeID\":200,\"FirstName\":'Danielle',\"LastName\":'Rooney'}," +
                                    "{\"OrderID\":7,\"EmployeeID\":201,\"FirstName\":'Danielle',\"LastName\":'Rooney'}," +
                                    "{\"OrderID\":8,\"EmployeeID\":300,\"FirstName\":'Frank',\"LastName\":'Gable'},]";

Here is the modified constructor for MainPage():

        public MainPage()
        {
            InitializeComponent();
            dataGrid.ItemsSource = new QueryableViewExt(viewModel.DynamicCollection, dataGrid);
            dataGrid.AutoGenerateColumns = false;
            //dataGrid.Columns.Add(new GridTextColumn()
            //{
            //    HeaderText = "Order ID",
            //    MappingName = "Values[OrderID]",
            //});

            //dataGrid.Columns.Add(new GridTextColumn()
            //{
            //    HeaderText = "Customer ID",
            //    MappingName = "Values[EmployeeID]",
            //});

            //dataGrid.Columns.Add(new GridTextColumn()
            //{
            //    HeaderText = "First Name",
            //    MappingName = "Values[FirstName]",
            //});

            //dataGrid.Columns.Add(new GridTextColumn()
            //{
            //    HeaderText = "Last Name",
            //    MappingName = "Values[LastName]",
            //});
            var firstObject = viewModel.DynamicCollection.First();
            foreach (KeyValuePair kvp in firstObject.Values.ToArray())
            {
                var templateColumn = new GridTemplateColumn()
                {
                    HeaderText = kvp.Key,
                    MappingName = $"Values[{kvp.Key}]",
                    AllowSorting = true
                };

                var dataTemplate = new DataTemplate(() =>
                {
                    var label = new SfLabel()
                    {
                        VerticalOptions = LayoutOptions.Center,
                        HorizontalOptions = LayoutOptions.Center
                    };
                    label.SetBinding(SfLabel.TextProperty, $"Values[{kvp.Key}]");
                    return label;
                });
                templateColumn.CellTemplate = dataTemplate;
                dataGrid.Columns.Add(templateColumn);
            }
        }

With the above changes, you'll notice that when you sort by OrderId you'll get: 1,13,7,8 in ascending order and 8,7,13,1 in descending order instead of 1,7,8,13 asc and 13,8,7,1 desc

Let me know if you need more details,

Adolfo


AD Adolfo replied to Adolfo April 14, 2021 09:21 PM UTC

Thanks Karthik

I was able to reproduce the issue making slight modifications to the project you sent. In MainPage.cs I commented out the Column addition section with logic iterating through the ViewModel Dynamic Collection's first item (because that's all I need to build the dynamic data template).

I need to use data template approach because my columns are variable and I cannot configure them ahead of time. I need to build the grid programmatically. If you do this, you'll notice that sorting of OrderID is alphabetical instead of numeric.

I changed the JsonData in ViewModel.cs to this:

        public const string JsonData = "[{\"OrderID\":13,\"EmployeeID\":100,\"FirstName\":'Gina',\"LastName\":'Gable'}," +
                                     "{\"OrderID\":1,\"EmployeeID\":200,\"FirstName\":'Danielle',\"LastName\":'Rooney'}," +
                                    "{\"OrderID\":7,\"EmployeeID\":201,\"FirstName\":'Danielle',\"LastName\":'Rooney'}," +
                                    "{\"OrderID\":8,\"EmployeeID\":300,\"FirstName\":'Frank',\"LastName\":'Gable'},]";

Here is the modified constructor for MainPage():

        public MainPage()
        {
            InitializeComponent();
            dataGrid.ItemsSource = new QueryableViewExt(viewModel.DynamicCollection, dataGrid);
            dataGrid.AutoGenerateColumns = false;
            //dataGrid.Columns.Add(new GridTextColumn()
            //{
            //    HeaderText = "Order ID",
            //    MappingName = "Values[OrderID]",
            //});

            //dataGrid.Columns.Add(new GridTextColumn()
            //{
            //    HeaderText = "Customer ID",
            //    MappingName = "Values[EmployeeID]",
            //});

            //dataGrid.Columns.Add(new GridTextColumn()
            //{
            //    HeaderText = "First Name",
            //    MappingName = "Values[FirstName]",
            //});

            //dataGrid.Columns.Add(new GridTextColumn()
            //{
            //    HeaderText = "Last Name",
            //    MappingName = "Values[LastName]",
            //});
            var firstObject = viewModel.DynamicCollection.First();
            foreach (KeyValuePair kvp in firstObject.Values.ToArray())
            {
                var templateColumn = new GridTemplateColumn()
                {
                    HeaderText = kvp.Key,
                    MappingName = $"Values[{kvp.Key}]",
                    AllowSorting = true
                };

                var dataTemplate = new DataTemplate(() =>
                {
                    var label = new SfLabel()
                    {
                        VerticalOptions = LayoutOptions.Center,
                        HorizontalOptions = LayoutOptions.Center
                    };
                    label.SetBinding(SfLabel.TextProperty, $"Values[{kvp.Key}]");
                    return label;
                });
                templateColumn.CellTemplate = dataTemplate;
                dataGrid.Columns.Add(templateColumn);
            }
        }

With the above changes, you'll notice that when you sort by OrderId you'll get: 1,13,7,8 in ascending order and 8,7,13,1 in descending order instead of 1,7,8,13 asc and 13,8,7,1 desc

Let me know if you need more details,

Adolfo

I think I figured it out. I replaced SfLabel with Label in my data template (code b and the sorting came back to normal (numeric vs alphabetical):

                    var label = new SfLabel()
                    {
                        VerticalOptions = LayoutOptions.Center,
                        HorizontalOptions = LayoutOptions.Center
                    };
                    label.SetBinding(SfLabel.TextProperty, $"Values[{kvp.Key}]");
                    return label;

I actually grabbed the code snipped above from this link: https://www.syncfusion.com/kb/7521/how-to-create-gridtemplatecolumn-in-code-behind. Any idea why SfLabel behaves differently from normal Label for grid/dictionary sorting?

Thanks,


KK Karthikraja Kalaimani Syncfusion Team April 15, 2021 02:13 PM UTC

Hi Adolfo,

Thanks for the update.

Currently, we are validating the reported issue. We will validate and update the details on or before 19th April 2021. We appreciate your patience until then.

Regards, 
Karthik Raja 



KK Karthikraja Kalaimani Syncfusion Team April 19, 2021 01:22 PM UTC

Hi Adolfo,

Thanks for your patience.

Actually, we have an TextProperty which is bindable property and its type is string in SfLabel class. So, the sorting are not in numeric order and it is alphabetical order (since the numeric value considered as alphabetical because the TextProperty type is String). So, we suggest to use Xamarin forms Label for your scenario.

Regards,
Karthik Raja
 


Marked as answer

AD Adolfo April 19, 2021 02:02 PM UTC

Thanks Karthik. I'm using a Label and it works fine. We can close the thread.

Thanks for your help.


KK Karthikraja Kalaimani Syncfusion Team April 20, 2021 05:34 AM UTC

Hi Adolfo,

Thanks for the update. Please let us know if you need further assistance from us.

Regards,
Karthik Raja
 


Loader.
Up arrow icon