@@ -15,10 +15,10 @@ namespace UnityMvvmToolkit.UITK.BindableUIElements
1515 public partial class BindableDropdownField : DropdownField , IBindableCollection , IInitializable , IDisposable
1616 {
1717 private IProperty < string > _selectedItemProperty ;
18- private IReadOnlyProperty < ObservableCollection < string > > _itemsSource ;
19-
2018 private PropertyBindingData _selectedItemBindingData ;
19+
2120 private PropertyBindingData _itemsSourceBindingData ;
21+ private IReadOnlyProperty < ObservableCollection < string > > _itemsSource ;
2222
2323 public void Initialize ( )
2424 {
@@ -27,102 +27,155 @@ public void Initialize()
2727
2828 public void Dispose ( )
2929 {
30- choices . Clear ( ) ;
30+ RemoveAllItems ( ) ;
3131 }
32-
32+
3333 public void SetBindingContext ( IBindingContext context , IObjectProvider objectProvider )
3434 {
35- if ( string . IsNullOrWhiteSpace ( BindingItemsSourcePath ) == false )
35+ if ( string . IsNullOrWhiteSpace ( BindingItemsSourcePath ) )
3636 {
37- _itemsSourceBindingData ??= BindingItemsSourcePath . ToPropertyBindingData ( ) ;
38- _itemsSource = objectProvider
39- . RentReadOnlyProperty < ObservableCollection < string > > ( context , _itemsSourceBindingData ) ;
40- _itemsSource . Value . CollectionChanged += OnItemsCollectionChanged ;
41- choices = new List < string > ( _itemsSource . Value ) ;
37+ return ;
4238 }
43-
39+
40+ _itemsSourceBindingData ??= BindingItemsSourcePath . ToPropertyBindingData ( ) ;
41+
42+ _itemsSource =
43+ objectProvider . RentReadOnlyProperty < ObservableCollection < string > > ( context , _itemsSourceBindingData ) ;
44+ _itemsSource . Value . CollectionChanged += OnItemsCollectionChanged ;
45+
46+ AddItems ( _itemsSource . Value ) ;
47+
4448 if ( string . IsNullOrWhiteSpace ( BindingSelectedItemPath ) == false )
4549 {
4650 _selectedItemBindingData ??= BindingSelectedItemPath . ToPropertyBindingData ( ) ;
51+
4752 _selectedItemProperty = objectProvider . RentProperty < string > ( context , _selectedItemBindingData ) ;
48- _selectedItemProperty . ValueChanged += OnSelectedItemValueChanged ;
49-
50- var isContains = choices . Contains ( _selectedItemProperty . Value ) ;
51- if ( isContains == true )
53+
54+ if ( string . IsNullOrWhiteSpace ( _selectedItemProperty . Value ) )
55+ {
56+ _selectedItemProperty . Value = choices . Count > 0 ? choices [ 0 ] : default ;
57+ }
58+ else
5259 {
5360 UpdateControlValue ( _selectedItemProperty . Value ) ;
5461 }
55-
56- this . RegisterValueChangedCallback ( OnControlValueChanged ) ;
57- _selectedItemProperty . Value = choices . Count > 0 ? choices [ 0 ] : default ;
62+
63+ _selectedItemProperty . ValueChanged += OnSelectedItemValueChanged ;
64+ this . RegisterValueChangedCallback ( OnControlSelectedValueChanged ) ;
5865 }
5966 }
6067
68+ public virtual void ResetBindingContext ( IObjectProvider objectProvider )
69+ {
70+ if ( _itemsSource is null )
71+ {
72+ return ;
73+ }
74+
75+ _itemsSource . Value . CollectionChanged -= OnItemsCollectionChanged ;
76+ objectProvider . ReturnReadOnlyProperty ( _itemsSource ) ;
77+ _itemsSource = null ;
78+
79+ if ( _selectedItemProperty is not null )
80+ {
81+ _selectedItemProperty . ValueChanged -= OnSelectedItemValueChanged ;
82+ objectProvider . ReturnProperty ( _selectedItemProperty ) ;
83+ _selectedItemProperty = null ;
84+
85+ this . UnregisterValueChangedCallback ( OnControlSelectedValueChanged ) ;
86+ }
87+
88+ RemoveAllItems ( ) ;
89+ }
90+
6191 protected virtual void OnItemsCollectionChanged ( object sender , NotifyCollectionChangedEventArgs e )
6292 {
6393 if ( e . Action == NotifyCollectionChangedAction . Add )
6494 {
6595 foreach ( string newItem in e . NewItems )
6696 {
67- choices . Add ( newItem ) ;
97+ AddItem ( newItem ) ;
6898 }
6999 }
70100
71101 if ( e . Action == NotifyCollectionChangedAction . Remove )
72102 {
73103 foreach ( string oldItem in e . OldItems )
74104 {
75- choices . Remove ( oldItem ) ;
105+ RemoveItem ( oldItem ) ;
76106 }
77107 }
78-
108+
79109 if ( e . Action == NotifyCollectionChangedAction . Reset )
80110 {
81- choices . Clear ( ) ;
111+ if ( _itemsSource . Value . Count == 0 )
112+ {
113+ RemoveAllItems ( ) ;
114+ }
115+ else
116+ {
117+ throw new InvalidOperationException ( "Action not supported." ) ;
118+ }
82119 }
83120 }
84121
85- public virtual void ResetBindingContext ( IObjectProvider objectProvider )
122+ protected virtual void OnControlSelectedValueChanged ( ChangeEvent < string > e )
123+ {
124+ _selectedItemProperty . Value = e . newValue ;
125+ }
126+
127+ private void OnSelectedItemValueChanged ( object sender , string newValue )
86128 {
87- if ( _selectedItemProperty != null )
129+ UpdateControlValue ( newValue ) ;
130+ }
131+
132+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
133+ protected virtual void UpdateControlValue ( string selectedItem )
134+ {
135+ if ( choices . Any ( ) && choices . Contains ( selectedItem ) == false )
88136 {
89- _selectedItemProperty . ValueChanged -= OnSelectedItemValueChanged ;
90- objectProvider . ReturnProperty ( _selectedItemProperty ) ;
91- _selectedItemProperty = null ;
92- this . UnregisterValueChangedCallback ( OnControlValueChanged ) ;
137+ throw new InvalidOperationException ( $ "\" { selectedItem } \" is not presented in the collection.") ;
93138 }
94-
95- if ( _itemsSource != null )
139+
140+ SetValueWithoutNotify ( selectedItem ) ;
141+ }
142+
143+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
144+ private void AddItems ( IEnumerable < string > items )
145+ {
146+ foreach ( var item in items )
96147 {
97- _itemsSource . Value . CollectionChanged -= OnItemsCollectionChanged ;
98- choices = new List < string > ( ) ;
99- objectProvider . ReturnReadOnlyProperty ( _itemsSource ) ;
100- _itemsSource = null ;
148+ AddItem ( item ) ;
101149 }
102-
103- UpdateControlValue ( default ) ;
104150 }
105151
106- protected virtual void OnControlValueChanged ( ChangeEvent < string > e )
152+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
153+ private void AddItem ( string item )
107154 {
108- _selectedItemProperty . Value = e . newValue ;
155+ if ( string . IsNullOrWhiteSpace ( item ) )
156+ {
157+ throw new NullReferenceException ( "Item cannot be null or empty." ) ;
158+ }
159+
160+ choices . Add ( item ) ;
109161 }
110162
111- private void OnSelectedItemValueChanged ( object sender , string newValue )
163+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
164+ private void RemoveItem ( string item )
112165 {
113- var isContains = choices . Contains ( newValue ) ;
114- if ( isContains == false )
166+ choices . Remove ( item ) ;
167+
168+ if ( value == item )
115169 {
116- return ;
170+ value = choices . Count == 0 ? default : choices [ ^ 1 ] ;
117171 }
118-
119- UpdateControlValue ( newValue ) ;
120172 }
121-
173+
122174 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
123- protected virtual void UpdateControlValue ( string newValue )
175+ private void RemoveAllItems ( )
124176 {
125- SetValueWithoutNotify ( newValue ) ;
177+ choices . Clear ( ) ;
178+ value = default ;
126179 }
127180 }
128181}
0 commit comments