2
\$\begingroup\$

Scenario

A portable controls/widgets library for Xamarin.Forms (PCL Profile 111) contains a combobox/dropdown/picker control where the ItemsSource property is an IEnumerable.

  • The ItemsSource can be populated with any IEnumerable of objects.
  • The combobox displays value by
    • DisplayMemberPath: string
  • The combobox syncs selection:
    • SelectedItem : object
    • SelectedIndex: int

To do all this the IEnumerable must be parsed so we can

  • Select index
  • Select item from source collection

The tricky part

Parse IEnumerable to Dictionary<object, object> in a Portable Class Library. The sourceDictionary field is used to sync the "selected" properties as described above.

    private Dictionary<object, object> sourceDictionary;

    /// <summary>
    ///     Parse type of ItemsSource as Dictionary and populate <see cref="Picker.Items" /> and
    ///     <see cref="sourceDictionary" />.
    /// </summary>
    private void PopulateItemsAndSelectionValuesFromDictionary()
    {
        // TODO: Better way to get Dictionary from IEnumerable
        if (this.ItemsSource is Dictionary<object, object>)
        {
            foreach (var newItem in (Dictionary<object, object>)this.ItemsSource)
            {
                this.AddToItemsAndSelectionValues(newItem.Key, newItem.Value);
            }
        }
        else if (this.ItemsSource is Dictionary<object, string>)
        {
            foreach (var newItem in (Dictionary<object, string>)this.ItemsSource)
            {
                this.AddToItemsAndSelectionValues(newItem.Key, newItem.Value);
            }
        }
        else if (this.ItemsSource is Dictionary<object, int>)
        {
            foreach (var newItem in (Dictionary<object, int>)this.ItemsSource)
            {
                this.AddToItemsAndSelectionValues(newItem.Key, newItem.Value);
            }
        }
        else if (this.ItemsSource is Dictionary<int, object>)
        {
            foreach (var newItem in (Dictionary<int, object>)this.ItemsSource)
            {
                this.AddToItemsAndSelectionValues(newItem.Key, newItem.Value);
            }
        }
        else if (this.ItemsSource is Dictionary<string, object>)
        {
            foreach (var newItem in (Dictionary<string, object>)this.ItemsSource)
            {
                this.AddToItemsAndSelectionValues(newItem.Key, newItem.Value);
            }
        }
        else if (this.ItemsSource is Dictionary<int, int>)
        {
            foreach (var newItem in (Dictionary<int, int>)this.ItemsSource)
            {
                this.AddToItemsAndSelectionValues(newItem.Key, newItem.Value);
            }
        }
        else if (this.ItemsSource is Dictionary<string, string>)
        {
            foreach (var newItem in (Dictionary<string, string>)this.ItemsSource)
            {
                this.AddToItemsAndSelectionValues(newItem.Key, newItem.Value);
            }
        }
    }

    /// <summary>
    ///     Add the provided KeyValuePair to <see cref="Picker.Items" /> and <see cref="sourceDictionary" />
    /// </summary>
    private void AddToItemsAndSelectionValues(object key, object value)
    {
        this.Items.Add(this.ValueIsDisplayMember() ? value.ToString() : key.ToString());
        this.sourceDictionary.Add(this.ValueIsDisplayMember() ? key : value, new KeyValuePair<object, object>(key, value));
    }
\$\endgroup\$
3
\$\begingroup\$

If you know that ItemsSource is a dictionary then you can simply cast it into IDictionary and iterate it because you just need objects and it gives you exacly that:

var items = (IDictionary)ItemsSource;
foreach (var key in items.Keys)
{
    AddToItemsAndSelectionValues(key, items[key]);
}

You cast it into a concrete dictionary but you never use the types anyway so go directly with objects instead.

That's all. You don't need any of those ifs.

\$\endgroup\$
  • \$\begingroup\$ That worked quite excellent. Very elegant \$\endgroup\$ – Thomas Hagström Sep 5 '16 at 7:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.