.NET Framework 4.8 WPF如何在XAML中通过DI加载视图?
在.NET Framework 4.8 WPF中从DI容器获取XAML视图实例
核心问题原因
直接在XAML中写<rasViews:RasView/>时,WPF解析器会直接调用视图的无参构造函数创建实例,完全绕过你配置的DI容器,所以无法获取到DI注入的依赖。
解决方案:自定义XAML标记扩展
通过自定义Markup Extension,让XAML在解析时从DI容器中获取视图实例,具体步骤如下:
1. 保存DI容器的服务提供者
在App.xaml.cs中,将Host创建的IServiceProvider暴露为静态属性,方便标记扩展访问:
public partial class App : Application { public static IServiceProvider ServiceProvider { get; private set; } protected override void OnStartup(StartupEventArgs e) { var host = Host.CreateDefaultBuilder() .ConfigureServices(services => { // 注册视图和视图模型 services.AddTransient<RasViewModel>(); services.AddTransient<RasView>(); }) .Build(); ServiceProvider = host.Services; base.OnStartup(e); } }
2. 实现自定义DI标记扩展
创建一个继承自MarkupExtension的类,用于从DI容器中获取指定类型的实例:
using System; using System.Windows.Markup; namespace YourAppNamespace { public class DIExtension : MarkupExtension { public Type ServiceType { get; set; } public override object ProvideValue(IServiceProvider serviceProvider) { return App.ServiceProvider.GetService(ServiceType); } } }
3. 在XAML中使用标记扩展获取视图
不再直接写<rasViews:RasView/>,而是通过自定义标记扩展从DI容器获取实例,通常用ContentControl承载:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:YourAppNamespace" xmlns:rasViews="clr-namespace:YourRasViewsNamespace"> <!-- 通过DI获取RasView实例 --> <ContentControl Content="{local:DIExtension ServiceType={x:Type rasViews:RasView}}"/> </Window>
可选方案:ViewModel-First模式
如果你的视图依赖于ViewModel(构造函数注入),也可以采用ViewModel优先的方式:
- 在XAML中定义ViewModel到视图的DataTemplate:
<Window.Resources> <DataTemplate DataType="{x:Type rasViewModels:RasViewModel}"> <rasViews:RasView/> </DataTemplate> </Window.Resources>
- 通过标记扩展获取ViewModel实例,WPF会自动匹配DataTemplate创建视图:
<ContentControl Content="{local:DIExtension ServiceType={x:Type rasViewModels:RasViewModel}}"/>
这种方式更符合MVVM模式,且视图的依赖会由DI容器自动注入。
内容的提问来源于stack exchange,提问作者Vaccano
相关产品推荐
相关产品推荐

