-
Notifications
You must be signed in to change notification settings - Fork 224
How to implement OnPropertyChanged
This guide shows how to add INotifyPropertyChanged support to generated POCO classes. The approach uses file-based templates for a clean, maintainable implementation.
The cleanest way is to use Custom file-based templates and modify the POCO template directly. This avoids editing the .ttinclude file (which would be overwritten on upgrade).
If you only need OnPropertyChanged for specific scenarios, use the partial modifier and implement the logic in a separate file without touching the generator.
Settings.UpdateTable = delegate(Table table)
{
table.BaseClasses = " : INotifyPropertyChanged";
};Settings.AdditionalNamespaces = new List<string>
{
"System.ComponentModel",
"System.Runtime.CompilerServices"
};In Database.tt, use WriteInsideClassBody:
Settings.WriteInsideClassBody = delegate(Table t)
{
return
" public event PropertyChangedEventHandler PropertyChanged;" + Environment.NewLine +
" protected virtual void OnPropertyChanged([CallerMemberName] string name = null)" + Environment.NewLine +
" {" + Environment.NewLine +
" PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));" + Environment.NewLine +
" }" + Environment.NewLine;
};This step requires editing the Mustache property template in your file-based templates folder, or editing EF.Reverse.POCO.v3.ttinclude.
Warning: Editing
EF.Reverse.POCO.v3.ttincludedirectly means your changes will be lost when you upgrade the generator. Use file-based templates instead.
In the property template, find the line that generates properties:
public {{#if OverrideModifier}}override {{/if}}{{WrapIfNullable}} {{NameHumanCase}}
Replace it with a backing field + property with change notification:
private {{WrapIfNullable}} _{{NameHumanCase}};{{#newline}}
public {{#if OverrideModifier}}override {{/if}}{{WrapIfNullable}} {{NameHumanCase}} { get { return _{{NameHumanCase}}; } {{PrivateSetterForComputedColumns}}set { if(value != _{{NameHumanCase}}) { _{{NameHumanCase}} = value; OnPropertyChanged(); } } }{{PropertyInitialisers}}{{InlineComments}}{{#newline}}Generated classes will look like:
public partial class Order : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
private int _orderId;
public int OrderId
{
get { return _orderId; }
set { if (value != _orderId) { _orderId = value; OnPropertyChanged(); } }
}
private string _customerName;
public string CustomerName
{
get { return _customerName; }
set { if (value != _customerName) { _customerName = value; OnPropertyChanged(); } }
}
}