Is it possible to implement INotifyPropertyChanged as a type extension in F #

In C #, you can implement a PropertyChangedEventHandler based extension method like this:

  static class VMExts
  {
    public static void RaisePropertyChanged(this PropertyChangedEventHandler handler, object sender, string propName)
    {
      if(handler != null)
      {
        handler(sender, new PropertyChangedEventArgs(propName));
      }
    }
  }

      

What can be called the following:

  class VM : INotifyPropertyChanged
  {
    private string _someText;

    public event PropertyChangedEventHandler PropertyChanged;

    public string SomeText
    {
      get { return _someText; }
      set
      {
        _someText = value;
        PropertyChanged.RaisePropertyChanged(this, "SomeText");
      }
    }
  }

      

I'm trying to achieve something similar in F #, but can't figure out the syntax. Obviously it is quite easy to achieve this by inheriting from some ViewModelBase style class such as http://www.fssnip.net/2x , but it would be nice to have an extension method.

So, given this class:

  type ViewModelBase() =
    let mutable _someText = ""
    let propertyChanged = Event<_, _>()

    interface INotifyPropertyChanged with
      [<CLIEvent>]
      member x.PropertyChanged = propertyChanged.Publish

    member x.SomeText 
      with get() = _someText
      and set(value) = 
        _someText <- value
        (x :> INotifyPropertyChanged).PropertyChanged.RaisePropertyChanged("SomeText")

      

I tried:

  type PropertyChangedEventHandler with
    member x.RaisePropertyChanged(sender, propName) =
      if x <> null then
        x.Invoke(sender, PropertyChangedEventArgs(propName))

      

and

  open System.Runtime.CompilerServices

  [<Extension>]
  type VmExtensions() =
    [<Extension>]  
    static member inline RaisePropertyChanged(handler : PropertyChangedEventHandler, propName) =
      if handler <> null then
        handler.Invoke(handler, PropertyChangedEventArgs(propName))

      

I think they cannot be found as valid for PropertyChanged because PropertyChanged type is IEvent whereas I extended PropertyChangedEventHandler type.

So I tried:

  type IEvent<PropertyChangedEventHandler, PropertyChangedEventArgs> with
    member x.RaisePropertyChanged(sender, propName) =
      if x <> null then
        x.Invoke(sender, PropertyChangedEventArgs(propName))

      

But the compiler doesn't like using IEvent

  [<Extension>]
  type VmExtensions() =
    [<Extension>]  
    static member inline RaisePropertyChanged(handler : IEvent<PropertyChangedEventHandler, PropertyChangedEventArgs>, propName) =
//      if handler <> null then
        handler.Invoke(handler, PropertyChangedEventArgs(propName))

      

But IEvent only has a Subscribe method

thank

+3


source to share


1 answer


You can raise the event with a method Trigger

that is defined in Event

(not on IEvent

):



[<Extension>]
type VmExtensions =
    [<Extension>]  
    static member inline RaisePropertyChanged
        (ev:Event<PropertyChangedEventHandler, _>, propName) =

        ev.Trigger(null, PropertyChangedEventArgs propName)

      

+4


source







All Articles