2012-12-21 1 views
2

je le ViewModelBase suivant F # que je suis en train de construire pour apprendre F # avec WPF.Type de défaut d'inférence avec F # donne une erreur peu claire

module MVVM 

open System 
open System.Collections.ObjectModel 
open System.ComponentModel 
open Microsoft.FSharp.Quotations 
open Microsoft.FSharp.Quotations.Patterns 
open System.Reactive.Linq 


module Property = 

    let ToName(query : Expr) = 
     match query with 
     | PropertyGet(a, b, list) -> 
      b.Name 
     | _ -> "" 

    let SetValue<'t>(obj, query : Expr<'t>, value : 't) = 
     match query with 
     | PropertyGet(a, b, list) -> 
      b.SetValue(obj, value) 
     | _ ->() 

    let GetValue<'o, 't>(obj : 'o , query : Expr<'t>) : option<'t> = 
     match query with 
     | PropertyGet(a, b, list) -> 
      option.Some(b.GetValue(obj) :?> 't) 
     | _ -> option.None 

    let Observe<'t>(x: INotifyPropertyChanged) (p : Expr<'t>) = 
     let name = ToName(p) 
     x.PropertyChanged. 
      Where(fun (v:PropertyChangedEventArgs) -> v.PropertyName = name). 
      Select(fun v -> GetValue(x, p).Value) 

type ViewModelBase() = 
    let propertyChanged = new Event<_, _>() 

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

    abstract member OnPropertyChanged: string -> unit 

    default x.OnPropertyChanged(propertyName : string) = 
     propertyChanged.Trigger(x, new PropertyChangedEventArgs(propertyName)) 

    member x.SetValue<'t>(expr : Expr<'t>, v : 't) = 
     Property.SetValue(x, expr, v) 
     x.OnPropertyChanged(expr) 

    member x.OnPropertyChanged<'t>(expr : Expr<'t>) = 
     let propName = Property.ToName(expr) 
     x.OnPropertyChanged(propName) 

Cependant je reçois une erreur du compilateur

Error 1 The type 'ViewModelBase' is used in an invalid way. 
A value prior to 'ViewModelBase' has an inferred type involving 
'ViewModelBase', which is an invalid forward reference. 

Cependant, le compilateur ne me dit pas ce que valeur avant est la partie incriminée du problème. Comme je suis assez nouveau à l'inférence de type utilisée par F #, je suis probablement manquer un problème évident.

Pour votre information, le code est destiné à être utilisé comme ci-dessous, mais au moment de ce code est commenté et l'erreur ne portant code de base ci-dessus

type TestModel() as this = 
    inherit MVVM.ViewModelBase() 

    let mutable name = "hello" 

    let subscription = (Property.Observe this <@ this.SelectedItem @>). 
      Subscribe(fun v -> Console.WriteLine "Yo") 

    member x.SelectedItem 
     with get() = name 
     and set(v) = 
      x.SetValue(<@ x.SelectedItem @>, v) 
+0

J'essaye de mettre à jour le wiki à la balise [inpc] que vous avez sur votre message qu'est-ce que c'est censé être? – SnareChops

+0

INPC est l'acronyme commun pour INotifyPropertyChanged une interface de notification des changements de propriété sur les objets les plus utilisés dans la conception d'interface utilisateur pour les modèles MVC ou MVVM – bradgonesurfing

+1

Les acronymes sont vagues. Nous avons déjà un tag pour la vraie chose. – Charles

Répondre

6

Je l'ai trouvé.

let SetValue<'t>(obj, query : Expr<'t>, value : 't) = 
    match query with 
    | PropertyGet(a, b, list) -> 
     b.SetValue(obj, value) 
    | _ ->() 

était sous contrainte. Je devrais être

let SetValue<'t>(obj : Object, query : Expr<'t>, value : 't) = 
    match query with 
    | PropertyGet(a, b, list) -> 
     b.SetValue(obj, value) 
    | _ ->() 
+0

Marquer comme une réponse! –

+0

Cela prend toujours deux jours avant que le débordement de pile vous permette d'accepter votre propre réponse. – bradgonesurfing

Questions connexes