mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-21 08:32:21 +08:00
292 lines
9.3 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
} |