Files
AtomUI/src/AtomUI.Controls/Select/SelectResultOptionsBox.cs
T
2025-11-03 14:26:24 +08:00

292 lines
9.3 KiB
C#

using System.Collections;
using AtomUI.Controls.Themes;
using AtomUI.Data;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Layout;
namespace AtomUI.Controls;
internal class SelectResultOptionsBox : TemplatedControl
{
#region 公共属性定义
public static readonly DirectProperty<SelectResultOptionsBox, IList?> SelectedOptionsProperty =
AvaloniaProperty.RegisterDirect<SelectResultOptionsBox, IList?>(
nameof(SelectedOptions),
o => o.SelectedOptions,
(o, v) => o.SelectedOptions = v);
public static readonly StyledProperty<SelectMode> ModeProperty =
AvaloniaProperty.Register<SelectResultOptionsBox, SelectMode>(nameof(Mode));
public static readonly StyledProperty<bool> IsSearchEnabledProperty =
Select.IsSearchEnabledProperty.AddOwner<SelectResultOptionsBox>();
public static readonly StyledProperty<bool> IsDropDownOpenProperty =
AvaloniaProperty.Register<SelectResultOptionsBox, bool>(nameof(IsDropDownOpen));
public static readonly StyledProperty<SizeType> SizeTypeProperty =
SizeTypeAwareControlProperty.SizeTypeProperty.AddOwner<SelectResultOptionsBox>();
public static readonly StyledProperty<int?> MaxTagCountProperty =
Select.MaxTagCountProperty.AddOwner<SelectResultOptionsBox>();
public static readonly StyledProperty<bool?> IsResponsiveMaxTagCountProperty =
Select.IsResponsiveMaxTagCountProperty.AddOwner<SelectResultOptionsBox>();
private IList? _selectedOptions;
public IList? SelectedOptions
{
get => _selectedOptions;
set => SetAndRaise(SelectedOptionsProperty, ref _selectedOptions, value);
}
public SelectMode Mode
{
get => GetValue(ModeProperty);
set => SetValue(ModeProperty, value);
}
public bool IsSearchEnabled
{
get => GetValue(IsSearchEnabledProperty);
set => SetValue(IsSearchEnabledProperty, value);
}
public bool IsDropDownOpen
{
get => GetValue(IsDropDownOpenProperty);
set => SetValue(IsDropDownOpenProperty, value);
}
public SizeType SizeType
{
get => GetValue(SizeTypeProperty);
set => SetValue(SizeTypeProperty, value);
}
public int? MaxTagCount
{
get => GetValue(MaxTagCountProperty);
set => SetValue(MaxTagCountProperty, value);
}
public bool? IsResponsiveMaxTagCount
{
get => GetValue(IsResponsiveMaxTagCountProperty);
set => SetValue(IsResponsiveMaxTagCountProperty, value);
}
#endregion
#region 内部属性定义
public static readonly DirectProperty<SelectResultOptionsBox, bool> IsShowDefaultPanelProperty =
AvaloniaProperty.RegisterDirect<SelectResultOptionsBox, bool>(
nameof(IsShowDefaultPanel),
o => o.IsShowDefaultPanel,
(o, v) => o.IsShowDefaultPanel = v);
private bool _isShowDefaultPanel;
public bool IsShowDefaultPanel
{
get => _isShowDefaultPanel;
set => SetAndRaise(IsShowDefaultPanelProperty, ref _isShowDefaultPanel, value);
}
#endregion
private WrapPanel? _defaultPanel;
private SelectMaxTagAwarePanel? _maxCountAwarePanel;
private SelectSearchTextBox? _searchTextBox;
private SelectRemainInfoTag? _collapsedInfoTag;
private protected readonly Dictionary<object, IDisposable> _tagsBindingDisposables = new();
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == SelectedOptionsProperty)
{
HandleSelectedOptionsChanged();
}
else if (change.Property == IsSearchEnabledProperty ||
change.Property == ModeProperty)
{
ConfigureSearchTextControl();
}
else if (change.Property == IsDropDownOpenProperty)
{
ConfigureSearchTextReadOnly();
}
else if (change.Property == IsResponsiveMaxTagCountProperty ||
change.Property == MaxTagCountProperty)
{
if (IsResponsiveMaxTagCount == true)
{
SetCurrentValue(IsShowDefaultPanelProperty, false);
}
else
{
SetCurrentValue(IsShowDefaultPanelProperty, true);
}
}
else if (change.Property == IsShowDefaultPanelProperty)
{
_defaultPanel?.Children.Clear();
_maxCountAwarePanel?.Children.Clear();
HandleSelectedOptionsChanged();
}
}
protected override void OnPointerPressed(PointerPressedEventArgs e)
{
base.OnPointerPressed(e);
e.Handled = false;
}
protected override void OnPointerReleased(PointerReleasedEventArgs e)
{
base.OnPointerReleased(e);
e.Handled = false;
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
_defaultPanel = e.NameScope.Find<WrapPanel>(SelectResultOptionsBoxThemeConstants.DefaultPanelPart);
_maxCountAwarePanel = e.NameScope.Find<SelectMaxTagAwarePanel>(SelectResultOptionsBoxThemeConstants.MaxCountAwarePanelPart);
_searchTextBox = new SelectSearchTextBox
{
HorizontalAlignment = HorizontalAlignment.Stretch
};
_collapsedInfoTag = new SelectRemainInfoTag()
{
IsClosable = false
};
BindUtils.RelayBind(this, SizeTypeProperty, _searchTextBox, SizeTypeProperty);
if (IsSearchEnabled)
{
if (Mode == SelectMode.Multiple)
{
if (IsShowDefaultPanel)
{
_defaultPanel?.Children.Add(_searchTextBox);
}
}
}
ConfigureSearchTextControl();
HandleSelectedOptionsChanged();
}
private void HandleSelectedOptionsChanged()
{
if (_isShowDefaultPanel)
{
if (_defaultPanel != null)
{
_searchTextBox?.Clear();
_defaultPanel.Children.Clear();
foreach (var entry in _tagsBindingDisposables)
{
entry.Value.Dispose();
}
_tagsBindingDisposables.Clear();
if (_selectedOptions != null)
{
foreach (var item in _selectedOptions)
{
if (item is SelectOption option)
{
var tag = new SelectTag
{
TagText = option.Header,
Option = option
};
_tagsBindingDisposables.Add(tag, BindUtils.RelayBind(this, SizeTypeProperty, tag, SizeTypeProperty));
_defaultPanel.Children.Add(tag);
}
}
}
if (_searchTextBox != null)
{
_defaultPanel.Children.Add(_searchTextBox);
_searchTextBox.Focus();
}
}
}
else
{
if (_maxCountAwarePanel != null)
{
_searchTextBox?.Clear();
_maxCountAwarePanel.Children.Clear();
foreach (var entry in _tagsBindingDisposables)
{
entry.Value.Dispose();
}
_tagsBindingDisposables.Clear();
if (_selectedOptions != null)
{
foreach (var item in _selectedOptions)
{
if (item is SelectOption option)
{
var tag = new SelectTag
{
TagText = option.Header,
Option = option
};
_tagsBindingDisposables.Add(tag, BindUtils.RelayBind(this, SizeTypeProperty, tag, SizeTypeProperty));
_maxCountAwarePanel.Children.Add(tag);
}
}
}
if (_collapsedInfoTag != null)
{
_maxCountAwarePanel.Children.Add(_collapsedInfoTag);
}
if (_searchTextBox != null)
{
_maxCountAwarePanel.Children.Add(_searchTextBox);
_searchTextBox.Focus();
}
}
}
}
private void ConfigureSearchTextControl()
{
if (_searchTextBox != null)
{
if (Mode == SelectMode.Multiple)
{
_searchTextBox.IsVisible = IsSearchEnabled;
}
}
}
private void ConfigureSearchTextReadOnly()
{
if (_searchTextBox != null)
{
if (IsDropDownOpen)
{
_searchTextBox.IsReadOnly = false;
}
else
{
_searchTextBox.Clear();
_searchTextBox.IsReadOnly = true;
}
}
}
}