Browse Source

Remove AutoCompleteBox.BindingEvaluator (#20596)

* Remove AutoCompleteBox.BindingEvaluator

* Fix AutoCompleteBoxPage sample

* Update API suppressions
pull/20108/merge
Julien Lebosquain 2 days ago
committed by GitHub
parent
commit
313bceea90
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 12
      api/Avalonia.nupkg.xml
  2. 20
      samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs
  3. 26
      src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.Properties.cs
  4. 153
      src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs

12
api/Avalonia.nupkg.xml

@ -31,6 +31,12 @@
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Controls.AutoCompleteBox.BindingEvaluator`1</Target>
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll</Left>
<Right>current/Avalonia/lib/net10.0/Avalonia.Controls.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Controls.NativeMenuItemToggleType</Target>
@ -79,6 +85,12 @@
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Controls.AutoCompleteBox.BindingEvaluator`1</Target>
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll</Left>
<Right>current/Avalonia/lib/net8.0/Avalonia.Controls.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Controls.NativeMenuItemToggleType</Target>

20
samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs

@ -7,30 +7,12 @@ using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.LogicalTree;
using ControlCatalog.Models;
namespace ControlCatalog.Pages
{
public partial class AutoCompleteBoxPage : UserControl
{
public class StateData
{
public string Name { get; private set; }
public string Abbreviation { get; private set; }
public string Capital { get; private set; }
public StateData(string name, string abbreviatoin, string capital)
{
Name = name;
Abbreviation = abbreviatoin;
Capital = capital;
}
public override string ToString()
{
return Name;
}
}
private static StateData[] BuildAllStates()
{
return new StateData[]

26
src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.Properties.cs

@ -191,6 +191,12 @@ namespace Avalonia.Controls
public static readonly StyledProperty<object?> InnerRightContentProperty =
TextBox.InnerRightContentProperty.AddOwner<AutoCompleteBox>();
/// <summary>
/// Defines the <see cref="ValueMemberBinding" /> property.
/// </summary>
public static readonly StyledProperty<BindingBase?> ValueMemberBindingProperty =
AvaloniaProperty.Register<AutoCompleteBox, BindingBase?>(nameof(ValueMemberBinding));
/// <summary>
/// Gets or sets the caret index
/// </summary>
@ -311,26 +317,16 @@ namespace Avalonia.Controls
}
/// <summary>
/// Gets or sets the <see cref="T:Avalonia.Data.Binding" /> that
/// is used to get the values for display in the text portion of
/// the <see cref="AutoCompleteBox" />
/// control.
/// Gets or sets the <see cref="BindingBase" /> that is used to get the values for display in the text portion
/// of the <see cref="AutoCompleteBox" /> control.
/// </summary>
/// <value>The <see cref="T:Avalonia.Data.IBinding" /> object used
/// when binding to a collection property.</value>
/// <value>The <see cref="T:Avalonia.Data.BindingBase" /> object used when binding to a collection property.</value>
[AssignBinding]
[InheritDataTypeFromItems(nameof(ItemsSource))]
public BindingBase? ValueMemberBinding
{
get => _valueBindingEvaluator?.ValueBinding;
set
{
if (ValueMemberBinding != value)
{
_valueBindingEvaluator = new BindingEvaluator<string>(value);
OnValueMemberBindingChanged(value);
}
}
get => GetValue(ValueMemberBindingProperty);
set => SetValue(ValueMemberBindingProperty, value);
}
/// <summary>

153
src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs

@ -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;
}
}
}
}

Loading…
Cancel
Save