|
|
|
@ -189,7 +189,7 @@ namespace Avalonia.Controls |
|
|
|
/// <summary>
|
|
|
|
/// A control that can provide updated string values from a binding.
|
|
|
|
/// </summary>
|
|
|
|
private BindingEvaluator<string>? _valueBindingEvaluator; |
|
|
|
private BindingEvaluator<string?>? _valueMemberBindingEvaluator; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// A weak subscription for the collection changed event.
|
|
|
|
@ -439,6 +439,7 @@ namespace Avalonia.Controls |
|
|
|
if (!_settingItemTemplateFromValueMemberBinding) |
|
|
|
_itemTemplateIsFromValueMemberBinding = false; |
|
|
|
} |
|
|
|
|
|
|
|
private void OnValueMemberBindingChanged(BindingBase? value) |
|
|
|
{ |
|
|
|
if (_itemTemplateIsFromValueMemberBinding) |
|
|
|
@ -460,6 +461,16 @@ namespace Avalonia.Controls |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) |
|
|
|
{ |
|
|
|
base.OnPropertyChanged(change); |
|
|
|
|
|
|
|
if (change.Property == ValueMemberBindingProperty) |
|
|
|
{ |
|
|
|
OnValueMemberBindingChanged(change.GetNewValue<BindingBase?>()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static AutoCompleteBox() |
|
|
|
{ |
|
|
|
FocusableProperty.OverrideDefaultValue<AutoCompleteBox>(true); |
|
|
|
@ -1181,25 +1192,6 @@ namespace Avalonia.Controls |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Formats an Item for text comparisons based on Converter
|
|
|
|
/// and ConverterCulture properties.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="value">The object to format.</param>
|
|
|
|
/// <param name="clearDataContext">A value indicating whether to clear
|
|
|
|
/// the data context after the lookup is performed.</param>
|
|
|
|
/// <returns>Formatted Value.</returns>
|
|
|
|
private string? FormatValue(object? value, bool clearDataContext) |
|
|
|
{ |
|
|
|
string? result = FormatValue(value); |
|
|
|
if (clearDataContext && _valueBindingEvaluator != null) |
|
|
|
{ |
|
|
|
_valueBindingEvaluator.ClearDataContext(); |
|
|
|
} |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Converts the specified object to a string by using the
|
|
|
|
/// <see cref="P:Avalonia.Data.Binding.Converter" /> and
|
|
|
|
@ -1215,9 +1207,13 @@ namespace Avalonia.Controls |
|
|
|
/// </remarks>
|
|
|
|
protected virtual string? FormatValue(object? value) |
|
|
|
{ |
|
|
|
if (_valueBindingEvaluator != null) |
|
|
|
if (ValueMemberBinding is { } valueMemberBinding) |
|
|
|
{ |
|
|
|
return _valueBindingEvaluator.GetDynamicValue(value) ?? String.Empty; |
|
|
|
_valueMemberBindingEvaluator ??= new(); |
|
|
|
_valueMemberBindingEvaluator.UpdateBinding(valueMemberBinding); |
|
|
|
var result = _valueMemberBindingEvaluator.Evaluate(value) ?? string.Empty; |
|
|
|
_valueMemberBindingEvaluator.ClearDataContext(); |
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
return value == null ? String.Empty : value.ToString(); |
|
|
|
@ -1451,9 +1447,6 @@ namespace Avalonia.Controls |
|
|
|
|
|
|
|
_view?.Clear(); |
|
|
|
_view?.AddRange(_newViewItems); |
|
|
|
|
|
|
|
// Clear the evaluator to discard a reference to the last item
|
|
|
|
_valueBindingEvaluator?.ClearDataContext(); |
|
|
|
} |
|
|
|
finally |
|
|
|
{ |
|
|
|
@ -1638,7 +1631,7 @@ namespace Avalonia.Controls |
|
|
|
if (top != null) |
|
|
|
{ |
|
|
|
newSelectedItem = top; |
|
|
|
string? topString = FormatValue(top, true); |
|
|
|
string? topString = FormatValue(top); |
|
|
|
|
|
|
|
// Only replace partially when the two words being the same
|
|
|
|
int minLength = Math.Min(topString?.Length ?? 0, Text?.Length ?? 0); |
|
|
|
@ -1744,7 +1737,7 @@ namespace Avalonia.Controls |
|
|
|
} |
|
|
|
else if (TextSelector != null) |
|
|
|
{ |
|
|
|
text = TextSelector(SearchText, FormatValue(newItem, true)); |
|
|
|
text = TextSelector(SearchText, FormatValue(newItem)); |
|
|
|
} |
|
|
|
else if (ItemSelector != null) |
|
|
|
{ |
|
|
|
@ -1752,7 +1745,7 @@ namespace Avalonia.Controls |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
text = FormatValue(newItem, true); |
|
|
|
text = FormatValue(newItem); |
|
|
|
} |
|
|
|
|
|
|
|
// Update the Text property and the TextBox values
|
|
|
|
@ -2020,109 +2013,5 @@ namespace Avalonia.Controls |
|
|
|
return string.Equals(value, text, StringComparison.Ordinal); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// TODO12: Remove, this shouldn't be part of the public API. Use our internal BindingEvaluator instead.
|
|
|
|
/// <summary>
|
|
|
|
/// A framework element that permits a binding to be evaluated in a new data
|
|
|
|
/// context leaf node.
|
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="T">The type of dynamic binding to return.</typeparam>
|
|
|
|
public class BindingEvaluator<T> : Control |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
/// Gets or sets the string value binding used by the control.
|
|
|
|
/// </summary>
|
|
|
|
private BindingBase? _binding; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Identifies the Value dependency property.
|
|
|
|
/// </summary>
|
|
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1002:AvaloniaProperty objects should not be owned by a generic type", |
|
|
|
Justification = "This property is not supposed to be used from XAML.")] |
|
|
|
public static readonly StyledProperty<T> ValueProperty = |
|
|
|
AvaloniaProperty.Register<BindingEvaluator<T>, T>(nameof(Value)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets or sets the data item value.
|
|
|
|
/// </summary>
|
|
|
|
public T Value |
|
|
|
{ |
|
|
|
get => GetValue(ValueProperty); |
|
|
|
set => SetValue(ValueProperty, value); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets or sets the value binding.
|
|
|
|
/// </summary>
|
|
|
|
public BindingBase? ValueBinding |
|
|
|
{ |
|
|
|
get => _binding; |
|
|
|
set |
|
|
|
{ |
|
|
|
_binding = value; |
|
|
|
if (value is not null) |
|
|
|
Bind(ValueProperty, value); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the BindingEvaluator class.
|
|
|
|
/// </summary>
|
|
|
|
public BindingEvaluator() |
|
|
|
{ } |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the BindingEvaluator class,
|
|
|
|
/// setting the initial binding to the provided parameter.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="binding">The initial string value binding.</param>
|
|
|
|
public BindingEvaluator(BindingBase? binding) |
|
|
|
: this() |
|
|
|
{ |
|
|
|
ValueBinding = binding; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Clears the data context so that the control does not keep a
|
|
|
|
/// reference to the last-looked up item.
|
|
|
|
/// </summary>
|
|
|
|
public void ClearDataContext() |
|
|
|
{ |
|
|
|
DataContext = null; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Updates the data context of the framework element and returns the
|
|
|
|
/// updated binding value.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="o">The object to use as the data context.</param>
|
|
|
|
/// <param name="clearDataContext">If set to true, this parameter will
|
|
|
|
/// clear the data context immediately after retrieving the value.</param>
|
|
|
|
/// <returns>Returns the evaluated T value of the bound dependency
|
|
|
|
/// property.</returns>
|
|
|
|
public T GetDynamicValue(object o, bool clearDataContext) |
|
|
|
{ |
|
|
|
DataContext = o; |
|
|
|
T value = Value; |
|
|
|
if (clearDataContext) |
|
|
|
{ |
|
|
|
DataContext = null; |
|
|
|
} |
|
|
|
return value; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Updates the data context of the framework element and returns the
|
|
|
|
/// updated binding value.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="o">The object to use as the data context.</param>
|
|
|
|
/// <returns>Returns the evaluated T value of the bound dependency
|
|
|
|
/// property.</returns>
|
|
|
|
public T GetDynamicValue(object? o) |
|
|
|
{ |
|
|
|
DataContext = o; |
|
|
|
return Value; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|