2using System.Collections.ObjectModel;
3using System.Collections.Specialized;
4using Microsoft.Maui.Controls;
8 public enum SelectorSelectionMode
16 public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(
17 nameof(ItemsSource), typeof(IEnumerable), typeof(
TemplatedSelector), propertyChanged: OnItemsSourceChanged);
19 public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create(
22 public static readonly BindableProperty SelectionModeProperty = BindableProperty.Create(
23 nameof(SelectionMode), typeof(SelectorSelectionMode), typeof(
TemplatedSelector), SelectorSelectionMode.Single);
25 public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create(
26 nameof(SelectedItem), typeof(
object), typeof(
TemplatedSelector), defaultBindingMode: BindingMode.TwoWay);
28 public static readonly BindableProperty SelectedItemsProperty = BindableProperty.Create(
29 nameof(SelectedItems), typeof(IList), typeof(
TemplatedSelector), defaultValue:
new ObservableCollection<object>(), defaultBindingMode: BindingMode.TwoWay, propertyChanged: OnSelectedItemsChanged);
30 public static readonly BindableProperty SelectOnTapProperty = BindableProperty.Create(
33 public bool SelectOnTap
35 get => (bool)this.GetValue(SelectOnTapProperty);
36 set => this.SetValue(SelectOnTapProperty, value);
38 public IEnumerable ItemsSource
40 get => (IEnumerable)this.GetValue(ItemsSourceProperty);
41 set => this.SetValue(ItemsSourceProperty, value);
44 public DataTemplate ItemTemplate
46 get => (DataTemplate)this.GetValue(ItemTemplateProperty);
47 set => this.SetValue(ItemTemplateProperty, value);
50 public SelectorSelectionMode SelectionMode
52 get => (SelectorSelectionMode)this.GetValue(SelectionModeProperty);
53 set => this.SetValue(SelectionModeProperty, value);
56 public object SelectedItem
58 get => this.GetValue(SelectedItemProperty);
59 set => this.SetValue(SelectedItemProperty, value);
62 public IList SelectedItems
64 get => (IList)this.GetValue(SelectedItemsProperty);
65 set => this.SetValue(SelectedItemsProperty, value);
68 private bool syncingSelection =
false;
72 this.Orientation = StackOrientation.Vertical;
73 TryAttachSelectedItemsHandler(this.SelectedItems);
76 private static void OnSelectedItemsChanged(BindableObject bindable,
object oldValue,
object newValue)
80 selector.TryDetachSelectedItemsHandler(oldValue as IList);
81 selector.TryAttachSelectedItemsHandler(newValue as IList);
82 selector.SyncSelectionFromSelectedItems();
86 private void TryAttachSelectedItemsHandler(IList? list)
88 if (list is INotifyCollectionChanged incc)
90 incc.CollectionChanged += this.SelectedItems_CollectionChanged;
94 private void TryDetachSelectedItemsHandler(IList? list)
96 if (list is INotifyCollectionChanged incc)
98 incc.CollectionChanged -= this.SelectedItems_CollectionChanged;
102 private void SelectedItems_CollectionChanged(
object? sender, NotifyCollectionChangedEventArgs e)
104 this.SyncSelectionFromSelectedItems();
107 private static void OnItemsSourceChanged(BindableObject bindable,
object oldValue,
object newValue)
111 selector.BuildItems();
115 private void BuildItems()
117 this.Children.Clear();
118 if (this.ItemsSource ==
null || this.ItemTemplate ==
null)
120 foreach (
object Item
in this.ItemsSource)
125 Selectable = AlreadySelectable;
134 this.SelectedItems?.Contains(kycOption) ==
true,
135 o => this.ToggleSelection(o));
146 Option2.IsSelectedChanged += this.OnChildIsSelectedChanged;
150 Option3.IsSelectedChanged += this.OnChildIsSelectedChanged;
152 View Content = (View)this.ItemTemplate.CreateContent();
153 Content.BindingContext = Selectable;
154 if (this.SelectOnTap)
156 TapGestureRecognizer TapGesture =
new TapGestureRecognizer();
157 TapGesture.Tapped += (s, e) => this.ToggleSelection(Selectable);
158 Content.GestureRecognizers.Add(TapGesture);
160 this.Children.Add(Content);
163 this.SyncSelectionFromSelectedItems();
166 private void OnChildIsSelectedChanged(
object? sender, EventArgs e)
168 if (this.syncingSelection)
174 object Item = GetUnderlyingItem(ChangedSelectable);
175 if (this.SelectionMode == SelectorSelectionMode.Single && ChangedSelectable.IsSelected)
177 foreach (View ChildView
in this.Children.Cast<View>())
181 OtherSelectable.IsSelected =
false;
184 this.SelectedItem = Item;
185 if (this.SelectedItems !=
null)
187 this.SelectedItems.Clear();
188 this.SelectedItems.Add(this.SelectedItem);
191 else if (this.SelectionMode == SelectorSelectionMode.Multiple)
193 if (ChangedSelectable.IsSelected)
195 if (!this.SelectedItems.Contains(Item))
197 this.SelectedItems.Add(Item);
202 if (this.SelectedItems.Contains(Item))
204 this.SelectedItems.Remove(Item);
211 private void ToggleSelection(
object selectableOptionObj)
214 if (Selectable ==
null)
218 object Item = GetUnderlyingItem(Selectable);
219 if (this.SelectionMode == SelectorSelectionMode.Single)
222 foreach (View ChildView
in this.Children.Cast<View>())
226 OtherSelectable.IsSelected =
false;
230 Selectable.IsSelected =
true;
231 this.SelectedItem = Item;
233 if (this.SelectedItems !=
null)
235 this.SelectedItems.Clear();
236 this.SelectedItems.Add(Item);
241 Selectable.IsSelected = !Selectable.IsSelected;
242 if (Selectable.IsSelected)
244 if (!this.SelectedItems.Contains(Item))
246 this.SelectedItems.Add(Item);
251 if (this.SelectedItems.Contains(Item))
253 this.SelectedItems.Remove(Item);
259 private void SyncSelectionFromSelectedItems()
263 this.syncingSelection =
true;
264 HashSet<object> selected =
new HashSet<object>(this.SelectedItems?.Cast<object>() ?? Enumerable.Empty<
object>());
265 foreach (View child
in this.Children)
269 object item = GetUnderlyingItem(selectable);
270 bool shouldSelect = selected.Contains(item);
271 selectable.IsSelected = shouldSelect;
277 this.syncingSelection =
false;
285 return kycOption.Item;
289 return genericOption.Item;