如何在WPF的IValueConverter中注入依赖项
如何在WPF的IValueConverter中注入依赖项
嘿,我来给你说下在WPF里用Prism给IValueConverter做依赖注入的办法,完全不用那些讨厌的静态访问~
步骤1:改造转换器支持构造函数注入
先把你的转换器改成通过构造函数接收依赖的形式,比如我要注入一个IMyService服务,代码可以这么写:
public class MyConverter : IValueConverter { private readonly IMyService _myService; // 直接在构造函数里声明依赖,容器会自动注入 public MyConverter(IMyService myService) { _myService = myService; } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { // 这里就可以正常使用注入的_myService处理业务逻辑了 return _myService.ProcessInputValue(value); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
步骤2:在Prism容器中注册服务和转换器
打开App.xaml.cs,找到RegisterTypes方法,把你的服务和转换器都注册到Prism的依赖注入容器里:
protected override void RegisterTypes(IContainerRegistry containerRegistry) { // 先注册依赖的服务 containerRegistry.Register<IMyService, MyServiceImpl>(); // 再注册转换器 containerRegistry.Register<MyConverter>(); }
步骤3:让Prism接管转换器的实例化(关键)
WPF默认会自己实例化XAML中引用的转换器,这会导致依赖注入失效,所以我们要让Prism来负责创建转换器实例,这里有两种好用的方式:
- 方式一:使用Prism的ConverterMarkupExtension
Prism专门提供了这个标记扩展来解决转换器的DI问题,在XAML里引用转换器时,不要用普通的StaticResource,换成它:
<Window x:Class="YourAppNamespace.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" xmlns:local="clr-namespace:YourAppNamespace"> <Window.Resources> <!-- 用这个扩展从容器中获取已注入依赖的转换器实例 --> <prism:ConverterMarkupExtension x:Key="MyConverter" Type="{x:Type local:MyConverter}" /> </Window.Resources> <Grid> <TextBlock Text="{Binding YourData, Converter={StaticResource MyConverter}}" /> </Grid> </Window>
这样WPF就会从Prism容器里拿已经注入好依赖的转换器,而不是自己new一个无参的实例。
- 方式二:将转换器作为ViewModel的属性
如果觉得标记扩展用着麻烦,也可以在ViewModel里注入转换器,然后暴露成属性,XAML直接绑定这个属性:
public class MainViewModel : BindableBase { // 注入转换器 public MyConverter MyConverter { get; } public MainViewModel(MyConverter myConverter) { MyConverter = myConverter; } // 你的业务数据属性 private object _yourData; public object YourData { get => _yourData; set => SetProperty(ref _yourData, value); } }
XAML里的用法:
<TextBlock Text="{Binding YourData, Converter={Binding MyConverter}}" />
这种方式更贴合MVVM的思路,也能确保转换器完全由容器管理,依赖注入自然生效。
这两种方案都能避开静态访问,和你之前看到的Xamarin方案逻辑一致,完美适配WPF的场景哦~
备注:内容来源于stack exchange,提问作者06luki06
相关产品推荐
相关产品推荐

