mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
defer content load
This commit is contained in:
@@ -1,44 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.WinUI.Behaviors;
|
||||
using Microsoft.UI.Xaml;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Snap.Hutao.Control.Behavior;
|
||||
|
||||
[DependencyProperty("ElementNames", typeof(DeferLoadCollection))]
|
||||
internal sealed partial class DeferLoadBehavior : BehaviorBase<FrameworkElement>
|
||||
{
|
||||
protected override bool Initialize()
|
||||
{
|
||||
if (ElementNames.IsNullOrEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
ThreadPool.UnsafeQueueUserWorkItem(LoadElements, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void LoadElements(object? state)
|
||||
{
|
||||
if (state is not DeferLoadBehavior behavior)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<string>? elementNames = null;
|
||||
behavior.AssociatedObject.DispatcherQueue.Invoke(() => elementNames = [.. behavior.ElementNames]);
|
||||
|
||||
foreach (string name in CollectionsMarshal.AsSpan(elementNames))
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
|
||||
behavior.AssociatedObject.DispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
behavior.AssociatedObject.FindName(name);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Windows.Foundation.Metadata;
|
||||
|
||||
namespace Snap.Hutao.Control.Behavior;
|
||||
|
||||
[CreateFromString(MethodName = "Snap.Hutao.Control.Behavior.DeferLoadCollection.Parse")]
|
||||
internal sealed class DeferLoadCollection : List<string>
|
||||
{
|
||||
public static DeferLoadCollection Parse(string text)
|
||||
{
|
||||
DeferLoadCollection collection = [];
|
||||
foreach (StringSegment segment in new StringTokenizer(text, [',']))
|
||||
{
|
||||
if (segment.HasValue)
|
||||
{
|
||||
collection.Add(segment.Value);
|
||||
}
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using Snap.Hutao.Service.Navigation;
|
||||
using Snap.Hutao.View.Helper;
|
||||
using Snap.Hutao.ViewModel.Abstraction;
|
||||
|
||||
namespace Snap.Hutao.Control;
|
||||
@@ -48,6 +49,7 @@ internal class ScopedPage : Page
|
||||
{
|
||||
IViewModel viewModel = pageScope.ServiceProvider.GetRequiredService<TViewModel>();
|
||||
viewModel.CancellationToken = viewCancellationTokenSource.Token;
|
||||
viewModel.DeferContentLoader = new DeferContentLoader(this);
|
||||
DataContext = viewModel;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
24
src/Snap.Hutao/Snap.Hutao/View/Helper/DeferContentLoader.cs
Normal file
24
src/Snap.Hutao/Snap.Hutao/View/Helper/DeferContentLoader.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
|
||||
namespace Snap.Hutao.View.Helper;
|
||||
|
||||
internal sealed class DeferContentLoader : IDeferContentLoader
|
||||
{
|
||||
private readonly WeakReference<FrameworkElement> reference = new(default!);
|
||||
|
||||
public DeferContentLoader(FrameworkElement element)
|
||||
{
|
||||
this.reference.SetTarget(element);
|
||||
}
|
||||
|
||||
public void Load(string name)
|
||||
{
|
||||
if (reference.TryGetTarget(out FrameworkElement? element))
|
||||
{
|
||||
element.FindName(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.View.Helper;
|
||||
|
||||
internal interface IDeferContentLoader
|
||||
{
|
||||
void Load(string name);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Windows.Foundation.Metadata;
|
||||
|
||||
namespace Snap.Hutao.View.Helper;
|
||||
|
||||
internal sealed class LoadDeferral : ObservableObject
|
||||
{
|
||||
private bool canLoad;
|
||||
|
||||
public bool CanLoad { get => canLoad; set => SetProperty(ref canLoad, value); }
|
||||
}
|
||||
@@ -23,7 +23,6 @@
|
||||
mc:Ignorable="d">
|
||||
<mxi:Interaction.Behaviors>
|
||||
<shcb:InvokeCommandOnLoadedBehavior Command="{Binding OpenUICommand}"/>
|
||||
<shcb:DeferLoadBehavior ElementNames="TopPanel,GameAnnouncementPivot"/>
|
||||
</mxi:Interaction.Behaviors>
|
||||
<shc:ScopedPage.Resources>
|
||||
<shc:BindingProxy x:Key="BindingProxy" DataContext="{Binding}"/>
|
||||
@@ -218,9 +217,12 @@
|
||||
</Border>
|
||||
|
||||
<ItemsControl
|
||||
x:Name="HutaoAnnouncementControl"
|
||||
x:Load="False"
|
||||
ItemTemplate="{StaticResource HutaoAnnouncementTemplate}"
|
||||
ItemsPanel="{ThemeResource StackPanelSpacing8Template}"
|
||||
ItemsSource="{Binding HutaoAnnouncements}"
|
||||
Transitions="{ThemeResource EntranceThemeTransitions}"
|
||||
Visibility="{Binding HutaoAnnouncements.Count, Converter={StaticResource Int32ToVisibilityConverter}}"/>
|
||||
|
||||
<!-- ItemsRepeater will behave abnormal if no direct scrollhost wrapping it -->
|
||||
|
||||
@@ -20,4 +20,4 @@ internal sealed partial class AnnouncementPage : ScopedPage
|
||||
InitializeWith<AnnouncementViewModel>();
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,18 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.View.Helper;
|
||||
|
||||
namespace Snap.Hutao.ViewModel.Abstraction;
|
||||
|
||||
/// <summary>
|
||||
/// 视图模型接口
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal interface IViewModel : IPageScoped
|
||||
{
|
||||
/// <summary>
|
||||
/// 用于通知页面卸载的取消令牌
|
||||
/// </summary>
|
||||
CancellationToken CancellationToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 释放操作锁
|
||||
/// </summary>
|
||||
SemaphoreSlim DisposeLock { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 对应的视图是否已经释放
|
||||
/// </summary>
|
||||
IDeferContentLoader DeferContentLoader { get; set; }
|
||||
|
||||
bool IsViewDisposed { get; set; }
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Snap.Hutao.Core.ExceptionService;
|
||||
using Snap.Hutao.View.Helper;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Snap.Hutao.ViewModel.Abstraction;
|
||||
@@ -22,6 +23,8 @@ internal abstract partial class ViewModel : ObservableObject, IViewModel
|
||||
|
||||
public SemaphoreSlim DisposeLock { get; set; } = new(1);
|
||||
|
||||
public IDeferContentLoader DeferContentLoader { get; set; } = default!;
|
||||
|
||||
public bool IsViewDisposed { get; set; }
|
||||
|
||||
protected TaskCompletionSource<bool> Initialization { get; } = new();
|
||||
|
||||
@@ -67,6 +67,7 @@ internal sealed partial class AnnouncementViewModel : Abstraction.ViewModel
|
||||
AnnouncementWrapper announcementWrapper = await announcementService.GetAnnouncementWrapperAsync(cultureOptions.LanguageCode, appOptions.Region, CancellationToken).ConfigureAwait(false);
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
Announcement = announcementWrapper;
|
||||
DeferContentLoader.Load("GameAnnouncementPivot");
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
@@ -80,6 +81,7 @@ internal sealed partial class AnnouncementViewModel : Abstraction.ViewModel
|
||||
ObservableCollection<Web.Hutao.HutaoAsAService.Announcement> hutaoAnnouncements = await hutaoAsAService.GetHutaoAnnouncementCollectionAsync().ConfigureAwait(false);
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
HutaoAnnouncements = hutaoAnnouncements;
|
||||
DeferContentLoader.Load("HutaoAnnouncementControl");
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
@@ -141,4 +143,4 @@ internal sealed partial class AnnouncementViewModel : Abstraction.ViewModel
|
||||
|
||||
Cards = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user