diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
index 5ca00c15..7a51f3e3 100644
--- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
+++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
@@ -298,6 +298,7 @@
+
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml
index 8be405da..e3cab592 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml
@@ -7,7 +7,6 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
- xmlns:mxic="using:Microsoft.Xaml.Interactions.Core"
xmlns:shc="using:Snap.Hutao.Control"
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
xmlns:shci="using:Snap.Hutao.Control.Image"
@@ -74,10 +73,7 @@
-
+
@@ -272,18 +268,20 @@
-
+ QueryIcon="{cw:FontIconSource Glyph=}"
+ SuggestedItemTemplate="{StaticResource SuggestionTemplate}"
+ SuggestedItemsSource="{Binding AvailableQueries}"
+ Text="{Binding FilterToken, Mode=TwoWay}"
+ TokenItemTemplate="{StaticResource SuggestionTemplate}"/>
();
InitializeComponent();
- viewModel.Initialize(new AutoSuggestBoxAccessor(AvatarSuggestBox));
+ viewModel.Initialize(new TokenizingTextBoxAccessor(AvatarSuggestBox));
}
- private class AutoSuggestBoxAccessor : IAutoSuggestBoxAccessor
+ private class TokenizingTextBoxAccessor : ITokenizingTextBoxAccessor
{
- public AutoSuggestBoxAccessor(AutoSuggestBox autoSuggestBox)
+ public TokenizingTextBoxAccessor(TokenizingTextBox tokenizingTextBox)
{
- AutoSuggestBox = autoSuggestBox;
+ TokenizingTextBox = tokenizingTextBox;
}
- public AutoSuggestBox AutoSuggestBox { get; private set; }
+ public TokenizingTextBox TokenizingTextBox { get; private set; }
}
}
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml
index 5358afed..219c399c 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml
@@ -33,10 +33,7 @@
-
+
@@ -138,17 +135,21 @@
LocalSettingKeySuffixForCurrent="WikiWeaponPage.Weapons"/>
-
+ QueryIcon="{cw:FontIconSource Glyph=}"
+ SuggestedItemTemplate="{StaticResource SuggestionTemplate}"
+ SuggestedItemsSource="{Binding AvailableQueries}"
+ Text="{Binding FilterToken, Mode=TwoWay}"
+ TokenItemTemplate="{StaticResource SuggestionTemplate}"/>
();
InitializeComponent();
- viewModel.Initialize(new AutoSuggestBoxAccessor(WeaponSuggestBox));
+ viewModel.Initialize(new TokenizingTextBoxAccessor(WeaponSuggestBox));
}
- private class AutoSuggestBoxAccessor : IAutoSuggestBoxAccessor
+ private class TokenizingTextBoxAccessor : ITokenizingTextBoxAccessor
{
- public AutoSuggestBoxAccessor(AutoSuggestBox autoSuggestBox)
+ public TokenizingTextBoxAccessor(TokenizingTextBox tokenizingTextBox)
{
- AutoSuggestBox = autoSuggestBox;
+ TokenizingTextBox = tokenizingTextBox;
}
- public AutoSuggestBox AutoSuggestBox { get; private set; }
+ public TokenizingTextBox TokenizingTextBox { get; private set; }
}
}
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IAutoSuggestBoxAccessor.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/ITokenizingTextBoxAccessor.cs
similarity index 50%
rename from src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IAutoSuggestBoxAccessor.cs
rename to src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/ITokenizingTextBoxAccessor.cs
index 2f5233ca..64964f1e 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IAutoSuggestBoxAccessor.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/ITokenizingTextBoxAccessor.cs
@@ -1,12 +1,12 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
-using Microsoft.UI.Xaml.Controls;
+using CommunityToolkit.WinUI.Controls;
using Snap.Hutao.Control;
namespace Snap.Hutao.ViewModel.Wiki;
-internal interface IAutoSuggestBoxAccessor : IXamlElementAccessor
+internal interface ITokenizingTextBoxAccessor : IXamlElementAccessor
{
- AutoSuggestBox AutoSuggestBox { get; }
+ TokenizingTextBox TokenizingTextBox { get; }
}
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IWikiViewModelInitialization.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IWikiViewModelInitialization.cs
index 45335020..c41c48cf 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IWikiViewModelInitialization.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IWikiViewModelInitialization.cs
@@ -5,5 +5,5 @@ namespace Snap.Hutao.ViewModel.Wiki;
internal interface IWikiViewModelInitialization
{
- void Initialize(IAutoSuggestBoxAccessor accessor);
+ void Initialize(ITokenizingTextBoxAccessor accessor);
}
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs
index 2c2283cc..53f44fbf 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs
@@ -1,6 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using CommunityToolkit.WinUI.Controls;
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Control.Collection.AdvancedCollectionView;
using Snap.Hutao.Factory.ContentDialog;
@@ -20,6 +21,7 @@ using Snap.Hutao.Service.User;
using Snap.Hutao.View.Dialog;
using Snap.Hutao.Web.Response;
using System.Collections.Frozen;
+using System.Collections.ObjectModel;
using System.Runtime.InteropServices;
using CalculateAvatarPromotionDelta = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.AvatarPromotionDelta;
using CalculateClient = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.CalculateClient;
@@ -48,7 +50,8 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki
private AdvancedCollectionView? avatars;
private Avatar? selected;
- private string? filterText;
+ private ObservableCollection? filterTokens;
+ private string? filterToken;
private BaseValueInfo? baseValueInfo;
private Dictionary>? levelAvatarCurveMap;
private List? promotes;
@@ -79,15 +82,20 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki
public BaseValueInfo? BaseValueInfo { get => baseValueInfo; set => SetProperty(ref baseValueInfo, value); }
///
- /// 筛选文本
+ /// 保存的筛选标志
///
- public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); }
+ public ObservableCollection? FilterTokens { get => filterTokens; set => SetProperty(ref filterTokens, value); }
- public void Initialize(IAutoSuggestBoxAccessor accessor)
+ public string? FilterToken { get => filterToken; set => SetProperty(ref filterToken, value); }
+
+ public FrozenSet? AvailableQueries { get => availableQueries; }
+
+ public void Initialize(ITokenizingTextBoxAccessor accessor)
{
- accessor.AutoSuggestBox.TextChanged += OnFilterSuggestionRequested;
- accessor.AutoSuggestBox.SuggestionChosen += OnFilterSuggestionChosen;
- accessor.AutoSuggestBox.QuerySubmitted += ApplyFilter;
+ accessor.TokenizingTextBox.TextChanged += OnFilterSuggestionRequested;
+ accessor.TokenizingTextBox.QuerySubmitted += OnQuerySubmitted;
+ accessor.TokenizingTextBox.TokenItemAdded += OnTokenItemModified;
+ accessor.TokenizingTextBox.TokenItemRemoved += OnTokenItemModified;
}
protected override async ValueTask InitializeUIAsync()
@@ -112,6 +120,7 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki
await taskContext.SwitchToMainThreadAsync();
Avatars = new(list, true);
Selected = Avatars.View.ElementAtOrDefault(0);
+ FilterTokens = [];
availableQueries = FrozenSet.ToFrozenSet(
[
@@ -231,36 +240,46 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki
return;
}
- if (string.IsNullOrWhiteSpace(FilterText))
+ if (string.IsNullOrWhiteSpace(FilterToken))
{
return;
}
if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)
{
- sender.ItemsSource = availableQueries.Where(q => q.Contains(FilterText, StringComparison.OrdinalIgnoreCase));
+ sender.ItemsSource = availableQueries.Where(q => q.Contains(FilterToken, StringComparison.OrdinalIgnoreCase));
}
}
- private void OnFilterSuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args)
+ private void OnQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
- sender.Text = args.SelectedItem.ToString();
+ if (args.ChosenSuggestion is not null)
+ {
+ return;
+ }
+
+ ApplyFilter();
}
- private void ApplyFilter(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
+ private void OnTokenItemModified(TokenizingTextBox sender, object args)
+ {
+ ApplyFilter();
+ }
+
+ private void ApplyFilter()
{
if (Avatars is null)
{
return;
}
- if (string.IsNullOrWhiteSpace(FilterText))
+ if (FilterTokens.IsNullOrEmpty())
{
Avatars.Filter = default!;
return;
}
- Avatars.Filter = AvatarFilter.Compile(FilterText);
+ Avatars.Filter = AvatarFilter.Compile(string.Join(' ', FilterTokens));
if (Selected is not null && Avatars.Contains(Selected))
{
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs
index 2cc99cbb..a1912c90 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs
@@ -1,6 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using CommunityToolkit.WinUI.Controls;
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Control.Collection.AdvancedCollectionView;
using Snap.Hutao.Factory.ContentDialog;
@@ -45,7 +46,8 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki
private AdvancedCollectionView? weapons;
private Weapon? selected;
- private string? filterText;
+ private List? filterTokens;
+ private string? filterToken;
private BaseValueInfo? baseValueInfo;
private Dictionary>? levelWeaponCurveMap;
private List? promotes;
@@ -76,15 +78,20 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki
public BaseValueInfo? BaseValueInfo { get => baseValueInfo; set => SetProperty(ref baseValueInfo, value); }
///
- /// 筛选文本
+ /// 保存的筛选标志
///
- public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); }
+ public List? FilterTokens { get => filterTokens; set => SetProperty(ref filterTokens, value); }
- public void Initialize(IAutoSuggestBoxAccessor accessor)
+ public string? FilterToken { get => filterToken; set => SetProperty(ref filterToken, value); }
+
+ public FrozenSet AvailableQueries { get => availableQueries; }
+
+ public void Initialize(ITokenizingTextBoxAccessor accessor)
{
- accessor.AutoSuggestBox.TextChanged += OnFilterSuggestionRequested;
- accessor.AutoSuggestBox.SuggestionChosen += OnFilterSuggestionChosen;
- accessor.AutoSuggestBox.QuerySubmitted += ApplyFilter;
+ accessor.TokenizingTextBox.TextChanged += OnFilterSuggestionRequested;
+ accessor.TokenizingTextBox.QuerySubmitted += OnQuerySubmitted;
+ accessor.TokenizingTextBox.TokenItemAdded += OnTokenItemModified;
+ accessor.TokenizingTextBox.TokenItemRemoved += OnTokenItemModified;
}
///
@@ -109,6 +116,7 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki
Weapons = new(list, true);
Selected = Weapons.View.ElementAtOrDefault(0);
+ FilterTokens = [];
availableQueries = FrozenSet.ToFrozenSet(
[
@@ -213,36 +221,46 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki
return;
}
- if (string.IsNullOrWhiteSpace(FilterText))
+ if (string.IsNullOrWhiteSpace(FilterToken))
{
return;
}
if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)
{
- sender.ItemsSource = availableQueries.Where(q => q.Contains(FilterText, StringComparison.OrdinalIgnoreCase));
+ sender.ItemsSource = availableQueries.Where(q => q.Contains(FilterToken, StringComparison.OrdinalIgnoreCase));
}
}
- private void OnFilterSuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args)
+ private void OnQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
- sender.Text = args.SelectedItem.ToString();
+ if (args.ChosenSuggestion is not null)
+ {
+ return;
+ }
+
+ ApplyFilter();
}
- private void ApplyFilter(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
+ private void OnTokenItemModified(TokenizingTextBox sender, object args)
+ {
+ ApplyFilter();
+ }
+
+ private void ApplyFilter()
{
if (Weapons is null)
{
return;
}
- if (string.IsNullOrWhiteSpace(FilterText))
+ if (FilterTokens.IsNullOrEmpty())
{
Weapons.Filter = default!;
return;
}
- Weapons.Filter = WeaponFilter.Compile(FilterText);
+ Weapons.Filter = WeaponFilter.Compile(string.Join(' ', FilterTokens));
if (Selected is not null && Weapons.Contains(Selected))
{