--- /dev/null
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using Tizen.Xamarin.Forms.Extension;
+using Tizen.Xamarin.Forms.Extension.Renderer;
+using Xamarin.Forms.Platform.Tizen;
+using EHoversel = ElmSharp.Hoversel;
+using TForms = Xamarin.Forms.Platform.Tizen.Forms;
+
+[assembly: ExportRenderer(typeof(DropdownList), typeof(DropdownListRenderer))]
+namespace Tizen.Xamarin.Forms.Extension.Renderer
+{
+ public class DropdownListRenderer : ViewRenderer<DropdownList, EHoversel>
+ {
+ Dictionary<ElmSharp.HoverselItem, object> _items = new Dictionary<ElmSharp.HoverselItem, object>();
+
+ public DropdownListRenderer()
+ {
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<DropdownList> e)
+ {
+ if (Control == null)
+ {
+ var dropdownList = new EHoversel(TForms.Context.MainWindow);
+ SetNativeControl(dropdownList);
+ }
+ if (e.OldElement != null)
+ {
+ ((ObservableCollection<object>)e.OldElement.InternalItems).CollectionChanged -= OnCollectionChanged;
+ Control.ItemSelected -= ItemSelectedEventHandler;
+ Control.Dismissed -= OnDismissed;
+ }
+ if (e.NewElement != null)
+ {
+ ((ObservableCollection<object>)e.NewElement.InternalItems).CollectionChanged += OnCollectionChanged;
+ Control.ItemSelected += ItemSelectedEventHandler;
+ Control.Dismissed += OnDismissed;
+
+ Control.HoverParent = Platform.GetRenderer(Element.Parent)?.NativeView;
+
+ ClearItems();
+ AddItems(e.NewElement.InternalItems);
+
+ UpdateIsHorizontal();
+ UpdateIsExpanded();
+ }
+ base.OnElementChanged(e);
+ }
+
+ void ItemSelectedEventHandler(object sender, ElmSharp.HoverselItemEventArgs e)
+ {
+ Element.SelectedItem = _items[e.Item];
+ }
+
+ void OnDismissed(object sender, EventArgs e)
+ {
+ Element.IsExpanded = false;
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == DropdownList.IsHorizontalProperty.PropertyName)
+ {
+ UpdateIsHorizontal();
+ }
+ else if (e.PropertyName == DropdownList.IsExpandedProperty.PropertyName)
+ {
+ UpdateIsExpanded();
+ }
+ else if (e.PropertyName == DropdownList.SelectedItemProperty.PropertyName)
+ {
+ UpdateText();
+ }
+ base.OnElementPropertyChanged(sender, e);
+ }
+
+ void UpdateIsHorizontal()
+ {
+ Control.IsHorizontal = Element.IsHorizontal;
+ }
+
+ void UpdateIsExpanded()
+ {
+ if (Element.IsExpanded)
+ {
+ Control.HoverBegin();
+ }
+ else
+ {
+ Control.HoverEnd();
+ }
+ }
+
+ void UpdateText()
+ {
+ Control.Text = Element.SelectedItem != null ? Element.SelectedItem.ToString() : string.Empty;
+ }
+
+ void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ if (e.NewItems != null)
+ {
+ AddItems(e.NewItems);
+ }
+ if (e.OldItems != null)
+ {
+ RemoveItems(e.OldItems);
+ }
+ if (e.Action == NotifyCollectionChangedAction.Reset)
+ {
+ ClearItems();
+ }
+ }
+
+ void AddItems(IEnumerable items)
+ {
+ foreach (object item in items)
+ {
+ _items.Add(Control.AddItem(item.ToString()), item);
+ }
+ }
+
+ void RemoveItems(IEnumerable items)
+ {
+ foreach (object item in items)
+ {
+ var target = _items.Where(d => d.Value == item).ToList();
+ if (target.Count == 1)
+ {
+ Element.SelectedItem = null;
+ }
+ _items.Remove(target[0].Key);
+ target[0].Key.Delete();
+ }
+ }
+
+ void ClearItems()
+ {
+ Control.Clear();
+ _items.Clear();
+
+ Element.SelectedItem = null;
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Reflection;
+using Xamarin.Forms;
+
+namespace Tizen.Xamarin.Forms.Extension
+{
+ public class DropdownList : View
+ {
+ public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create("SelectedItem", typeof(object), typeof(DropdownList), default(object), BindingMode.TwoWay, coerceValue: OnCoerceSelectedItem, propertyChanged: OnSelectedItemChanged);
+
+ public static readonly BindableProperty IsHorizontalProperty = BindableProperty.Create("IsHorizontal", typeof(bool), typeof(DropdownList), default(bool));
+
+ public static readonly BindableProperty IsExpandedProperty = BindableProperty.Create("IsExpanded", typeof(bool), typeof(DropdownList), default(bool));
+
+ public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(DropdownList), default(IEnumerable), propertyChanged: OnItemsSourceChanged);
+
+ public static readonly BindableProperty DisplayMemberPathProperty = BindableProperty.Create("DisplayMemberPath", typeof(string), typeof(DropdownList), default(string), propertyChanged: OnDisplayMemberPathChanged);
+
+ public event EventHandler<SelectedItemChangedEventArgs> ItemSelected;
+
+ internal IEnumerable InternalItems => _items;
+
+ ObservableCollection<object> _items = new ObservableCollection<object>();
+
+ public DropdownList()
+ {
+ }
+
+ public object SelectedItem
+ {
+ get { return (object)GetValue(SelectedItemProperty); }
+ set { SetValue(SelectedItemProperty, value); }
+ }
+
+ public bool IsHorizontal
+ {
+ get { return (bool)GetValue(IsHorizontalProperty); }
+ set { SetValue(IsHorizontalProperty, value); }
+ }
+
+ public bool IsExpanded
+ {
+ get { return (bool)GetValue(IsExpandedProperty); }
+ set { SetValue(IsExpandedProperty, value); }
+ }
+
+ public IEnumerable ItemsSource
+ {
+ get { return (IEnumerable)GetValue(ItemsSourceProperty); }
+ set { SetValue(ItemsSourceProperty, value); }
+ }
+
+ public string DisplayMemberPath
+ {
+ get { return (string)GetValue(DisplayMemberPathProperty); }
+ set { SetValue(DisplayMemberPathProperty, value); }
+ }
+
+ static void OnItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ ((DropdownList)bindable).OnItemsSourceChanged((IEnumerable)oldValue, (IEnumerable)newValue);
+ }
+
+ void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
+ {
+ var oldObservable = oldValue as INotifyCollectionChanged;
+ if (oldObservable != null)
+ oldObservable.CollectionChanged -= ItemsSourceCollectionChanged;
+
+ var newObservable = newValue as INotifyCollectionChanged;
+ if (newObservable != null)
+ {
+ newObservable.CollectionChanged += ItemsSourceCollectionChanged;
+ }
+
+ if (newValue != null)
+ {
+ ResetItems();
+ }
+ else
+ {
+ _items.Clear();
+ }
+ }
+
+ void ItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ AddItems(e);
+ break;
+ case NotifyCollectionChangedAction.Remove:
+ RemoveItems(e);
+ break;
+ default: //Move, Replace, Reset
+ ResetItems();
+ break;
+ }
+ }
+
+ void AddItems(NotifyCollectionChangedEventArgs e)
+ {
+ foreach (object newItem in e.NewItems)
+ _items.Add(GetDisplayMember(newItem));
+ }
+
+ void RemoveItems(NotifyCollectionChangedEventArgs e)
+ {
+ int index = e.OldStartingIndex < _items.Count ? e.OldStartingIndex : _items.Count;
+ foreach (object _ in e.OldItems)
+ _items.RemoveAt(index--);
+ }
+
+ void ResetItems()
+ {
+ if (ItemsSource == null)
+ return;
+
+ _items.Clear();
+ foreach (object item in ItemsSource)
+ _items.Add(GetDisplayMember(item));
+ }
+
+ object GetDisplayMember(object item)
+ {
+ if (string.IsNullOrEmpty(DisplayMemberPath) || string.IsNullOrWhiteSpace(DisplayMemberPath))
+ return item.ToString();
+
+ PropertyInfo prop = item.GetType().GetRuntimeProperty(DisplayMemberPath);
+
+ if (prop == null)
+ return item.ToString();
+
+ return prop.GetValue(item);
+ }
+
+ static object OnCoerceSelectedItem(BindableObject bindable, object value)
+ {
+ var dropdownList = bindable as DropdownList;
+ if (!dropdownList._items.Contains(value))
+ return null;
+
+ return value;
+ }
+
+ static void OnSelectedItemChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var dropdownList = bindable as DropdownList;
+ if (oldValue != newValue)
+ dropdownList.ItemSelected?.Invoke(bindable as DropdownList, new SelectedItemChangedEventArgs(newValue));
+ }
+
+ static void OnDisplayMemberPathChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var dropdownList = bindable as DropdownList;
+ dropdownList.ResetItems();
+ }
+ }
+}