Skip to main content Skip to footer

How to Create a Custom DropDown Control in Xamarin.Forms

In the Xuni 2016 v2 release we included several new input controls such as AutoComplete, MaskedEntry, ComboBox, and DropDown. The Xuni DropDown control is the base drop-down control used in AutoComplete and ComboBox, and it’s been made public so anyone can easily create their own custom drop-downs. In this blog post I'll show you some of the basic features and how to create a custom DatePicker drop-down control.

In this article series, we also discuss Using a Native Custom Control with Xamarin.Forms via a Custom Renderer, How to Create a Custom Color Picker for Xamarin.Forms, and How to Customize Your Xamarin.Forms Apps with Animations.

Note: Xuni has since become ComponentOne Studio for Xamarin, and all controls have been optimized for Xamarin.Forms, Xamarin.iOS, and Xamarin.Android.

Xuni_Xamarin_DropDown_DatePicker

The control is composed of 3 parts: header, button and drop-down. Xuni_DropDown_Diagram The header makes up the entire width of the control. The arrow button is optional (set ShowButton=False), and it indicates to the user that the control can be expanded. The drop-down expands/collapses and also takes up the full width of the control. What makes the control extensible is that you can put any UI view into the header and drop-down parts. You can also programmatically expand and collapse the control and listen to when it expands to complete your custom drop-down solution.

Set When the Drop-Down Opens

You can programmatically expand and collapse the drop-down by setting the IsDropDownOpen property. We also designed the control to support two different touch behaviors. You can set it so that the drop-down only opens/closes when the user taps the arrow button, OR you can have it open/close when the user taps anywhere on the drop-down header. You can configure this behavior by setting the DropDownBehavior property. DropDownBehavior options:

  • ButtonTap – the drop-down opens/closes when the user taps the button.
  • HeaderTap – the drop-down opens/closes when the user taps anywhere on the header.

Since the arrow button is optional, you may prefer to set this property to HeaderTab.

Set the Drop-Down Direction Preference

Since mobile screens are small, we made it possible for the drop-down to appear above or below the header depending on available space. By default, the control tries to display the drop-down below the header. You can change this preference by setting the DropDownDirection property. DropDownDirection options:

  • AboveOrBelow – tries to open the drop-down above the header. If it’s not possible it tries to open below.
  • BelowOrAbove – tries to open the drop-down below the header. If it’s not possible it tries to open above. (default value)
  • ForceAbove – forces the drop-down to open above the header.
  • ForceBelow – forces the drop-down to open below the header.

Example – Creating a Custom DatePicker

We can use Xuni DropDown, MaskedEntry and Calendar controls together to create a custom, classic date picker. Xuni_DropDown_DatePicker Here’s the basic concept of how we can create the control.

  1. Set the XuniDropDown.Header property to an instance of XuniMaskedEntry
  2. Set the XuniDropDown.DropDown property to an instance of XuniCalendar.

    
    <xuni:XuniDropDown x:Name="dropdown" DropDownHeight="220" HeightRequest="42">  
      <xuni:XuniDropDown.Header>  
        <xuni:XuniMaskedEntry x:Name="mask" Mask="00/00/0000"/>  
      </xuni:XuniDropDown.Header>  
      <xuni:XuniDropDown.DropDown>  
        <calendar:XuniCalendar x:Name="calendar" DayOfWeekBackgroundColor="Transparent"/>  
      </xuni:XuniDropDown.DropDown>  
    </xuni:XuniDropDown>  
    
    
  3. In the calendar’s SelectedDateChanged event, set the mask value.


private void CalendarSelectionChanged(object sender, CalendarSelectionChangedEventArgs e)  
{  
    DateTime selectedDate = (DateTime)this.calendar.SelectedDate;  
    this.mask.Value = selectedDate.ToString("MM/dd/yyyy");  
    this.dropdown.IsDropDownOpen = false;  
}  

And that’s it! This takes care of most the work. You may want to also make the date editing a two-way process by updating the selected date if the user manually enters something in the MaskedEntry. And to make it even fancier, you can directly bind the XuniMaskedEntry to the XuniCalendar using a Converter. The XAML would look like this:


<xuni:XuniDropDown x:Name="dropdown">  
  <xuni:XuniDropDown.Header>  
    <xuni:XuniMaskedEntry x:Name="mask" BindingContext="{x:Reference calendar}" Mask="00/00/0000" Value="{Binding SelectedDate, Converter={StaticResource converter}}"/>  
  </xuni:XuniDropDown.Header>  
  <xuni:XuniDropDown.DropDown>  
    <calendar:XuniCalendar x:Name="calendar"/>  
  </xuni:XuniDropDown.DropDown>  
</xuni:XuniDropDown>  

And you need a converter in this case to handle the DateTime value formatting.


public class DateTimeStringConverter : IValueConverter  
{  
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)  
    {  
        if(value is DateTime)  
        {  
            return ((DateTime)value).ToString("MM/dd/yyyy");  
        }  
        return "";  
    }  

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)  
    {  
        return null;  
    }  
}  

We’ve included this entire sample in the Input101 samples. If you didn’t download the latest samples yet you can also access them from GitHub.

Download Now!<%/if%>

ComponentOne Product Manager Greg Lutz

Greg Lutz

comments powered by Disqus