MVVM – f#async / await in view model

My ViewModel in F #

I'm trying to use f# instead of c# to implement my ViewModel I'm following this article (by the way, do you have any new or better suggestions?)

So, suppose I have my view model library implementation (MVVM. ViewModel, which is in C #, but I can refer to it from F #) and a simple status attribute

namespace Funcviewmodel
open MVVM.viewmodel
open System

    type MyFuncviewmodel() = 
        inherit viewmodelBase()

        let mutable status=""

        member this.RunSetStatus() =
            status <- "Reset @" + DateTime.Now.ToString "yy.MM.dd hh:mm:ss"
            base.OnPropertyChanged("Status")

        member this.SetStatus = new DelegateCommand(fun _ -> this.RunSetStatus() )


    member this.Status 
        with get() =
            status
        and set(value) =
             status <- value
             base.OnPropertyChanged(fun () -> this.Status)

Everything worked as expected and has been good so far (but if you find any conceptual errors, or if you find a more common version of the above code, please let me know)

Introduce async / await mode

This is where I went wrong: I know how to do this in C #, but I'm not good at f #

I've tried the following

member this.RunSetStatus() =
    status <- "Start resetting @" + DateTime.Now.ToString "yy.MM.dd hh:mm:ss"
    base.OnPropertyChanged("Status")
    let task = async {

        do! Async.Sleep (30 * 1000) 

    }
    Async.StartImmediate(task)
    status <- "Reset done @" + DateTime.Now.ToString "yy.MM.dd hh:mm:ss"
    base.OnPropertyChanged("Status")

The problem is - when I run a full WPF application - I don't see the expected delay: the final state is output directly to the output

If I put the above async Change startimmediate to async Runsynchronously (task), of course I see the ongoing delay, but the application is frozen, so this is not what I want

If I rearrange them as

member this.RunSetStatus() =
    status <- "Start resetting @" + DateTime.Now.ToString "yy.MM.dd hh:mm:ss"
    base.OnPropertyChanged("Status")
    let task = async {

        do! Async.Sleep (30 * 1000) 

        status <- "Reset done @" + DateTime.Now.ToString "yy.MM.dd hh:mm:ss"
        base.OnPropertyChanged("Status")

    }
    Async.StartImmediate(task)

I received an error

Editing (Continued)

Finally, I tried this

member this.RunSetStatus() =
    status <- "Start resetting @" + DateTime.Now.ToString "yy.MM.dd hh:mm:ss"
    base.OnPropertyChanged("Status")
    let task = async {

        do! Async.Sleep (30 * 1000) 

    }
    Async.StartWithContinuations(task,(fun _ -> this.Status <- "Reset done @" + DateTime.Now.ToString "yy.MM.dd hh:mm:ss"),(fun _ -> this.Status <- "Operation Failed."),(fun _ -> this.Status <- "Operation canceled."))

However, argumentexception occurs when the application crashes

stack trace

Edit 2 – problems found

I have to use the following - more simply - the overload of onpropertychanged (they are implemented according to this source code and work in c#)

member this.Status 
        with get() =
            status
        and set(value) =
             status <- value
             base.OnPropertyChanged("Status")

Solution

The reason for the exception is that f#'s function cannot be expressed as memberexpression:

protected virtual void OnPropertyChanged<T>(Expression<Func<T>> selectorExpression)
    {
        if (selectorExpression == null)
            throw new ArgumentNullException("selectorExpression");
        MemberExpression body = selectorExpression.Body as MemberExpression;
        if (body == null)
            throw new ArgumentException("The body must be a member expression");
        OnPropertyChanged(body.Member.Name);
    }

In the debugger, you will see the exception actually obtained - "the body must be a member expression"

Your first code:

member this.RunSetStatus() =
    status <- "Reset @" + DateTime.Now.ToString "yy.MM.dd hh:mm:ss"
    base.OnPropertyChanged("Status")

Because you do not use the property setter state, it works normally

So you need to use different overloads

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>