Dropdown control in Xamarin.Forms – Part Two

banner_dropdown_part2

Introduction

In this article, we will learn how to create Dropdown in Xamarin.Forms (Xamarin.iOS). As we learned in the previous article about by default, Android Platform has dropdown called as “Spinner”, but iOS Platform has no dropdown like Android Spinner and how to achieve the dropdown in Xamarin.Forms for Android Platform using Custom renderer approach. In this article, we are going to create a custom renderer to achieve the dropdown for iOS platform in Xamarin.Forms.

Dropdown in Xamarin.Forms

Please refer the previous article to know, how to achieve the dropdown in Android Platform. I have done changes commonly for Android and iOS in this article.

We will go for custom renderer approach to have a new control to wrap a Platform specific control. I am going to use “FPTInformationSystem Dropdown” and refer the below link to know more details for this control.

Library Link: https://github.com/FPTInformationSystem/Dropdown-Xamarin-iOS

Without much introduction, we will skip into the coding part of this article.

Coding Part

Steps

Here, I will explain the steps to create Dropdown in Xamarin.Forms.

Step 1: Creating new Xamarin.Forms Projects.

Step 2: Creating a Dropdown view in Xamarin.Forms .NetStandard Project

Step 3: Wrapping FPT dropdown for Dropdown control in iOS Project.

Step 4: Implementation of Dropdown & It’s Demo for iOS Platform.

Step 1: Creating new Xamarin.Forms Projects

Create New Project by Selecting New à Project à Select Xamarin Cross Platform App and Click OK.

Note: Xamarin.Forms version should be greater than 4.5.

Then Select Android and iOS Platforms as shown below with Code Sharing Strategy as PCL or .Net Standard and Click OK.

Step 2: Creating a Dropdown view in Xamarin.Forms .NetStandard Project

In this step, we will see how to create a dropdown view with required properties.

  • Create a class named as “Dropdown” and inherit the Dropdown with “Label”. That is Dropdown is child of View.
    public class Dropdown :  Label
    {
      //...
    }
  • Then we will create a required bindable properties. First we will see, what are all the properties & events required for dropdown.
    1. ItemsSource – To assign the list of data to be populated in the dropdown.
    2. SelectedIndex – To identify the index of selected values from the ItemsSource.
    3. ItemSelected – Event for performing action when the item selected in the dropdown.
  • Create a bindable property for the ItemsSource as shown in below.
    public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(
          propertyName: nameof(ItemsSource),
          returnType: typeof(List<string>),
          declaringType: typeof(List<string>),
          defaultValue: null);
    
    public List<string> ItemsSource
    {
          get { return (List<string>)GetValue(ItemsSourceProperty); }
          set { SetValue(ItemsSourceProperty, value); }
    }

Step 3: Wrapping FPT dropdown for Dropdown control in iOS Project.

