InitializeDataContext

This commit is contained in:
Lightczx
2024-04-17 15:05:26 +08:00
parent 45dd276b89
commit c6618be0fc
12 changed files with 76 additions and 38 deletions

View File

@@ -28,4 +28,21 @@ internal static class FrameworkElementExtension
frameworkElement.IsRightTapEnabled = false; frameworkElement.IsRightTapEnabled = false;
frameworkElement.IsTabStop = 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;
}
}
} }

View File

@@ -44,9 +44,17 @@ internal class ScopedPage : Page
protected void InitializeWith<TViewModel>() protected void InitializeWith<TViewModel>()
where TViewModel : class, IViewModel where TViewModel : class, IViewModel
{ {
IViewModel viewModel = currentScope.ServiceProvider.GetRequiredService<TViewModel>(); try
viewModel.CancellationToken = viewCancellationTokenSource.Token; {
DataContext = viewModel; IViewModel viewModel = currentScope.ServiceProvider.GetRequiredService<TViewModel>();
viewModel.CancellationToken = viewCancellationTokenSource.Token;
DataContext = viewModel;
}
catch (Exception ex)
{
currentScope.ServiceProvider.GetRequiredService<ILogger<ScopedPage>>().LogError(ex, "Failed to initialize view model.");
throw;
}
} }
/// <inheritdoc/> /// <inheritdoc/>

View File

@@ -2,6 +2,7 @@
// Licensed under the MIT license. // Licensed under the MIT license.
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Snap.Hutao.Control.Extension;
using Snap.Hutao.Core.Windowing; using Snap.Hutao.Core.Windowing;
using Snap.Hutao.ViewModel.Game; using Snap.Hutao.ViewModel.Game;
using Snap.Hutao.Win32.UI.WindowsAndMessaging; using Snap.Hutao.Win32.UI.WindowsAndMessaging;
@@ -35,7 +36,7 @@ internal sealed partial class LaunchGameWindow : Window, IDisposable, IWindowOpt
scope = serviceProvider.CreateScope(); scope = serviceProvider.CreateScope();
windowOptions = new(this, DragableGrid, new(MaxWidth, MaxHeight)); windowOptions = new(this, DragableGrid, new(MaxWidth, MaxHeight));
this.InitializeController(serviceProvider); this.InitializeController(serviceProvider);
RootGrid.DataContext = scope.ServiceProvider.GetRequiredService<LaunchGameViewModel>(); RootGrid.InitializeDataContext<LaunchGameViewModel>(scope.ServiceProvider);
} }
/// <inheritdoc/> /// <inheritdoc/>

View File

@@ -17,16 +17,15 @@ namespace Snap.Hutao.Service;
/// <inheritdoc/> /// <inheritdoc/>
[HighQuality] [HighQuality]
[ConstructorGenerated] [ConstructorGenerated]
[Injection(InjectAs.Transient, typeof(IAnnouncementService))] [Injection(InjectAs.Scoped, typeof(IAnnouncementService))]
internal sealed partial class AnnouncementService : IAnnouncementService internal sealed partial class AnnouncementService : IAnnouncementService
{ {
private static readonly string CacheKey = $"{nameof(AnnouncementService)}.Cache.{nameof(AnnouncementWrapper)}"; private static readonly string CacheKey = $"{nameof(AnnouncementService)}.Cache.{nameof(AnnouncementWrapper)}";
private readonly AnnouncementClient announcementClient; private readonly IServiceScopeFactory serviceScopeFactory;
private readonly ITaskContext taskContext; private readonly ITaskContext taskContext;
private readonly IMemoryCache memoryCache; private readonly IMemoryCache memoryCache;
/// <inheritdoc/>
public async ValueTask<AnnouncementWrapper> GetAnnouncementWrapperAsync(string languageCode, Region region, CancellationToken cancellationToken = default) 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(); 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; Dictionary<int, string> contentMap = contents.ToDictionary(id => id.AnnId, content => content.Content);
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);
// 将活动公告置于前方 // 将活动公告置于前方
wrapper.List.Reverse(); wrapper.List.Reverse();
@@ -75,8 +82,7 @@ internal sealed partial class AnnouncementService : IAnnouncementService
{ {
foreach (ref readonly WebAnnouncement item in CollectionsMarshal.AsSpan(listWrapper.List)) foreach (ref readonly WebAnnouncement item in CollectionsMarshal.AsSpan(listWrapper.List))
{ {
contentMap.TryGetValue(item.AnnId, out string? rawContent); item.Content = contentMap.GetValueOrDefault(item.AnnId, string.Empty);
item.Content = rawContent ?? string.Empty;
} }
} }

View File

@@ -2,6 +2,7 @@
// Licensed under the MIT license. // Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Control.Extension;
namespace Snap.Hutao.View.Card; namespace Snap.Hutao.View.Card;
@@ -15,7 +16,7 @@ internal sealed partial class AchievementCard : Button
/// </summary> /// </summary>
public AchievementCard() public AchievementCard()
{ {
DataContext = Ioc.Default.GetRequiredService<ViewModel.Achievement.AchievementViewModelSlim>(); this.InitializeDataContext<ViewModel.Achievement.AchievementViewModelSlim>();
InitializeComponent(); InitializeComponent();
} }
} }

