You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinUI3中SelectorBar切换时复用子页面的DI实现方案

解决方案:WinUI3中实现子页面与父页面同生命周期的复用

方案1:手动缓存子页面实例(最简单直接)

无需修改现有DI注册,直接在OverviewPage内部维护子页面实例,切换视图时复用已创建对象:

  1. 在OverviewPage中声明私有字段用于缓存实例:
private Page1? _page1;
private Page2? _page2;
  1. 在SelectorBar的SelectionChanged事件中,判断实例是否已创建,未创建则通过DI获取,否则直接复用:
private void SelectorBar_SelectionChanged(SelectorBar sender, SelectorBarSelectionChangedEventArgs args)
{
    var selectedItem = args.SelectedItem as SelectorBarItem;
    if (selectedItem?.Tag.ToString() == "Page1")
    {
        _page1 ??= App.Current.Services.GetService<Page1>();
        ContentFrame.Content = _page1;
    }
    else if (selectedItem?.Tag.ToString() == "Page2")
    {
        _page2 ??= App.Current.Services.GetService<Page2>();
        ContentFrame.Content = _page2;
    }
}

注:直接赋值ContentFrame.Content而非调用Navigate,避免Frame导航栈创建新实例;若需保留导航栈逻辑,可自定义判断逻辑跳过实例重建。

  1. 在OverviewPage销毁时显式清理缓存(可选,GC会自动回收,显式清理更严谨):
protected override void OnUnloaded(RoutedEventArgs e)
{
    base.OnUnloaded(e);
    _page1 = null;
    _page2 = null;
}

方案2:使用Scoped服务配合专属服务范围(符合DI设计)

将子页面注册为Scoped服务,为OverviewPage创建专属服务范围,子页面从该范围获取,实现与父页面同生命周期:

  1. 在App.xaml.cs中修改DI注册为Scoped:
builder.Services.AddScoped<Page1>();
builder.Services.AddScoped<Page2>();
builder.Services.AddTransient<OverviewPage>();
  1. 在OverviewPage中创建并持有专属服务范围,从该范围获取子页面实例:
private readonly IServiceScope _scope;
private Page1? _page1;
private Page2? _page2;

public OverviewPage(IServiceProvider serviceProvider)
{
    InitializeComponent();
    // 创建父页面专属的服务范围
    _scope = serviceProvider.CreateScope();
}

private void SelectorBar_SelectionChanged(SelectorBar sender, SelectorBarSelectionChangedEventArgs args)
{
    var selectedItem = args.SelectedItem as SelectorBarItem;
    if (selectedItem?.Tag.ToString() == "Page1")
    {
        _page1 ??= _scope.ServiceProvider.GetRequiredService<Page1>();
        ContentFrame.Content = _page1;
    }
    else if (selectedItem?.Tag.ToString() == "Page2")
    {
        _page2 ??= _scope.ServiceProvider.GetRequiredService<Page2>();
        ContentFrame.Content = _page2;
    }
}
  1. 在OverviewPage销毁时释放服务范围,自动销毁Scoped注册的子页面:
protected override void OnUnloaded(RoutedEventArgs e)
{
    base.OnUnloaded(e);
    _scope.Dispose();
}

注意事项

  • 方案1适合简单场景,代码量少,无需改动DI结构;
  • 方案2更适合子页面依赖其他Scoped服务的场景,能保证整个依赖链的生命周期与父页面一致;
  • 禁止使用AddSingleton注册子页面,会导致实例在App生命周期内永久存在,不符合销毁需求。

内容的提问来源于stack exchange,提问作者xerxos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 08:35:14