如何让PropertyChanged.Fody适配WPF数据绑定与EF 6.0数据库优先模式?
我之前也碰到过类似的场景——用EF6数据库优先生成的实体类,不想改自动生成的代码,还要让Fody帮我们自动实现INotifyPropertyChanged来支持WPF数据绑定,而且没走MVVM模式。给你一步步梳理下怎么做:
1. 先安装必要的NuGet包
首先得把PropertyChanged.Fody装到你的项目里。你可以通过NuGet包管理器界面搜索PropertyChanged.Fody安装,或者打开Package Manager Console执行命令:
Install-Package PropertyChanged.Fody
安装完成后,项目根目录会自动生成一个FodyWeavers.xml文件,如果没生成的话,手动创建一个,内容如下:
<Weavers> <PropertyChanged /> </Weavers>
这个文件是Fody的配置,告诉它要启用PropertyChanged织入器。
2. 利用partial类扩展EF生成的Test类
EF数据库优先生成的Test类是partial类型(你看自动生成的代码里肯定有public partial class Test),这就给了我们扩展的空间——绝对不要修改自动生成的代码,因为重新生成EDMX的时候会被覆盖。
在项目里新建一个类文件(比如叫Test.PropertyChanged.cs),然后写一个同名的partial类,命名空间要和自动生成的Test类完全一致,然后加上Fody的[AddINotifyPropertyChangedInterface]属性:
using PropertyChanged; // 这里的命名空间必须和EF自动生成的Test类完全相同 namespace YourProjectNamespace.Entities { [AddINotifyPropertyChangedInterface] public partial class Test { // 这里不需要写任何额外代码,Fody会自动帮我们织入INotifyPropertyChanged的实现 } }
这个属性会告诉Fody,在编译时给Test类自动添加INotifyPropertyChanged接口的实现,并且在每个属性的setter里触发PropertyChanged事件。
3. 验证WPF绑定是否正常工作
因为你没采用MVVM模式,直接把Test实例绑定到界面就行。比如在Window的构造函数里:
public MainWindow() { InitializeComponent(); // 实例化EF上下文,获取Test对象 using(var dbContext = new YourDbContext()) { var testItem = dbContext.Tests.FirstOrDefault(); // 把Test对象设为界面的DataContext DataContext = testItem; } }
然后在XAML里写绑定,比如绑定一个TextBox:
<TextBox Text="{Binding YourPropertyName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
现在你修改TextBox的内容,Test对象的对应属性会自动更新,同时因为Fody织入了PropertyChanged事件,界面也会同步属性的变化(如果有其他控件绑定了同一个属性的话)。
可能踩的坑
- 命名空间必须一致:如果partial类的命名空间和EF生成的不一样,Fody找不到要处理的类,肯定不会生效。
- 不要修改自动生成的代码:每次更新EDMX重新生成实体类时,手动修改的内容会被覆盖,所以一定要用partial类扩展。
- 如果EF生成的类继承了EntityObject:这种情况下EntityObject本身已经实现了
INotifyPropertyChanged,可能不需要Fody,但如果还是想用Fody的话,需要确保Fody的织入逻辑不会和原有实现冲突,不过一般建议用POCO实体类(EDMX生成时可以选择POCO)。
内容的提问来源于stack exchange,提问作者Joe

