mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
migrate to TokenizingTextBox
This commit is contained in:
@@ -298,6 +298,7 @@
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.0.240109" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.0.240109" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.0.240109" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.TokenizingTextBox" Version="8.0.240109" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.0.240109" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.2" />
|
||||
|
||||
@@ -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 @@
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="SuggestionTemplate">
|
||||
<TextBlock
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding}"/>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding}"/>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="AvatarListTemplate">
|
||||
@@ -272,18 +268,20 @@
|
||||
</CommandBar.Content>
|
||||
<!--<AppBarButton Icon="{shcm:FontIcon Glyph=}" Label="搜索提示"/>-->
|
||||
<AppBarElementContainer>
|
||||
<AutoSuggestBox
|
||||
<cwc:TokenizingTextBox
|
||||
x:Name="AvatarSuggestBox"
|
||||
Width="240"
|
||||
Height="36"
|
||||
Margin="6,6,6,0"
|
||||
Width="520"
|
||||
Margin="6,0,6,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalContentAlignment="Center"
|
||||
ItemTemplate="{StaticResource SuggestionTemplate}"
|
||||
ItemsSource="{Binding FilterTokens, Mode=TwoWay}"
|
||||
MaximumTokens="5"
|
||||
PlaceholderText="{shcm:ResourceString Name=ViewPageWiKiAvatarAutoSuggestBoxPlaceHolder}"
|
||||
QueryIcon="{shcm:FontIcon Glyph=}"
|
||||
Style="{StaticResource DefaultAutoSuggestBoxStyle}"
|
||||
Text="{Binding FilterText, Mode=TwoWay}"/>
|
||||
QueryIcon="{cw:FontIconSource Glyph=}"
|
||||
SuggestedItemTemplate="{StaticResource SuggestionTemplate}"
|
||||
SuggestedItemsSource="{Binding AvailableQueries}"
|
||||
Text="{Binding FilterToken, Mode=TwoWay}"
|
||||
TokenItemTemplate="{StaticResource SuggestionTemplate}"/>
|
||||
</AppBarElementContainer>
|
||||
<AppBarButton
|
||||
Command="{Binding CultivateCommand}"
|
||||
|
||||
@@ -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;
|
||||
using Snap.Hutao.ViewModel.Wiki;
|
||||
@@ -21,16 +22,16 @@ internal sealed partial class WikiAvatarPage : ScopedPage
|
||||
WikiAvatarViewModel viewModel = InitializeWith<WikiAvatarViewModel>();
|
||||
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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,10 +33,7 @@
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="SuggestionTemplate">
|
||||
<TextBlock
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding}"/>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding}"/>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="WeaponListTemplate">
|
||||
@@ -138,17 +135,21 @@
|
||||
LocalSettingKeySuffixForCurrent="WikiWeaponPage.Weapons"/>
|
||||
</CommandBar.Content>
|
||||
<AppBarElementContainer>
|
||||
<AutoSuggestBox
|
||||
<cwc:TokenizingTextBox
|
||||
x:Name="WeaponSuggestBox"
|
||||
Width="240"
|
||||
Height="36"
|
||||
Margin="16,6,6,0"
|
||||
Width="520"
|
||||
Margin="16,0,6,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalContentAlignment="Center"
|
||||
ItemTemplate="{StaticResource SuggestionTemplate}"
|
||||
ItemsSource="{Binding FilterTokens, Mode=TwoWay}"
|
||||
MaximumTokens="5"
|
||||
PlaceholderText="{shcm:ResourceString Name=ViewPageWiKiWeaponAutoSuggestBoxPlaceHolder}"
|
||||
QueryIcon="{shcm:FontIcon Glyph=}"
|
||||
Text="{Binding FilterText, Mode=TwoWay}"/>
|
||||
QueryIcon="{cw:FontIconSource Glyph=}"
|
||||
SuggestedItemTemplate="{StaticResource SuggestionTemplate}"
|
||||
SuggestedItemsSource="{Binding AvailableQueries}"
|
||||
Text="{Binding FilterToken, Mode=TwoWay}"
|
||||
TokenItemTemplate="{StaticResource SuggestionTemplate}"/>
|
||||
</AppBarElementContainer>
|
||||
<AppBarButton
|
||||
Command="{Binding CultivateCommand}"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// 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;
|
||||
using Snap.Hutao.ViewModel.Wiki;
|
||||
|
||||
@@ -21,16 +21,16 @@ internal sealed partial class WikiWeaponPage : ScopedPage
|
||||
WikiWeaponViewModel viewModel = InitializeWith<WikiWeaponViewModel>();
|
||||
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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -5,5 +5,5 @@ namespace Snap.Hutao.ViewModel.Wiki;
|
||||
|
||||
internal interface IWikiViewModelInitialization
|
||||
{
|
||||
void Initialize(IAutoSuggestBoxAccessor accessor);
|
||||
void Initialize(ITokenizingTextBoxAccessor accessor);
|
||||
}
|
||||
|
||||
@@ -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<Avatar>? avatars;
|
||||
private Avatar? selected;
|
||||
private string? filterText;
|
||||
private ObservableCollection<string>? filterTokens;
|
||||
private string? filterToken;
|
||||
private BaseValueInfo? baseValueInfo;
|
||||
private Dictionary<Level, Dictionary<GrowCurveType, float>>? levelAvatarCurveMap;
|
||||
private List<Promote>? promotes;
|
||||
@@ -79,15 +82,20 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki
|
||||
public BaseValueInfo? BaseValueInfo { get => baseValueInfo; set => SetProperty(ref baseValueInfo, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 筛选文本
|
||||
/// 保存的筛选标志
|
||||
/// </summary>
|
||||
public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); }
|
||||
public ObservableCollection<string>? 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<string>? 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<bool> 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<string>(
|
||||
[
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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<Weapon>? weapons;
|
||||
private Weapon? selected;
|
||||
private string? filterText;
|
||||
private List<string>? filterTokens;
|
||||
private string? filterToken;
|
||||
private BaseValueInfo? baseValueInfo;
|
||||
private Dictionary<Level, Dictionary<GrowCurveType, float>>? levelWeaponCurveMap;
|
||||
private List<Promote>? promotes;
|
||||
@@ -76,15 +78,20 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki
|
||||
public BaseValueInfo? BaseValueInfo { get => baseValueInfo; set => SetProperty(ref baseValueInfo, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 筛选文本
|
||||
/// 保存的筛选标志
|
||||
/// </summary>
|
||||
public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); }
|
||||
public List<string>? 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<string> 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;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user