fsprojects-archive / zzarchive-FSharp.Desktop.UI

F# MVC framework for WPF.
http://fsprojects.github.io/FSharp.Desktop.UI/
Other
81 stars 21 forks source link

TypeInitializationException in Patterns #9

Closed TeaDrivenDev closed 9 years ago

TeaDrivenDev commented 9 years ago

I have started a small application taking the general structure from the Calculator example (which I ported to FsXaml first). However, I am already stuck very early on.

This is the complete F# code:

open System
open System.Windows
open System.Windows.Data

open FSharp.Desktop.UI

type App = FsXaml.XAML<"App.xaml">

type OAuth = FsXaml.XAML<"OAuth.xaml", true>

[<AbstractClass>]
type OAuthModel() =
    inherit Model()

    abstract Pin : string with get, set

type OAuthEvents =
    | SubmitPin

type OAuthView(root : OAuth) as this =
    inherit View<OAuthEvents, OAuthModel, Window>(root.Root)

    override this.EventStreams =
        [
            let buttonClicks =
                [
                    root.SubmitPinButton, SubmitPin
                ]
                |> List.map (fun (button, event) -> button.Click |> Observable.mapTo event)

            yield! buttonClicks                
       ]

    override this.SetBindings model =
        let root = OAuth this.Root

        Binding.OfExpression
            <@
                root.PinTextBox.Text <- coerce model.Pin
            @>

type OAuthController() =
    interface IController<OAuthEvents, OAuthModel> with
        member this.InitModel model =
            model.Pin <- ""

        member this.Dispatcher = function
            | SubmitPin -> Sync this.SubmitPin

    member this.SubmitPin(model : OAuthModel) =
        MessageBox.Show "Da" |> ignore

[<EntryPoint; STAThread>]
let main args =
    let model, view, controller = OAuthModel.Create(), OAuthView(OAuth()), OAuthController()

    let mvc = Mvc(model, view, controller)
    use eventLoop = mvc.Start()
    let app = App().Root
    app.DispatcherUnhandledException.Add <| fun args ->
        if MessageBox.Show(args.Exception.ToString(), "Error! Ignore?", MessageBoxButton.YesNo, MessageBoxImage.Error, MessageBoxResult.Yes) = MessageBoxResult.Yes
        then args.Handled <- true
    app.Run(window = view.Root)

I am at this time just trying to get anything to work; however, when I run this, a TypeInitializationException occurs in the Binding.OfExpression call, telling me that the type initializer for Patterns has thrown an error, and I don't know what to make of it.

PinTextBox in OAuth.xaml is a simple text box, SubmitPin is a button.

Any ideas what I'm doing wrong?

dmitry-a-morozov commented 9 years ago

@TeaDrivenDev Do you have a full source code somewhere on GitHub?

TeaDrivenDev commented 9 years ago

Not right now; I'll try and push something tomorrow.

dmitry-a-morozov commented 9 years ago

Couple suggestions: First, you don't need coerce in binding because types aligned (string - string). coerce is a way to say 'I want to use default WPF type conversions'. Second, to pin-point an issue set-up binding in typeless way e.g.

    root.PinTextBox.SetBinding(TextBox.TextProperty,  "Pin") |< ignore

And see if it works.

TeaDrivenDev commented 9 years ago

@dmitry-a-morozov Yes, that works.

dmitry-a-morozov commented 9 years ago

Hmm, it means there is a problem in typed data-binding module. I will be much interested in repo, if you can.

TeaDrivenDev commented 9 years ago

I put it here: https://github.com/TeaDrivenDev/TwitterDemo

dmitry-a-morozov commented 9 years ago

Fixed in the latest version 0.7.0 Thanks for the bug report and test case repository ! Funny enough the fix has been sitting in source control for more than a month I just haven't manage to push update.

TeaDrivenDev commented 9 years ago

Works fine now, thanks! :-)