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

WPF使用工厂委托DI时如何通过NavigationService向页面传参

WPF NavigationService 结合DI传参实现

现有代码说明

当前已通过工厂委托完成依赖注入注册,需要实现从PrinterDetails页面导航到ProvinceList页面时同步传递参数,并在目标页GetProvinceList方法中读取参数。

现有DI配置(App.xaml.cs)

private void ConfigureServices(ServiceCollection serviceCollection)
{
    serviceCollection.AddTransient<Home>();
    serviceCollection.AddSingleton<Func<Home>>(ServiceProvider => ServiceProvider.GetService<Home>);

    serviceCollection.AddTransient<PrinterDetails>();
    serviceCollection.AddSingleton<Func<PrinterDetails>>(ServiceProvider => ServiceProvider.GetService<PrinterDetails>);

    serviceCollection.AddTransient<ProvinceList>();
    serviceCollection.AddSingleton<Func<ProvinceList>>(ServiceProvider => ServiceProvider.GetService<ProvinceList>);

    serviceCollection.AddSingleton(Configuration);
    serviceCollection.AddTransient<ISqlDataAccess, SqlDataAccess>();
    serviceCollection.AddTransient<IProvinceListViewModel, ProvinceListViewModel>();
    
    serviceCollection.AddTransient(typeof(MainWindow));
}

现有导航发起页代码(PrinterDetails.xaml.cs)

public partial class PrinterDetails : Page, INotifyPropertyChanged
{
    private Func<ProvinceList> ProvinceListFactory { get; }

    
    public PrinterDetails(Func<ProvinceList> provinceListFactory)
    {
        InitializeComponent();
        DataContext = this;

        PrinterService printerService = new PrinterService();
        cmbPrinterList.ItemsSource = printerService.PrinterList();
        ProvinceListFactory = provinceListFactory;
   
    }

    private void btnProvince_Click(object sender, RoutedEventArgs e)
    {
        ProvinceList nextPage = this.ProvinceListFactory.Invoke();
        NavigationService.Navigate(nextPage);
    }
}

现有参数接收页代码(ProvinceList.xaml.cs)

public partial class ProvinceList : Page
{
    private readonly IProvinceListViewModel _provinceListViewModel;

    public ProvinceList(IProvinceListViewModel provinceListViewModel)
    {
        InitializeComponent();
        _provinceListViewModel = provinceListViewModel;
        GetProvinceList();
    }

    private void GetProvinceList()
    {
        // 待实现:获取上一页面传递的参数
    }
}

实现方案(最小改动版本,推荐)

不需要调整现有DI注册逻辑,利用WPF Page自带的导航生命周期即可实现参数传递。

  1. 修改目标页ProvinceList
    • 添加参数接收属性
    • 重写OnNavigatedTo生命周期方法,在导航完成后读取参数、执行业务逻辑
    • 移除构造函数中对GetProvinceList的调用(构造函数执行时参数尚未传递,会导致空值)
public partial class ProvinceList : Page
{
    private readonly IProvinceListViewModel _provinceListViewModel;
    // 导航参数接收属性,可根据实际业务替换为具体的强类型
    public object? PassedParameter { get; set; }

    public ProvinceList(IProvinceListViewModel provinceListViewModel)
    {
        InitializeComponent();
        _provinceListViewModel = provinceListViewModel;
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);
        // 导航完成后执行参数依赖的业务逻辑
        GetProvinceList();
    }

    private void GetProvinceList()
    {
        // 直接读取PassedParameter即可获取上一页传递的参数
        var param = PassedParameter;
        // 原有业务逻辑
    }
}
  1. 修改导航发起页的点击事件
    实例化目标页后直接给参数属性赋值,再执行导航即可,不需要改动DI注册代码:
private void btnProvince_Click(object sender, RoutedEventArgs e)
{
    ProvinceList nextPage = this.ProvinceListFactory.Invoke();
    // 赋值要传递的参数,支持任意自定义类型、值类型、引用类型
    nextPage.PassedParameter = "实际需要传递的业务参数";
    NavigationService.Navigate(nextPage);
}

可选强类型工厂方案

如果需要把传参逻辑收敛到工厂层、避免页面暴露可写参数属性,可以改造DI注册的工厂委托:

  1. 修改DI配置
    把原有无参工厂替换为支持传参的强类型工厂:
// 替换原有ProvinceList的工厂注册
serviceCollection.AddTransient<ProvinceList>();
serviceCollection.AddSingleton<Func<object, ProvinceList>>(sp =>
{
    return (bizParam) =>
    {
        var page = sp.GetRequiredService<ProvinceList>();
        page.PassedParameter = bizParam;
        return page;
    };
});
  1. 修改PrinterDetails的工厂注入和导航逻辑
public partial class PrinterDetails : Page, INotifyPropertyChanged
{
    // 修改工厂类型匹配新注册的委托
    private Func<object, ProvinceList> ProvinceListFactory { get; }

    public PrinterDetails(Func<object, ProvinceList> provinceListFactory)
    {
        InitializeComponent();
        DataContext = this;
        PrinterService printerService = new PrinterService();
        cmbPrinterList.ItemsSource = printerService.PrinterList();
        ProvinceListFactory = provinceListFactory;
    }

    private void btnProvince_Click(object sender, RoutedEventArgs e)
    {
        // 调用工厂时直接传入参数
        ProvinceList nextPage = this.ProvinceListFactory.Invoke("实际需要传递的业务参数");
        NavigationService.Navigate(nextPage);
    }
}

注意事项

  • 所有依赖导航参数的逻辑必须放到OnNavigatedTo及之后的生命周期执行,禁止在构造函数中调用,否则会出现参数空引用问题
  • 同进程内导航传递参数不需要做序列化处理,直接传递原始对象即可
  • 若页面不需要保留参数引用,可在OnNavigatedFrom生命周期中将参数属性置空,方便GC回收

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 15:21:26