feat: remove some warnings.
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
using System.Collections;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using Avalonia;
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
@@ -9,11 +8,8 @@ using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Styling;
|
||||
using Irihi.Avalonia.Shared.Common;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
@@ -28,16 +24,73 @@ public class TagInput : TemplatedControl
|
||||
public const string PART_ItemsControl = "PART_ItemsControl";
|
||||
public const string PART_Watermark = "PART_Watermark";
|
||||
|
||||
private readonly TextBox _textBox;
|
||||
private ItemsControl? _itemsControl;
|
||||
private Visual? _watermark;
|
||||
|
||||
public static readonly StyledProperty<IList<string>> TagsProperty =
|
||||
AvaloniaProperty.Register<TagInput, IList<string>>(
|
||||
nameof(Tags));
|
||||
|
||||
public static readonly StyledProperty<string?> WatermarkProperty = TextBox.WatermarkProperty.AddOwner<TagInput>();
|
||||
|
||||
public static readonly StyledProperty<int> MaxCountProperty = AvaloniaProperty.Register<TagInput, int>(
|
||||
nameof(MaxCount), int.MaxValue);
|
||||
|
||||
public static readonly DirectProperty<TagInput, IList> ItemsProperty =
|
||||
AvaloniaProperty.RegisterDirect<TagInput, IList>(
|
||||
nameof(Items), o => o.Items);
|
||||
|
||||
public static readonly StyledProperty<ControlTheme> InputThemeProperty =
|
||||
AvaloniaProperty.Register<TagInput, ControlTheme>(
|
||||
nameof(InputTheme));
|
||||
|
||||
public static readonly StyledProperty<IDataTemplate?> ItemTemplateProperty =
|
||||
AvaloniaProperty.Register<TagInput, IDataTemplate?>(
|
||||
nameof(ItemTemplate));
|
||||
|
||||
public static readonly StyledProperty<string> SeparatorProperty = AvaloniaProperty.Register<TagInput, string>(
|
||||
nameof(Separator));
|
||||
|
||||
public static readonly StyledProperty<LostFocusBehavior> LostFocusBehaviorProperty =
|
||||
AvaloniaProperty.Register<TagInput, LostFocusBehavior>(
|
||||
nameof(LostFocusBehavior));
|
||||
|
||||
|
||||
public static readonly StyledProperty<bool> AllowDuplicatesProperty = AvaloniaProperty.Register<TagInput, bool>(
|
||||
nameof(AllowDuplicates), true);
|
||||
|
||||
public static readonly StyledProperty<object?> InnerLeftContentProperty =
|
||||
AvaloniaProperty.Register<TagInput, object?>(
|
||||
nameof(InnerLeftContent));
|
||||
|
||||
public static readonly StyledProperty<object?> InnerRightContentProperty =
|
||||
AvaloniaProperty.Register<TagInput, object?>(
|
||||
nameof(InnerRightContent));
|
||||
|
||||
private readonly TextBox _textBox;
|
||||
|
||||
private IList _items = null!;
|
||||
private ItemsControl? _itemsControl;
|
||||
|
||||
private TextPresenter? _presenter;
|
||||
private Visual? _watermark;
|
||||
|
||||
|
||||
static TagInput()
|
||||
{
|
||||
InputThemeProperty.Changed.AddClassHandler<TagInput>((o, e) => o.OnInputThemePropertyChanged(e));
|
||||
TagsProperty.Changed.AddClassHandler<TagInput>((o, e) => o.OnTagsPropertyChanged(e));
|
||||
}
|
||||
|
||||
public TagInput()
|
||||
{
|
||||
_textBox = new TextBox();
|
||||
_textBox.AddHandler(KeyDownEvent, OnTextBoxKeyDown, RoutingStrategies.Tunnel);
|
||||
_textBox.AddHandler(LostFocusEvent, OnTextBox_LostFocus, RoutingStrategies.Bubble);
|
||||
Items = new AvaloniaList<object>
|
||||
{
|
||||
_textBox
|
||||
};
|
||||
Tags = new ObservableCollection<string>();
|
||||
}
|
||||
|
||||
public string? Watermark
|
||||
{
|
||||
get => GetValue(WatermarkProperty);
|
||||
@@ -50,37 +103,58 @@ public class TagInput : TemplatedControl
|
||||
set => SetValue(TagsProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<int> MaxCountProperty = AvaloniaProperty.Register<TagInput, int>(
|
||||
nameof(MaxCount), int.MaxValue);
|
||||
|
||||
public int MaxCount
|
||||
{
|
||||
get => GetValue(MaxCountProperty);
|
||||
set => SetValue(MaxCountProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DirectProperty<TagInput, IList> ItemsProperty =
|
||||
AvaloniaProperty.RegisterDirect<TagInput, IList>(
|
||||
nameof(Items), o => o.Items);
|
||||
|
||||
private IList _items;
|
||||
|
||||
public IList Items
|
||||
{
|
||||
get => _items;
|
||||
private set => SetAndRaise(ItemsProperty, ref _items, value);
|
||||
}
|
||||
|
||||
public TagInput()
|
||||
public ControlTheme InputTheme
|
||||
{
|
||||
_textBox = new TextBox();
|
||||
_textBox.AddHandler(KeyDownEvent, OnTextBoxKeyDown, RoutingStrategies.Tunnel);
|
||||
_textBox.AddHandler(LostFocusEvent, OnTextBox_LostFocus, RoutingStrategies.Bubble);
|
||||
Items = new AvaloniaList<object>
|
||||
{
|
||||
_textBox
|
||||
};
|
||||
Tags = new ObservableCollection<string>();
|
||||
get => GetValue(InputThemeProperty);
|
||||
set => SetValue(InputThemeProperty, value);
|
||||
}
|
||||
|
||||
public IDataTemplate? ItemTemplate
|
||||
{
|
||||
get => GetValue(ItemTemplateProperty);
|
||||
set => SetValue(ItemTemplateProperty, value);
|
||||
}
|
||||
|
||||
public string Separator
|
||||
{
|
||||
get => GetValue(SeparatorProperty);
|
||||
set => SetValue(SeparatorProperty, value);
|
||||
}
|
||||
|
||||
public LostFocusBehavior LostFocusBehavior
|
||||
{
|
||||
get => GetValue(LostFocusBehaviorProperty);
|
||||
set => SetValue(LostFocusBehaviorProperty, value);
|
||||
}
|
||||
|
||||
public bool AllowDuplicates
|
||||
{
|
||||
get => GetValue(AllowDuplicatesProperty);
|
||||
set => SetValue(AllowDuplicatesProperty, value);
|
||||
}
|
||||
|
||||
public object? InnerLeftContent
|
||||
{
|
||||
get => GetValue(InnerLeftContentProperty);
|
||||
set => SetValue(InnerLeftContentProperty, value);
|
||||
}
|
||||
|
||||
public object? InnerRightContent
|
||||
{
|
||||
get => GetValue(InnerRightContentProperty);
|
||||
set => SetValue(InnerRightContentProperty, value);
|
||||
}
|
||||
|
||||
private void OnTextBox_LostFocus(object? sender, RoutedEventArgs e)
|
||||
@@ -96,81 +170,6 @@ public class TagInput : TemplatedControl
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<ControlTheme> InputThemeProperty =
|
||||
AvaloniaProperty.Register<TagInput, ControlTheme>(
|
||||
nameof(InputTheme));
|
||||
|
||||
public ControlTheme InputTheme
|
||||
{
|
||||
get => GetValue(InputThemeProperty);
|
||||
set => SetValue(InputThemeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IDataTemplate?> ItemTemplateProperty =
|
||||
AvaloniaProperty.Register<TagInput, IDataTemplate?>(
|
||||
nameof(ItemTemplate));
|
||||
|
||||
public IDataTemplate? ItemTemplate
|
||||
{
|
||||
get => GetValue(ItemTemplateProperty);
|
||||
set => SetValue(ItemTemplateProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<string> SeparatorProperty = AvaloniaProperty.Register<TagInput, string>(
|
||||
nameof(Separator));
|
||||
|
||||
public string Separator
|
||||
{
|
||||
get => GetValue(SeparatorProperty);
|
||||
set => SetValue(SeparatorProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<LostFocusBehavior> LostFocusBehaviorProperty = AvaloniaProperty.Register<TagInput, LostFocusBehavior>(
|
||||
nameof(LostFocusBehavior));
|
||||
|
||||
public LostFocusBehavior LostFocusBehavior
|
||||
{
|
||||
get => GetValue(LostFocusBehaviorProperty);
|
||||
set => SetValue(LostFocusBehaviorProperty, value);
|
||||
}
|
||||
|
||||
|
||||
public static readonly StyledProperty<bool> AllowDuplicatesProperty = AvaloniaProperty.Register<TagInput, bool>(
|
||||
nameof(AllowDuplicates), defaultValue: true);
|
||||
|
||||
public bool AllowDuplicates
|
||||
{
|
||||
get => GetValue(AllowDuplicatesProperty);
|
||||
set => SetValue(AllowDuplicatesProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<object?> InnerLeftContentProperty =
|
||||
AvaloniaProperty.Register<TagInput, object?>(
|
||||
nameof(InnerLeftContent));
|
||||
|
||||
public object? InnerLeftContent
|
||||
{
|
||||
get => GetValue(InnerLeftContentProperty);
|
||||
set => SetValue(InnerLeftContentProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<object?> InnerRightContentProperty =
|
||||
AvaloniaProperty.Register<TagInput, object?>(
|
||||
nameof(InnerRightContent));
|
||||
|
||||
public object? InnerRightContent
|
||||
{
|
||||
get => GetValue(InnerRightContentProperty);
|
||||
set => SetValue(InnerRightContentProperty, value);
|
||||
}
|
||||
|
||||
|
||||
static TagInput()
|
||||
{
|
||||
InputThemeProperty.Changed.AddClassHandler<TagInput>((o, e) => o.OnInputThemePropertyChanged(e));
|
||||
TagsProperty.Changed.AddClassHandler<TagInput>((o, e) => o.OnTagsPropertyChanged(e));
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
@@ -178,46 +177,37 @@ public class TagInput : TemplatedControl
|
||||
_watermark = e.NameScope.Find<Visual>(PART_Watermark);
|
||||
}
|
||||
|
||||
private TextPresenter? _presenter;
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
if (_watermark is null) return;
|
||||
_presenter = _textBox.GetTemplateChildren().OfType<TextPresenter>().FirstOrDefault();
|
||||
_presenter?.GetObservable(TextPresenter.PreeditTextProperty).Subscribe(a => CheckEmpty());
|
||||
_textBox.GetObservable(TextBox.TextProperty).Subscribe(a => CheckEmpty());
|
||||
_presenter?.GetObservable(TextPresenter.PreeditTextProperty).Subscribe(_ => CheckEmpty());
|
||||
_textBox.GetObservable(TextBox.TextProperty).Subscribe(_ => CheckEmpty());
|
||||
if (Tags is INotifyCollectionChanged incc)
|
||||
{
|
||||
incc.GetWeakCollectionChangedObservable().Subscribe(a => this.CheckEmpty());
|
||||
}
|
||||
incc.GetWeakCollectionChangedObservable().Subscribe(_ => CheckEmpty());
|
||||
}
|
||||
|
||||
private void OnInputThemePropertyChanged(AvaloniaPropertyChangedEventArgs args)
|
||||
{
|
||||
var newTheme = args.GetNewValue<ControlTheme>();
|
||||
if (newTheme?.TargetType == typeof(TextBox))
|
||||
{
|
||||
_textBox.Theme = newTheme;
|
||||
}
|
||||
var newTheme = args.GetNewValue<ControlTheme?>();
|
||||
if (newTheme?.TargetType == typeof(TextBox)) _textBox.Theme = newTheme;
|
||||
}
|
||||
|
||||
|
||||
private void CheckEmpty()
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(_presenter?.PreeditText) && string.IsNullOrEmpty(_textBox?.Text) && (Tags.Count==0))
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_presenter?.PreeditText) && string.IsNullOrEmpty(_textBox.Text) &&
|
||||
Tags.Count == 0)
|
||||
PseudoClasses.Set(PseudoClassName.PC_Empty, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
PseudoClasses.Set(PseudoClassName.PC_Empty, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTagsPropertyChanged(AvaloniaPropertyChangedEventArgs args)
|
||||
{
|
||||
var newTags = args.GetNewValue<IList<string>>();
|
||||
var oldTags = args.GetOldValue<IList<string>>();
|
||||
|
||||
var newTags = args.GetNewValue<IList<string>?>();
|
||||
var oldTags = args.GetOldValue<IList<string>?>();
|
||||
|
||||
if (Items is AvaloniaList<object> avaloniaList)
|
||||
{
|
||||
avaloniaList.RemoveRange(0, avaloniaList.Count - 1);
|
||||
@@ -227,23 +217,13 @@ public class TagInput : TemplatedControl
|
||||
Items.Clear();
|
||||
Items.Add(_textBox);
|
||||
}
|
||||
|
||||
if (newTags != null)
|
||||
{
|
||||
for (int i = 0; i < newTags.Count; i++)
|
||||
{
|
||||
Items.Insert(Items.Count - 1, newTags[i]);
|
||||
}
|
||||
}
|
||||
if (oldTags is INotifyCollectionChanged inccold)
|
||||
{
|
||||
inccold.CollectionChanged-= OnCollectionChanged;
|
||||
}
|
||||
|
||||
if (Tags is INotifyCollectionChanged incc)
|
||||
{
|
||||
incc.CollectionChanged += OnCollectionChanged;
|
||||
}
|
||||
if (newTags != null)
|
||||
for (var i = 0; i < newTags.Count; i++)
|
||||
Items.Insert(Items.Count - 1, newTags[i]);
|
||||
if (oldTags is INotifyCollectionChanged inccold) inccold.CollectionChanged -= OnCollectionChanged;
|
||||
|
||||
if (Tags is INotifyCollectionChanged incc) incc.CollectionChanged += OnCollectionChanged;
|
||||
}
|
||||
|
||||
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
@@ -251,27 +231,21 @@ public class TagInput : TemplatedControl
|
||||
if (e.Action == NotifyCollectionChangedAction.Add)
|
||||
{
|
||||
var items = e.NewItems;
|
||||
int index = e.NewStartingIndex;
|
||||
var index = e.NewStartingIndex;
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item is string s)
|
||||
{
|
||||
Items.Insert(index, s);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Remove)
|
||||
{
|
||||
var items = e.OldItems;
|
||||
int index = e.OldStartingIndex;
|
||||
var index = e.OldStartingIndex;
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item is string s)
|
||||
{
|
||||
if (item is string)
|
||||
Items.RemoveAt(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Reset)
|
||||
{
|
||||
@@ -279,50 +253,38 @@ public class TagInput : TemplatedControl
|
||||
Items.Add(_textBox);
|
||||
InvalidateVisual();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void OnTextBoxKeyDown(object? sender, KeyEventArgs args)
|
||||
{
|
||||
if (args.Key == Key.Enter)
|
||||
{
|
||||
AddTags();
|
||||
}
|
||||
else if (args.Key == Key.Delete || args.Key == Key.Back)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_textBox.Text)||_textBox.Text?.Length == 0)
|
||||
if (string.IsNullOrEmpty(_textBox.Text) || _textBox.Text?.Length == 0)
|
||||
{
|
||||
if (Tags.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int index = Items.Count - 2;
|
||||
if (Tags.Count == 0) return;
|
||||
var index = Items.Count - 2;
|
||||
// Items.RemoveAt(index);
|
||||
Tags.RemoveAt(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void AddTags()
|
||||
{
|
||||
if (!(_textBox.Text?.Length > 0)) return;
|
||||
string[] values;
|
||||
if (!string.IsNullOrEmpty(Separator))
|
||||
{
|
||||
values = _textBox.Text.Split(new string[] { Separator },
|
||||
values = _textBox.Text.Split(new[] { Separator },
|
||||
StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
else
|
||||
{
|
||||
values = new[] { _textBox.Text };
|
||||
}
|
||||
|
||||
if (!AllowDuplicates && Tags != null)
|
||||
if (!AllowDuplicates)
|
||||
values = values.Distinct().Except(Tags).ToArray();
|
||||
|
||||
for (int i = 0; i < values.Length; i++)
|
||||
for (var i = 0; i < values.Length; i++)
|
||||
{
|
||||
int index = Items.Count - 1;
|
||||
var index = Items.Count - 1;
|
||||
// Items.Insert(index, values[i]);
|
||||
Tags?.Insert(index, values[i]);
|
||||
}
|
||||
@@ -333,16 +295,12 @@ public class TagInput : TemplatedControl
|
||||
public void Close(object o)
|
||||
{
|
||||
if (o is Control t)
|
||||
{
|
||||
if (t.Parent is ContentPresenter presenter)
|
||||
{
|
||||
int? index = _itemsControl?.IndexFromContainer(presenter);
|
||||
var index = _itemsControl?.IndexFromContainer(presenter);
|
||||
if (index is >= 0 && index < Items.Count - 1)
|
||||
{
|
||||
// Items.RemoveAt(index.Value);
|
||||
Tags.RemoveAt(index.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user