/* BeejBløg */

Jun 23, 2017 - 2 minute read - Comments -

Syncfusion Xamarin.Forms SfDataGrid – Binding to List<Dictionary<,>>

corresponding syncfusion forums post

Binding to Collection> can be accomplished but doesn’t appear to be well documented… this WPF SfDataGrid doc gave the clue.

The basic trick is to set the SfDataGrid’s column.MappingName = “Fields[FieldName]“;

where Fields is a Dictionary property on your DictionaryWrapper class.

I couldn’t get List> working directly without the wrapper class “hiding” the dictionary from what I think is an SfDataGrid bug. The app crash exception call stack ultimately winds up on an invalid Linq related get_Item() call.

Below is sample working code including “SimpleTable” wrapper for List and Newtonsoft type converter for deserializing Json “table” directly into this datastructure… this facilitates delivery of tabular resultsets from web api’s… see my SqlClientHelpers.ToJson method as one implementation that works succinctly within Azure Functions for example.

FYI, I believe there is also a bug with SfDataGrid column sorting logic when bound to this kind of Dictionary, a non-fatal exception fires. I worked around by implementing grid.SortColumnsChanging.

Sample Deserialize call:

12
  var data = "[{\"Source\":\"Web\",\"Batch Id\":1}, {\"Source\":\"Manual\",\"Batch Id\":2}]";
  var table = JsonConvert.DeserializeObject<SimpleTable>(data);

Binding sample with crucial MappingName syntax:

123456
  grid.ItemsSource = table;
  grid.Columns.Add(new GridTextColumn()
  {
    HeaderText = "Source",
    MappingName = "Vals[Source]" // **** HERE'S THE KICKER ****
  });

SimpleTable.cs

 1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132333435363738
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  using Newtonsoft.Json;
    
  namespace DataHelpers
  {
    [JsonConverter(typeof(DictRow_DictDeserializer))]
    public class DictRow
    {
      public Dictionary<string, object> Vals { get; set; }
      public DictRow(Dictionary<string, object> dict) { Vals = dict; }
    }
    
    public class SimpleTable : List<DictRow>
    {
      public SimpleTable(IEnumerable<DictRow> list) : base(list) { }
    }
    
    public class DictRow_DictDeserializer : JsonConverter
    {
      public override bool CanRead => true;
      public override bool CanWrite => false;
      public override bool CanConvert(Type objectType) => objectType == typeof(Dictionary<string, object>);
    
      public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
      {
        return new DictRow(serializer.Deserialize<Dictionary<string, object>>(reader));
      }
    
      public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
      {
        throw new NotSupportedException();
      }
    }
  }