5
5
using Avalonia . Controls . Primitives ;
6
6
using Avalonia . Controls . Shapes ;
7
7
using Avalonia . Controls . Templates ;
8
+ using Avalonia . Controls . Utils ;
8
9
using Avalonia . Data ;
9
10
using Avalonia . Input ;
10
- using Avalonia . Interactivity ;
11
11
using Avalonia . Layout ;
12
12
using Avalonia . Media ;
13
13
using Avalonia . Metadata ;
14
14
using Avalonia . Reactive ;
15
15
using Avalonia . VisualTree ;
16
- using static Avalonia . Controls . AutoCompleteBox ;
17
16
18
17
namespace Avalonia . Controls
19
18
{
@@ -89,12 +88,6 @@ public class ComboBox : SelectingItemsControl
89
88
public static readonly StyledProperty < string ? > TextProperty =
90
89
TextBlock . TextProperty . AddOwner < ComboBox > ( new ( string . Empty , BindingMode . TwoWay ) ) ;
91
90
92
- /// <summary>
93
- /// Defines the <see cref="ItemTextBinding"/> property.
94
- /// </summary>
95
- public static readonly StyledProperty < IBinding ? > ItemTextBindingProperty =
96
- AvaloniaProperty . Register < ComboBox , IBinding ? > ( nameof ( ItemTextBinding ) ) ;
97
-
98
91
/// <summary>
99
92
/// Defines the <see cref="SelectionBoxItemTemplate"/> property.
100
93
/// </summary>
@@ -118,7 +111,7 @@ public class ComboBox : SelectingItemsControl
118
111
119
112
private bool _isEditable ;
120
113
private TextBox ? _inputText ;
121
- private BindingEvaluator < string > ? _textValueBindingEvaluator = null ;
114
+ private BindingEvaluator < string ? > ? _textValueBindingEvaluator = null ;
122
115
123
116
/// <summary>
124
117
/// Initializes static members of the <see cref="ComboBox"/> class.
@@ -129,7 +122,8 @@ static ComboBox()
129
122
FocusableProperty . OverrideDefaultValue < ComboBox > ( true ) ;
130
123
IsTextSearchEnabledProperty . OverrideDefaultValue < ComboBox > ( true ) ;
131
124
TextProperty . Changed . AddClassHandler < ComboBox > ( ( x , e ) => x . TextChanged ( e ) ) ;
132
- ItemTextBindingProperty . Changed . AddClassHandler < ComboBox > ( ( x , e ) => x . ItemTextBindingChanged ( e ) ) ;
125
+ DisplayMemberBindingProperty . Changed . AddClassHandler < ComboBox > ( ( x , e ) => x . DisplayMemberBindingChanged ( e ) ) ;
126
+ TextSearch . TextBindingProperty . Changed . AddClassHandler < ComboBox > ( ( x , e ) => x . ItemTextBindingChanged ( e ) ) ;
133
127
//when the items change we need to simulate a text change to validate the text being an item or not and selecting it
134
128
ItemsSourceProperty . Changed . AddClassHandler < ComboBox > ( ( x , e ) => x . TextChanged (
135
129
new AvaloniaPropertyChangedEventArgs < string ? > ( e . Sender , TextProperty , x . Text , x . Text , e . Priority ) ) ) ;
@@ -236,19 +230,6 @@ public string? Text
236
230
set => SetValue ( TextProperty , value ) ;
237
231
}
238
232
239
- /// <summary>
240
- /// Gets or sets the <see cref="T:Avalonia.Data.Binding" /> that
241
- /// is used to get the text for editing of an item.
242
- /// </summary>
243
- /// <value>The <see cref="T:Avalonia.Data.IBinding" /> object used
244
- /// when binding to a collection property.</value>
245
- [ AssignBinding , InheritDataTypeFromItems ( nameof ( ItemsSource ) , AncestorType = typeof ( ComboBox ) ) ]
246
- public IBinding ? ItemTextBinding
247
- {
248
- get => GetValue ( ItemTextBindingProperty ) ;
249
- set => SetValue ( ItemTextBindingProperty , value ) ;
250
- }
251
-
252
233
protected override void OnInitialized ( )
253
234
{
254
235
EnsureTextValueBinderOrThrow ( ) ;
@@ -592,6 +573,9 @@ private void UpdateFlowDirection()
592
573
593
574
private void UpdateInputTextFromSelection ( object ? item )
594
575
{
576
+ //if we are modifying the text box which has deselected a value we don't want to update the textbox value
577
+ if ( _skipNextTextChanged )
578
+ return ;
595
579
SetCurrentValue ( TextProperty , GetItemTextValue ( item ) ) ;
596
580
}
597
581
@@ -655,22 +639,43 @@ public void Clear()
655
639
SelectedIndex = - 1 ;
656
640
}
657
641
658
- private void ItemTextBindingChanged ( AvaloniaPropertyChangedEventArgs e )
642
+ private void ItemTextBindingChanged ( AvaloniaPropertyChangedEventArgs e )
643
+ => HandleTextValueBindingValueChanged ( e , null ) ;
644
+
645
+ private void DisplayMemberBindingChanged ( AvaloniaPropertyChangedEventArgs e )
646
+ => HandleTextValueBindingValueChanged ( null , e ) ;
647
+
648
+ private void HandleTextValueBindingValueChanged ( AvaloniaPropertyChangedEventArgs ? textSearchPropChange ,
649
+ AvaloniaPropertyChangedEventArgs ? displayMemberPropChange )
659
650
{
660
- _textValueBindingEvaluator = e . NewValue is IBinding binding
661
- ? new ( binding ) : null ;
651
+ IBinding ? textValueBinding ;
652
+ //prioritise using the TextSearch.TextBindingProperty if possible
653
+ if ( textSearchPropChange == null && TextSearch . GetTextBinding ( this ) is IBinding textSearchBinding )
654
+ textValueBinding = textSearchBinding ;
655
+
656
+ else if ( textSearchPropChange != null && textSearchPropChange . NewValue is IBinding eventTextSearchBinding )
657
+ textValueBinding = eventTextSearchBinding ;
658
+
659
+ else if ( displayMemberPropChange != null && displayMemberPropChange . NewValue is IBinding eventDisplayMemberBinding )
660
+ textValueBinding = eventDisplayMemberBinding ;
661
+
662
+ else
663
+ textValueBinding = null ;
662
664
663
- if ( IsInitialized )
665
+ _textValueBindingEvaluator = BindingEvaluator < string ? > . TryCreate ( textValueBinding ) ;
666
+
667
+ if ( IsInitialized )
664
668
EnsureTextValueBinderOrThrow ( ) ;
665
669
666
- if ( _textValueBindingEvaluator != null )
670
+ //if the binding is set we want to set the initial value for the selected item so the text box has the correct value
671
+ if ( _textValueBindingEvaluator != null )
667
672
_textValueBindingEvaluator . Value = GetItemTextValue ( SelectedValue ) ;
668
673
}
669
674
670
675
private void EnsureTextValueBinderOrThrow ( )
671
676
{
672
677
if ( IsEditable && _textValueBindingEvaluator == null )
673
- throw new InvalidOperationException ( $ "When { nameof ( ComboBox ) } .{ nameof ( IsEditable ) } is true you must set the text value binding using { nameof ( ItemTextBinding ) } ") ;
678
+ throw new InvalidOperationException ( $ "When { nameof ( ComboBox ) } .{ nameof ( IsEditable ) } is true you must either set { nameof ( ComboBox ) } . { nameof ( DisplayMemberBinding ) } or set the text value binding using attached property { nameof ( TextSearch ) } . { nameof ( TextSearch . TextBindingProperty ) } ") ;
674
679
}
675
680
676
681
private bool _skipNextTextChanged = false ;
@@ -706,7 +711,7 @@ private string GetItemTextValue(object? item)
706
711
if ( _textValueBindingEvaluator == null )
707
712
return string . Empty ;
708
713
709
- return _textValueBindingEvaluator . GetDynamicValue ( item ) ?? item ? . ToString ( ) ?? string . Empty ;
714
+ return TextSearch . GetEffectiveText ( item , _textValueBindingEvaluator ) ;
710
715
}
711
716
}
712
717
}
0 commit comments