In this step, we will see “How to wrap the iOS Spinner Control for Dropdown View”.

  • We need to download the DLL of FPT dropdown from the below GitHub link and include as a reference for the iOS project. Library Download Link
  • Create a class file named as “DropdownRenderer” in your iOS client project and add View Renderer as shown in below. I am using Label renderer for displaying the dropdown when the control tapped.
    public class DropdownRenderer :  LabelRenderer
    {
          XFDropdown xfDropdown = null;
          XIDropdown dropDown = null;
          public DropdownRenderer()
          {
    
          }    
          // ...
    }
  • Then Override the methods “OnElementChanged” and “OnElementPropertyChanged”. OnElementChanged method is triggered on element/control initiation. OnElementPropertyChanged method is called when the element property changes.
  • Set Control properties to LabelRenderer in OnElementChanged override method as shown in below.
  • We need to follow the below for initiating the FPT dropdown and open when the label tapped.
    if (Control != null)
    {
        dropDown = new XIDropdown();
        xfDropdown = (XFDropdown)e.NewElement;
        dropDown.AnchorView = new WeakReference<UIView>(Control);
        nfloat y = dropDown.Bounds.Height;
        if (y == 0)
            y += 40;
        dropDown.TopOffset = new CoreGraphics.CGPoint(0, -y);
        dropDown.BottomOffset = new CoreGraphics.CGPoint(0, y);
    
        //...
    
        UITapGestureRecognizer labelTap = new UITapGestureRecognizer(() =>
        {
            dropDown.Show();
        });
    
        if (xfDropdown.SelectedIndex > -1)
            Control.Text = xfDropdown.ItemsSource[xfDropdown.SelectedIndex];
        Control.UserInteractionEnabled = true;
        Control.AddGestureRecognizer(labelTap);
    }
  • Set Items Source from Xamarin.Forms Dropdown to FPT dropdown control as shown in below.
    string[] data = xfDropdown.ItemsSource.ToArray();
    dropDown.DataSource = data;
  • Set default selection of item from selected index as shown in below.
    if(xfDropdown.SelectedIndex != -1)
    {
          dropDown.SelectRow(xfDropdown.SelectedIndex);
    }
  • Create an item selected event for FPT dropdown and invoke the dropdown event created as shown below
    // ...
    
    dropDown.SelectionAction = (nint idx, string item) =>
    {
          if (xfDropdown.SelectedIndex == idx)
          {
                dropDown.Dispose();
                return;
          }
    
          xfDropdown.SelectedIndex = Convert.ToInt32(idx);
          Control.Text = item;
          xfDropdown.OnItemSelected(xfDropdown.SelectedIndex);
    };
  • In the same way, we will assign ItemsSource & SelectedIndex to FPT dropdown when the property changes using OnElementPropertyChanged as shown below.
    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
          base.OnElementPropertyChanged(sender, e);
          dropDown.Width = (nfloat)Element.Width;
          if (e.PropertyName == XFDropdown.SelectedIndexProperty.PropertyName)
          {
                if (xfDropdown.SelectedIndex > -1)
                      Control.Text = xfDropdown.ItemsSource[xfDropdown.SelectedIndex];
                dropDown.SelectRow(xfDropdown.SelectedIndex);
          }
    
          if (e.PropertyName == XFDropdown.ItemsSourceProperty.PropertyName)
          {
                string[] data = xfDropdown.ItemsSource.ToArray();
                dropDown.DataSource = data;
          }
    }
  • Add Export Renderer above the namespace to link dropdown view in .NetStandard project to iOS Client Project. This is very important step for any custom renderer approach.
    [assembly: ExportRenderer(typeof(Dropdown), typeof(DropdownRenderer))]
    namespace XF.Ctrls.iOS

Full Code of Dropdown Renderer

Here, we will see the full code for Dropdown Renderer.

[assembly: ExportRenderer(typeof(XFDropdown), typeof(DropdownRenderer))]
namespace XF.Ctrls.iOS
{
    public class DropdownRenderer : LabelRenderer
    {

        XFDropdown xfDropdown = null;
        XIDropdown dropDown = null;

        protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
        {
            base.OnElementChanged(e);
            if (Control != null)
            {
                dropDown = new XIDropdown();
                xfDropdown = (XFDropdown)e.NewElement;
                dropDown.AnchorView = new WeakReference<UIView>(Control);
                nfloat y = dropDown.Bounds.Height;
                if (y == 0)
                    y += 40;

                dropDown.TopOffset = new CoreGraphics.CGPoint(0, -y);
                dropDown.BottomOffset = new CoreGraphics.CGPoint(0, y);
                string[] data = xfDropdown.ItemsSource.ToArray();
                dropDown.DataSource = data;
                Control.Text = data[0];
                dropDown.SelectionAction = (nint idx, string item) =>
                {
                    if (xfDropdown.SelectedIndex == idx)
                    {
                        dropDown.Dispose();
                        return;
                    }
                    xfDropdown.SelectedIndex = Convert.ToInt32(idx);
                    Control.Text = item;
                    xfDropdown.OnItemSelected(xfDropdown.SelectedIndex);
                };

                UITapGestureRecognizer labelTap = new UITapGestureRecognizer(() =>
                {
                    dropDown.Show();
                });

                if (xfDropdown.SelectedIndex > -1)
                    Control.Text = xfDropdown.ItemsSource[xfDropdown.SelectedIndex];
                Control.UserInteractionEnabled = true;
                Control.AddGestureRecognizer(labelTap);
            }
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            dropDown.Width = (nfloat)Element.Width;
            if (e.PropertyName == XFDropdown.SelectedIndexProperty.PropertyName)
            {
                if (xfDropdown.SelectedIndex > -1)
                    Control.Text = xfDropdown.ItemsSource[xfDropdown.SelectedIndex];
                dropDown.SelectRow(xfDropdown.SelectedIndex);
            }
            if (e.PropertyName == XFDropdown.ItemsSourceProperty.PropertyName)
            {
                string[] data = xfDropdown.ItemsSource.ToArray();
                dropDown.DataSource = data;
            }
        }
    }
}

Step 4: Implementation of Dropdown & It’s Demo for iOS Platform

In this step, we will see how to use the view in Xamarin.Forms.

  • Open your designer file and in my case MainPage.xaml and add the control as shown below.
    <local:Dropdown HorizontalOptions="FillAndExpand"
                    VerticalOptions="Center"
                    BackgroundColor="LawnGreen"
                    x:Name="dropdown"/>
  • Set ItemsSource and SelectedIndex as shown in below.
    dropdown.ItemsSource = Items1;
    dropdown.SelectedIndex = 1;
  • Add item selection event to dropdown as shown in below.
    public MainPage()
    {
          //...
          dropdown.ItemSelected += OnDropdownSelected;
    }
    
    private void OnDropdownSelected(object sender, ItemSelectedEventArgs e)
    {
          label.Text = Items1[e.SelectedIndex];
    }

Full Code implementation of Dropdown in MainPage

Here, we will see the full code for Main Page.

namespace XF.Ctrls
{
    public partial class MainPage : ContentPage
    {
        List<string> Items1 = new List<string>();
        List<string> Items2 = new List<string>();
        bool IsItem1 = true;

        public MainPage()
        {
            InitializeComponent();

            for (int i = 0; i < 4; i++)
            {
                Items1.Add(i.ToString());
            }

            for (int i = 0; i < 10; i++)
            {
                Items2.Add(i.ToString());
            }

            dropdown.ItemsSource = Items1;
            dropdown.SelectedIndex = 1;
            dropdown.ItemSelected += OnDropdownSelected;
        }

        private void OnDropdownSelected(object sender, ItemSelectedEventArgs e)
        {
            label.Text = IsItem1 ? Items1[e.SelectedIndex] : Items2[e.SelectedIndex];
        }

        private void btn_Clicked(object sender, EventArgs e)
        {
            dropdown.ItemsSource = IsItem1 ? Items2 : Items1;
            dropdown.SelectedIndex = IsItem1 ? 5 : 1;
            IsItem1 = !IsItem1;
        }
    }
}

Demo

The following screens shows the output this tutorial and it is awesome to have this dropdown in Xamarin.Forms.

Platform

Screenshots

Android

iOS

This article covers the implementation of new dropdown control in iOS Platform. Refer my previous article for the implementation of Dropdown in Android Platform.

My plan is to create a dropdown control for supporting all platforms and offering this control as a standard plugin.

Download Code

You can download the code from GitHub. If you have doubt, feel free to post comment. If you like this article and is useful to you, do like, share the article & star the repository on GitHub.

Share this

Related Posts

Latest
Previous
Next Post »

Please Comment about the Posts and Blog