How would one implement INotifyPropertyChanged for use in an F# type? Thanks!
Asked
Active
Viewed 2,074 times
2 Answers
22
It's basically the same as in any other language:
open System.ComponentModel
type MyType() =
let ev = new Event<_,_>()
let mutable str = ""
member x.StringProp
with get() = str
and set(str') =
str <- str'
ev.Trigger(x, PropertyChangedEventArgs("StringProp"))
interface INotifyPropertyChanged with
[<CLIEvent>]
member x.PropertyChanged = ev.Publish

kvb
- 54,864
- 2
- 91
- 133
-
16That is not "basically the same" as other languages :P – Cameron MacFarland Nov 08 '09 at 23:10
-
1Thanks, What exactly is the [
] attribute do? I can't seem to find any the documentation on it. – rysama Nov 08 '09 at 23:17 -
5@RodYan - it affects the compiled form that the event takes; for interop with other .NET languages (and to implement interfaces exposing .NET events), you'll need to apply it to an IEvent value. This causes `add_` and `remove_` methods to be generated, as opposed to actually exposing a property of type `IEvent<_,_>`, as described at http://msdn.microsoft.com/en-us/library/ee370437(VS.100).aspx. – kvb Nov 08 '09 at 23:28
-
3This is a very good example of implementing the interface, but does not show how to wire it up via data binding to a WPF control property, for instance. – Scott Hutchinson Dec 22 '16 at 21:24
-
1@ScottHutchinson WPF automatically hooks to the event as part of the binding. – Jesse Feb 11 '17 at 05:06
3
https://github.com/Fody/PropertyChanged https://github.com/Fody/PropertyChanged/issues/280
In practice
You can use fody proeprty changed to automatically implement it
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
}
Then you can use it like this
type ViewModelTest() =
inherit ViewModelBase()
/// two way binding
member val Hello = 6 with get, set
/// one way binding
member x.Yes = x.Hello + 1
The generated Decompiled codes are
using System;
using Microsoft.FSharp.Core;
namespace Shrimp.UI.Forms.FSharp
{
// Token: 0x02000002 RID: 2
[CompilationMapping(3)]
[Serializable]
public class ViewModelTest : ViewModelBase
{
// Token: 0x06000001 RID: 1 RVA: 0x00002050 File Offset: 0x00000250
public ViewModelTest() : this()
{
this.Hello@ = 6;
}
// Token: 0x17000001 RID: 1
// (get) Token: 0x06000002 RID: 2 RVA: 0x00002061 File Offset: 0x00000261
// (set) Token: 0x06000003 RID: 3 RVA: 0x0000206C File Offset: 0x0000026C
public int Hello
{
get
{
return this.Hello@;
}
set
{
if (this.Hello@ == value)
{
return;
}
this.Hello@ = value;
this.<>OnPropertyChanged(<>PropertyChangedEventArgs.Yes);
this.<>OnPropertyChanged(<>PropertyChangedEventArgs.Hello);
}
}
// Token: 0x17000002 RID: 2
// (get) Token: 0x06000004 RID: 4 RVA: 0x000020A4 File Offset: 0x000002A4
public int Yes
{
get
{
return this.Hello + 1;
}
}
// Token: 0x04000001 RID: 1
internal int Hello@;
}
}

humhei
- 31
- 1