View File

@@ -2,6 +2,7 @@
// Licensed under the MIT license. // Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Control.Extension;
namespace Snap.Hutao.View.Card; namespace Snap.Hutao.View.Card;
@@ -15,7 +16,7 @@ internal sealed partial class DailyNoteCard : Button
/// </summary> /// </summary>
public DailyNoteCard() public DailyNoteCard()
{ {
DataContext = Ioc.Default.GetRequiredService<ViewModel.DailyNote.DailyNoteViewModelSlim>(); this.InitializeDataContext<ViewModel.DailyNote.DailyNoteViewModelSlim>();
InitializeComponent(); InitializeComponent();
} }
} }

View File

@@ -2,6 +2,7 @@
// Licensed under the MIT license. // Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Control.Extension;
namespace Snap.Hutao.View.Card; namespace Snap.Hutao.View.Card;
@@ -15,7 +16,7 @@ internal sealed partial class GachaStatisticsCard : Button
/// </summary> /// </summary>
public GachaStatisticsCard() public GachaStatisticsCard()
{ {
DataContext = Ioc.Default.GetRequiredService<ViewModel.GachaLog.GachaLogViewModelSlim>(); this.InitializeDataContext<ViewModel.GachaLog.GachaLogViewModelSlim>();
InitializeComponent(); InitializeComponent();
} }
} }

View File

@@ -2,6 +2,7 @@
// Licensed under the MIT license. // Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Control.Extension;
namespace Snap.Hutao.View.Card; namespace Snap.Hutao.View.Card;
@@ -15,7 +16,7 @@ internal sealed partial class LaunchGameCard : Button
/// </summary> /// </summary>
public LaunchGameCard() public LaunchGameCard()
{ {
DataContext = Ioc.Default.GetRequiredService<ViewModel.Game.LaunchGameViewModelSlim>(); this.InitializeDataContext<ViewModel.Game.LaunchGameViewModelSlim>();
InitializeComponent(); InitializeComponent();
} }
} }

View File

@@ -14,7 +14,7 @@ internal sealed partial class GuideView : UserControl
{ {
public GuideView() public GuideView()
{ {
this.InitializeDataContext<GuideViewModel>();
InitializeComponent(); InitializeComponent();
DataContext = this.ServiceProvider().GetRequiredService<GuideViewModel>();
} }
} }

View File

@@ -2,6 +2,7 @@
// Licensed under the MIT license. // Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Control.Extension;
using Snap.Hutao.Service.Navigation; using Snap.Hutao.Service.Navigation;
using Snap.Hutao.View.Page; using Snap.Hutao.View.Page;
using Snap.Hutao.ViewModel; using Snap.Hutao.ViewModel;
@@ -23,12 +24,11 @@ internal sealed partial class MainView : UserControl
{ {
IServiceProvider serviceProvider = Ioc.Default; IServiceProvider serviceProvider = Ioc.Default;
MainViewModel mainViewModel = serviceProvider.GetRequiredService<MainViewModel>(); this.InitializeDataContext<MainViewModel>(serviceProvider);
DataContext = mainViewModel;
InitializeComponent(); InitializeComponent();
mainViewModel.Initialize(new BackgroundImagePresenterAccessor(BackgroundImagePresenter)); (DataContext as MainViewModel)?.Initialize(new BackgroundImagePresenterAccessor(BackgroundImagePresenter));
navigationService = serviceProvider.GetRequiredService<INavigationService>(); navigationService = serviceProvider.GetRequiredService<INavigationService>();
if (navigationService is INavigationInitialization navigationInitialization) if (navigationService is INavigationInitialization navigationInitialization)

View File

@@ -3,6 +3,7 @@
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Control.Extension;
using Snap.Hutao.ViewModel; using Snap.Hutao.ViewModel;
namespace Snap.Hutao.View; namespace Snap.Hutao.View;
@@ -15,7 +16,7 @@ internal sealed partial class TitleView : UserControl
{ {
public TitleView() public TitleView()
{ {
DataContext = Ioc.Default.GetRequiredService<TitleViewModel>(); this.InitializeDataContext<TitleViewModel>();
InitializeComponent(); InitializeComponent();
} }

View File

@@ -2,6 +2,7 @@
// Licensed under the MIT license. // Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Control.Extension;
using Snap.Hutao.ViewModel.User; using Snap.Hutao.ViewModel.User;
namespace Snap.Hutao.View; namespace Snap.Hutao.View;
@@ -17,7 +18,7 @@ internal sealed partial class UserView : UserControl
/// </summary> /// </summary>
public UserView() public UserView()
{ {
this.InitializeDataContext<UserViewModel>();
InitializeComponent(); InitializeComponent();
DataContext = Ioc.Default.GetRequiredService<UserViewModel>();
} }
} }