Binding Columns to a Dictionary

4 posts, 0 answers
  1. Michael
    Michael avatar
    3 posts
    Member since:
    Jan 2011

    Posted 04 Mar 2015 Link to this post

    I want to do the same thing as described in http://www.telerik.com/forums/binding-to-a-dictionary, except I am using the DataGrid from UI for Windows Universal instead of UI for Silverlight.

    I created a DictionaryConverter that derives from IValueConverter just as the solution in the post I linked above describes. However, when I get to build/bind the columns, I run into issues.

    In the Silverlight version, the solution included an approach like:

    private void BuildColumns(Layer layer)
    {
      for (int i = 0; i < layer.Data[0].Attributes.Count; i++)
      {
        string key = layer.Data[0].Attributes.Keys.ElementAt(i);
        GridViewDataColumn dataColumn = new GridViewDataColumn();
        dataColumn.HeaderText = key;
        dataColumn.DataMemberBinding = PrepareDataMemberBinding(key);
        this.testGridView.Columns.Add(dataColumn);
      }
    }
      
    private System.Windows.Data.Binding PrepareDataMemberBinding(string key)
    {
      Binding binding = new Binding();
      binding.Path = new PropertyPath("Attributes");
      binding.Converter = new DictionaryConverter(key);
      
      return binding;
    }
     
    public class Layer
    {
      public List<LayerData> Data { get; set; }
    }
     
    public class LayerData
    {
      public Dictionary<string, object> Attributes { get; set; }
    }

    However, in the Windows Universal version, I do not have a GridViewDataColumn class available. Instead, I am trying to use a DataGridTextColumn. The problem is that DataGridTextColumn does not support a DataMemberBinding property which the solution above depends on. The only way I can see of telling DataGridTextColumn which property to bind to in my row object is by assigning the PropertyName attribute. This won't work because I don't have named properties on my row objects - I'm binding to keys in a Dictionary. Is there any way to achieve this?









  2. Michael
    Michael avatar
    3 posts
    Member since:
    Jan 2011

    Posted 04 Mar 2015 Link to this post

    I was able to find an alternative approach that addresses this issue. I defined a custom class that derives from DataGridTextColumn, and then I wrote an override of the GetValueForInstance() method that does a lookup into my Dictionary.
  3. Tsvyatko
    Admin
    Tsvyatko avatar
    833 posts

    Posted 06 Mar 2015 Link to this post

    Hi Michael,

    Indeed, using GetValueForInstance gives you good extension point for displaying custom data from your object.

    Keep in mind that this method does not controls the operations for sorting and grouping. If you like to support them you could take advantage of delegate descriptors - http://docs.telerik.com/windows-universal/controls/raddatagrid/sorting/datagrid-delegatesortdescriptor You can set them to the corresponding columns as well as to the grid itself.

    Regards,
    Tsvyatko
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  4. Michael
    Michael avatar
    3 posts
    Member since:
    Jan 2011

    Posted 06 Mar 2015 in reply to Tsvyatko Link to this post

    Yep, I also added an override for CreateSortDescriptor() and an implementation of IKeyLookup to support custom sorting. I don't require grouping yet, so I haven't added support for that at this point. I'm posting the code I used in case anyone is interested.

    public class PlaylistDataGridTextColumn : DataGridTextColumn
    {
        public override object GetValueForInstance(object instance)
        {
            var cutupPlay = instance as CutupPlay;
     
            if (cutupPlay == null)
            {
                return base.GetValueForInstance(instance);
            }
                 
            var header = Header.ToString();
            string metadataValue;
     
            cutupPlay.Metadata.TryGetValue(header, out metadataValue);
            return metadataValue;
        }
     
        protected override SortDescriptorBase CreateSortDescriptor()
        {
            var baseDescriptor = base.CreateSortDescriptor();
            var keyLookup = new CutupPlayMetadataKeyLookup(Header.ToString());
     
            var delegateSortDescriptor = new DelegateSortDescriptor
            {
                KeyLookup = keyLookup,
                SortOrder = baseDescriptor.SortOrder
            };
     
            return delegateSortDescriptor;
        }
    }
     
    public class CutupPlayMetadataKeyLookup : IKeyLookup
    {
        private readonly string _metadataKey;
     
        public CutupPlayMetadataKeyLookup(string metadataKey)
        {
            _metadataKey = metadataKey;
        }
     
        public object GetKey(object instance)
        {
            var cutupPlay = (CutupPlay)instance;
            string keyValue;
     
            cutupPlay.Metadata.TryGetValue(_metadataKey, out keyValue);
     
            if (string.IsNullOrWhiteSpace(keyValue) == false)
            {
                double numericalValue;
                if (double.TryParse(keyValue, out numericalValue))
                {
                    return numericalValue;
                }
            }
     
            return keyValue;
        }
    }
Back to Top