mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
Merge branch 'develop' into feat/unheld_statistics_items
This commit is contained in:
@@ -28,4 +28,21 @@ internal static class FrameworkElementExtension
|
||||
frameworkElement.IsRightTapEnabled = false;
|
||||
frameworkElement.IsTabStop = false;
|
||||
}
|
||||
|
||||
public static void InitializeDataContext<TDataContext>(this FrameworkElement frameworkElement, IServiceProvider? serviceProvider = default)
|
||||
where TDataContext : class
|
||||
{
|
||||
IServiceProvider service = serviceProvider ?? Ioc.Default;
|
||||
try
|
||||
{
|
||||
frameworkElement.DataContext = service.GetRequiredService<TDataContext>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
ILogger? logger = service.GetRequiredService(typeof(ILogger<>).MakeGenericType([frameworkElement.GetType()])) as ILogger;
|
||||
logger?.LogError(ex, "Failed to initialize DataContext");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ internal class ScopedPage : Page
|
||||
{
|
||||
private readonly RoutedEventHandler unloadEventHandler;
|
||||
private readonly CancellationTokenSource viewCancellationTokenSource = new();
|
||||
private readonly IServiceScope currentScope;
|
||||
private readonly IServiceScope pageScope;
|
||||
|
||||
private bool inFrame = true;
|
||||
|
||||
@@ -23,7 +23,7 @@ internal class ScopedPage : Page
|
||||
{
|
||||
unloadEventHandler = OnUnloaded;
|
||||
Unloaded += unloadEventHandler;
|
||||
currentScope = Ioc.Default.GetRequiredService<IScopedPageScopeReferenceTracker>().CreateScope();
|
||||
pageScope = Ioc.Default.GetRequiredService<IScopedPageScopeReferenceTracker>().CreateScope();
|
||||
}
|
||||
|
||||
public async ValueTask NotifyRecipientAsync(INavigationData extra)
|
||||
@@ -44,9 +44,17 @@ internal class ScopedPage : Page
|
||||
protected void InitializeWith<TViewModel>()
|
||||
where TViewModel : class, IViewModel
|
||||
{
|
||||
IViewModel viewModel = currentScope.ServiceProvider.GetRequiredService<TViewModel>();
|
||||
viewModel.CancellationToken = viewCancellationTokenSource.Token;
|
||||
DataContext = viewModel;
|
||||
try
|
||||
{
|
||||
IViewModel viewModel = pageScope.ServiceProvider.GetRequiredService<TViewModel>();
|
||||
viewModel.CancellationToken = viewCancellationTokenSource.Token;
|
||||
DataContext = viewModel;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
pageScope.ServiceProvider.GetRequiredService<ILogger<ScopedPage>>().LogError(ex, "Failed to initialize view model.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -95,7 +103,7 @@ internal class ScopedPage : Page
|
||||
viewModel.IsViewDisposed = true;
|
||||
|
||||
// Dispose the scope
|
||||
currentScope.Dispose();
|
||||
pageScope.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Snap.Hutao.Control.Extension;
|
||||
using Snap.Hutao.Core.Windowing;
|
||||
using Snap.Hutao.ViewModel.Game;
|
||||
using Snap.Hutao.Win32.UI.WindowsAndMessaging;
|
||||
@@ -35,7 +36,7 @@ internal sealed partial class LaunchGameWindow : Window, IDisposable, IWindowOpt
|
||||
scope = serviceProvider.CreateScope();
|
||||
windowOptions = new(this, DragableGrid, new(MaxWidth, MaxHeight));
|
||||
this.InitializeController(serviceProvider);
|
||||
RootGrid.DataContext = scope.ServiceProvider.GetRequiredService<LaunchGameViewModel>();
|
||||
RootGrid.InitializeDataContext<LaunchGameViewModel>(scope.ServiceProvider);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -17,16 +17,15 @@ namespace Snap.Hutao.Service;
|
||||
/// <inheritdoc/>
|
||||
[HighQuality]
|
||||
[ConstructorGenerated]
|
||||
[Injection(InjectAs.Transient, typeof(IAnnouncementService))]
|
||||
[Injection(InjectAs.Scoped, typeof(IAnnouncementService))]
|
||||
internal sealed partial class AnnouncementService : IAnnouncementService
|
||||
{
|
||||
private static readonly string CacheKey = $"{nameof(AnnouncementService)}.Cache.{nameof(AnnouncementWrapper)}";
|
||||
|
||||
private readonly AnnouncementClient announcementClient;
|
||||
private readonly IServiceScopeFactory serviceScopeFactory;
|
||||
private readonly ITaskContext taskContext;
|
||||
private readonly IMemoryCache memoryCache;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask<AnnouncementWrapper> GetAnnouncementWrapperAsync(string languageCode, Region region, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 缓存中存在记录,直接返回
|
||||
@@ -36,29 +35,37 @@ internal sealed partial class AnnouncementService : IAnnouncementService
|
||||
}
|
||||
|
||||
await taskContext.SwitchToBackgroundAsync();
|
||||
Response<AnnouncementWrapper> announcementWrapperResponse = await announcementClient
|
||||
.GetAnnouncementsAsync(languageCode, region, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (!announcementWrapperResponse.IsOk())
|
||||
List<AnnouncementContent>? contents;
|
||||
AnnouncementWrapper wrapper;
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
return default!;
|
||||
AnnouncementClient announcementClient = scope.ServiceProvider.GetRequiredService<AnnouncementClient>();
|
||||
|
||||
Response<AnnouncementWrapper> announcementWrapperResponse = await announcementClient
|
||||
.GetAnnouncementsAsync(languageCode, region, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (!announcementWrapperResponse.IsOk())
|
||||
{
|
||||
return default!;
|
||||
}
|
||||
|
||||
wrapper = announcementWrapperResponse.Data;
|
||||
|
||||
Response<ListWrapper<AnnouncementContent>> announcementContentResponse = await announcementClient
|
||||
.GetAnnouncementContentsAsync(languageCode, region, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (!announcementContentResponse.IsOk())
|
||||
{
|
||||
return default!;
|
||||
}
|
||||
|
||||
contents = announcementContentResponse.Data.List;
|
||||
}
|
||||
|
||||
AnnouncementWrapper wrapper = announcementWrapperResponse.Data;
|
||||
Response<ListWrapper<AnnouncementContent>> announcementContentResponse = await announcementClient
|
||||
.GetAnnouncementContentsAsync(languageCode, region, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (!announcementContentResponse.IsOk())
|
||||
{
|
||||
return default!;
|
||||
}
|
||||
|
||||
List<AnnouncementContent> contents = announcementContentResponse.Data.List;
|
||||
|
||||
Dictionary<int, string> contentMap = contents
|
||||
.ToDictionary(id => id.AnnId, content => content.Content);
|
||||
Dictionary<int, string> contentMap = contents.ToDictionary(id => id.AnnId, content => content.Content);
|
||||
|
||||
// 将活动公告置于前方
|
||||
wrapper.List.Reverse();
|
||||
@@ -75,8 +82,7 @@ internal sealed partial class AnnouncementService : IAnnouncementService
|
||||
{
|
||||
foreach (ref readonly WebAnnouncement item in CollectionsMarshal.AsSpan(listWrapper.List))
|
||||
{
|
||||
contentMap.TryGetValue(item.AnnId, out string? rawContent);
|
||||
item.Content = rawContent ?? string.Empty;
|
||||
item.Content = contentMap.GetValueOrDefault(item.AnnId, string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,17 +5,8 @@ using Snap.Hutao.ViewModel.AvatarProperty;
|
||||
|
||||
namespace Snap.Hutao.Service.AvatarInfo.Factory;
|
||||
|
||||
/// <summary>
|
||||
/// 简述工厂
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal interface ISummaryFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// 异步创建简述对象
|
||||
/// </summary>
|
||||
/// <param name="avatarInfos">角色列表</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>简述对象</returns>
|
||||
ValueTask<Summary> CreateAsync(IEnumerable<Model.Entity.AvatarInfo> avatarInfos, CancellationToken token);
|
||||
}
|
||||
@@ -17,9 +17,6 @@ using PropertyWeapon = Snap.Hutao.ViewModel.AvatarProperty.WeaponView;
|
||||
|
||||
namespace Snap.Hutao.Service.AvatarInfo.Factory;
|
||||
|
||||
/// <summary>
|
||||
/// 单个角色工厂
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class SummaryAvatarFactory
|
||||
{
|
||||
@@ -27,14 +24,9 @@ internal sealed class SummaryAvatarFactory
|
||||
private readonly DateTimeOffset showcaseRefreshTime;
|
||||
private readonly DateTimeOffset gameRecordRefreshTime;
|
||||
private readonly DateTimeOffset calculatorRefreshTime;
|
||||
private readonly SummaryMetadataContext metadataContext;
|
||||
private readonly SummaryFactoryMetadataContext metadataContext;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的角色工厂
|
||||
/// </summary>
|
||||
/// <param name="metadataContext">元数据上下文</param>
|
||||
/// <param name="avatarInfo">角色信息</param>
|
||||
public SummaryAvatarFactory(SummaryMetadataContext metadataContext, EntityAvatarInfo avatarInfo)
|
||||
public SummaryAvatarFactory(SummaryFactoryMetadataContext metadataContext, EntityAvatarInfo avatarInfo)
|
||||
{
|
||||
this.metadataContext = metadataContext;
|
||||
this.avatarInfo = avatarInfo.Info;
|
||||
|
||||
@@ -20,12 +20,12 @@ internal sealed partial class SummaryFactory : ISummaryFactory
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask<Summary> CreateAsync(IEnumerable<Model.Entity.AvatarInfo> avatarInfos, CancellationToken token)
|
||||
{
|
||||
SummaryMetadataContext metadataContext = new()
|
||||
SummaryFactoryMetadataContext metadataContext = new()
|
||||
{
|
||||
IdAvatarMap = await metadataService.GetIdToAvatarMapAsync(token).ConfigureAwait(false),
|
||||
IdWeaponMap = await metadataService.GetIdToWeaponMapAsync(token).ConfigureAwait(false),
|
||||
IdReliquaryAffixWeightMap = await metadataService.GetIdToReliquaryAffixWeightMapAsync(token).ConfigureAwait(false),
|
||||
IdReliquaryMainAffixMap = await metadataService.GetIdToReliquaryMainPropertyMapAsync(token).ConfigureAwait(false),
|
||||
IdReliquaryMainPropertyMap = await metadataService.GetIdToReliquaryMainPropertyMapAsync(token).ConfigureAwait(false),
|
||||
IdReliquarySubAffixMap = await metadataService.GetIdToReliquarySubAffixMapAsync(token).ConfigureAwait(false),
|
||||
ReliquaryLevels = await metadataService.GetReliquaryLevelListAsync(token).ConfigureAwait(false),
|
||||
Reliquaries = await metadataService.GetReliquaryListAsync(token).ConfigureAwait(false),
|
||||
|
||||
@@ -4,51 +4,32 @@
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Metadata.Reliquary;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
using Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
using MetadataAvatar = Snap.Hutao.Model.Metadata.Avatar.Avatar;
|
||||
using MetadataReliquary = Snap.Hutao.Model.Metadata.Reliquary.Reliquary;
|
||||
using MetadataWeapon = Snap.Hutao.Model.Metadata.Weapon.Weapon;
|
||||
|
||||
namespace Snap.Hutao.Service.AvatarInfo.Factory;
|
||||
|
||||
/// <summary>
|
||||
/// 简述元数据上下文
|
||||
/// 包含了所有制造简述需要的元数据
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class SummaryMetadataContext
|
||||
internal sealed class SummaryFactoryMetadataContext : IMetadataContext,
|
||||
IMetadataDictionaryIdAvatarSource,
|
||||
IMetadataDictionaryIdWeaponSource,
|
||||
IMetadataDictionaryIdReliquaryAffixWeightSource,
|
||||
IMetadataDictionaryIdReliquaryMainPropertySource,
|
||||
IMetadataDictionaryIdReliquarySubAffixSource
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色映射
|
||||
/// </summary>
|
||||
public Dictionary<AvatarId, MetadataAvatar> IdAvatarMap { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 武器映射
|
||||
/// </summary>
|
||||
public Dictionary<WeaponId, MetadataWeapon> IdWeaponMap { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 权重映射
|
||||
/// </summary>
|
||||
public Dictionary<AvatarId, ReliquaryAffixWeight> IdReliquaryAffixWeightMap { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 圣遗物主属性映射
|
||||
/// </summary>
|
||||
public Dictionary<ReliquaryMainAffixId, FightProperty> IdReliquaryMainAffixMap { get; set; } = default!;
|
||||
public Dictionary<ReliquaryMainAffixId, FightProperty> IdReliquaryMainPropertyMap { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 圣遗物副属性映射
|
||||
/// </summary>
|
||||
public Dictionary<ReliquarySubAffixId, ReliquarySubAffix> IdReliquarySubAffixMap { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 圣遗物等级
|
||||
/// </summary>
|
||||
public List<ReliquaryMainAffixLevel> ReliquaryLevels { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 圣遗物
|
||||
/// </summary>
|
||||
public List<MetadataReliquary> Reliquaries { get; set; } = default!;
|
||||
}
|
||||
@@ -19,7 +19,7 @@ namespace Snap.Hutao.Service.AvatarInfo.Factory;
|
||||
[HighQuality]
|
||||
internal sealed class SummaryReliquaryFactory
|
||||
{
|
||||
private readonly SummaryMetadataContext metadataContext;
|
||||
private readonly SummaryFactoryMetadataContext metadataContext;
|
||||
private readonly ModelAvatarInfo avatarInfo;
|
||||
private readonly Web.Enka.Model.Equip equip;
|
||||
|
||||
@@ -29,7 +29,7 @@ internal sealed class SummaryReliquaryFactory
|
||||
/// <param name="metadataContext">元数据上下文</param>
|
||||
/// <param name="avatarInfo">角色信息</param>
|
||||
/// <param name="equip">圣遗物</param>
|
||||
public SummaryReliquaryFactory(SummaryMetadataContext metadataContext, ModelAvatarInfo avatarInfo, Web.Enka.Model.Equip equip)
|
||||
public SummaryReliquaryFactory(SummaryFactoryMetadataContext metadataContext, ModelAvatarInfo avatarInfo, Web.Enka.Model.Equip equip)
|
||||
{
|
||||
this.metadataContext = metadataContext;
|
||||
this.avatarInfo = avatarInfo;
|
||||
@@ -70,7 +70,7 @@ internal sealed class SummaryReliquaryFactory
|
||||
result.ComposedSubProperties = CreateComposedSubProperties(equip.Reliquary.AppendPropIdList);
|
||||
|
||||
ReliquaryMainAffixLevel relicLevel = metadataContext.ReliquaryLevels.Single(r => r.Level == equip.Reliquary.Level && r.Rank == reliquary.RankLevel);
|
||||
FightProperty property = metadataContext.IdReliquaryMainAffixMap[equip.Reliquary.MainPropId];
|
||||
FightProperty property = metadataContext.IdReliquaryMainPropertyMap[equip.Reliquary.MainPropId];
|
||||
|
||||
result.MainProperty = FightPropertyFormat.ToNameValue(property, relicLevel.PropertyMap[property]);
|
||||
result.Score = ScoreReliquary(property, reliquary, relicLevel, subProperty);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Metadata.Reliquary;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
|
||||
namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataDictionaryIdReliquaryAffixWeightSource
|
||||
{
|
||||
public Dictionary<AvatarId, ReliquaryAffixWeight> IdReliquaryAffixWeightMap { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
|
||||
namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataDictionaryIdReliquaryMainPropertySource
|
||||
{
|
||||
public Dictionary<ReliquaryMainAffixId, FightProperty> IdReliquaryMainPropertyMap { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Metadata.Reliquary;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
|
||||
namespace Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
|
||||
internal interface IMetadataDictionaryIdReliquarySubAffixSource
|
||||
{
|
||||
public Dictionary<ReliquarySubAffixId, ReliquarySubAffix> IdReliquarySubAffixMap { get; set; }
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||
using Snap.Hutao.Model.Metadata.Avatar;
|
||||
using Snap.Hutao.Model.Metadata.Item;
|
||||
using Snap.Hutao.Model.Metadata.Weapon;
|
||||
@@ -51,6 +52,21 @@ internal static class MetadataServiceContextExtension
|
||||
dictionaryIdMaterialSource.IdMaterialMap = await metadataService.GetIdToMaterialMapAsync(token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (context is IMetadataDictionaryIdReliquaryAffixWeightSource dictionaryIdReliquaryAffixWeightSource)
|
||||
{
|
||||
dictionaryIdReliquaryAffixWeightSource.IdReliquaryAffixWeightMap = await metadataService.GetIdToReliquaryAffixWeightMapAsync(token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (context is IMetadataDictionaryIdReliquaryMainPropertySource dictionaryIdReliquaryMainPropertySource)
|
||||
{
|
||||
dictionaryIdReliquaryMainPropertySource.IdReliquaryMainPropertyMap = await metadataService.GetIdToReliquaryMainPropertyMapAsync(token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (context is IMetadataDictionaryIdReliquarySubAffixSource dictionaryIdReliquarySubAffixSource)
|
||||
{
|
||||
dictionaryIdReliquarySubAffixSource.IdReliquarySubAffixMap = await metadataService.GetIdToReliquarySubAffixMapAsync(token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (context is IMetadataDictionaryIdWeaponSource dictionaryIdWeaponSource)
|
||||
{
|
||||
dictionaryIdWeaponSource.IdWeaponMap = await metadataService.GetIdToWeaponMapAsync(token).ConfigureAwait(false);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Snap.Hutao.Control.Extension;
|
||||
|
||||
namespace Snap.Hutao.View.Card;
|
||||
|
||||
@@ -15,7 +16,7 @@ internal sealed partial class AchievementCard : Button
|
||||
/// </summary>
|
||||
public AchievementCard()
|
||||
{
|
||||
DataContext = Ioc.Default.GetRequiredService<ViewModel.Achievement.AchievementViewModelSlim>();
|
||||
this.InitializeDataContext<ViewModel.Achievement.AchievementViewModelSlim>();
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Snap.Hutao.Control.Extension;
|
||||
|
||||
namespace Snap.Hutao.View.Card;
|
||||
|
||||
@@ -15,7 +16,7 @@ internal sealed partial class DailyNoteCard : Button
|
||||
/// </summary>
|
||||
public DailyNoteCard()
|
||||
{
|
||||
DataContext = Ioc.Default.GetRequiredService<ViewModel.DailyNote.DailyNoteViewModelSlim>();
|
||||
this.InitializeDataContext<ViewModel.DailyNote.DailyNoteViewModelSlim>();
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Snap.Hutao.Control.Extension;
|
||||
|
||||
namespace Snap.Hutao.View.Card;
|
||||
|
||||
@@ -15,7 +16,7 @@ internal sealed partial class GachaStatisticsCard : Button
|
||||
/// </summary>
|
||||
public GachaStatisticsCard()
|
||||
{
|
||||
DataContext = Ioc.Default.GetRequiredService<ViewModel.GachaLog.GachaLogViewModelSlim>();
|
||||
this.InitializeDataContext<ViewModel.GachaLog.GachaLogViewModelSlim>();
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Snap.Hutao.Control.Extension;
|
||||
|
||||
namespace Snap.Hutao.View.Card;
|
||||
|
||||
@@ -15,7 +16,7 @@ internal sealed partial class LaunchGameCard : Button
|
||||
/// </summary>
|
||||
public LaunchGameCard()
|
||||
{
|
||||
DataContext = Ioc.Default.GetRequiredService<ViewModel.Game.LaunchGameViewModelSlim>();
|
||||
this.InitializeDataContext<ViewModel.Game.LaunchGameViewModelSlim>();
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ internal sealed partial class GuideView : UserControl
|
||||
{
|
||||
public GuideView()
|
||||
{
|
||||
this.InitializeDataContext<GuideViewModel>();
|
||||
InitializeComponent();
|
||||
DataContext = this.ServiceProvider().GetRequiredService<GuideViewModel>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Snap.Hutao.Control.Extension;
|
||||
using Snap.Hutao.Service.Navigation;
|
||||
using Snap.Hutao.View.Page;
|
||||
using Snap.Hutao.ViewModel;
|
||||
@@ -23,12 +24,11 @@ internal sealed partial class MainView : UserControl
|
||||
{
|
||||
IServiceProvider serviceProvider = Ioc.Default;
|
||||
|
||||
MainViewModel mainViewModel = serviceProvider.GetRequiredService<MainViewModel>();
|
||||
this.InitializeDataContext<MainViewModel>(serviceProvider);
|
||||
|
||||
DataContext = mainViewModel;
|
||||
InitializeComponent();
|
||||
|
||||
mainViewModel.Initialize(new BackgroundImagePresenterAccessor(BackgroundImagePresenter));
|
||||
(DataContext as MainViewModel)?.Initialize(new BackgroundImagePresenterAccessor(BackgroundImagePresenter));
|
||||
|
||||
navigationService = serviceProvider.GetRequiredService<INavigationService>();
|
||||
if (navigationService is INavigationInitialization navigationInitialization)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Snap.Hutao.Control.Extension;
|
||||
using Snap.Hutao.ViewModel;
|
||||
|
||||
namespace Snap.Hutao.View;
|
||||
@@ -15,7 +16,7 @@ internal sealed partial class TitleView : UserControl
|
||||
{
|
||||
public TitleView()
|
||||
{
|
||||
DataContext = Ioc.Default.GetRequiredService<TitleViewModel>();
|
||||
this.InitializeDataContext<TitleViewModel>();
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Snap.Hutao.Control.Extension;
|
||||
using Snap.Hutao.ViewModel.User;
|
||||
|
||||
namespace Snap.Hutao.View;
|
||||
@@ -17,7 +18,7 @@ internal sealed partial class UserView : UserControl
|
||||
/// </summary>
|
||||
public UserView()
|
||||
{
|
||||
this.InitializeDataContext<UserViewModel>();
|
||||
InitializeComponent();
|
||||
DataContext = Ioc.Default.GetRequiredService<UserViewModel>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.ViewModel.Abstraction;
|
||||
|
||||
internal interface IPageScoped;
|
||||
@@ -7,7 +7,7 @@ namespace Snap.Hutao.ViewModel.Abstraction;
|
||||
/// 视图模型接口
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal interface IViewModel
|
||||
internal interface IViewModel : IPageScoped
|
||||
{
|
||||
/// <summary>
|
||||
/// 用于通知页面卸载的取消令牌
|
||||
|
||||
@@ -7,29 +7,16 @@ using Snap.Hutao.Service.Navigation;
|
||||
|
||||
namespace Snap.Hutao.ViewModel.Abstraction;
|
||||
|
||||
/// <summary>
|
||||
/// 简化的视图模型抽象类
|
||||
/// </summary>
|
||||
[ConstructorGenerated]
|
||||
internal abstract partial class ViewModelSlim : ObservableObject
|
||||
{
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private bool isInitialized;
|
||||
|
||||
/// <summary>
|
||||
/// 是否初始化完成
|
||||
/// </summary>
|
||||
public bool IsInitialized { get => isInitialized; set => SetProperty(ref isInitialized, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 服务提供器
|
||||
/// </summary>
|
||||
protected IServiceProvider ServiceProvider { get => serviceProvider; }
|
||||
|
||||
/// <summary>
|
||||
/// 打开界面执行
|
||||
/// </summary>
|
||||
/// <returns>任务</returns>
|
||||
[Command("OpenUICommand")]
|
||||
protected virtual Task OpenUIAsync()
|
||||
{
|
||||
@@ -37,18 +24,10 @@ internal abstract partial class ViewModelSlim : ObservableObject
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 简化的视图模型抽象类
|
||||
/// 可导航
|
||||
/// </summary>
|
||||
/// <typeparam name="TPage">要导航到的页面类型</typeparam>
|
||||
[ConstructorGenerated(CallBaseConstructor = true)]
|
||||
internal abstract partial class ViewModelSlim<TPage> : ViewModelSlim
|
||||
where TPage : Page
|
||||
{
|
||||
/// <summary>
|
||||
/// 导航到指定的页面类型
|
||||
/// </summary>
|
||||
[Command("NavigateCommand")]
|
||||
protected virtual void Navigate()
|
||||
{
|
||||
|
||||
@@ -7,16 +7,9 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace Snap.Hutao.ViewModel.Achievement;
|
||||
|
||||
/// <summary>
|
||||
/// 成就完成进度
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal static class AchievementFinishPercent
|
||||
{
|
||||
/// <summary>
|
||||
/// 更新完成进度
|
||||
/// </summary>
|
||||
/// <param name="viewModel">视图模型</param>
|
||||
public static void Update(AchievementViewModel viewModel)
|
||||
{
|
||||
int totalFinished = 0;
|
||||
|
||||
Reference in New Issue
Block a user