Is there any example on how to invoke a DelegateCommand on a viewmodel written in F#?
I have found the following code for a DelegateCommand implementation here:
type DelegateCommand<a>(execute : 'a -> unit, ?canExecute : 'a -> bool) =
let event = Event<_,_>()
interface ICommand with
member this.CanExecute(param : obj) =
if canExecute.IsSome then
canExecute.Value(param :> 'a)
else true
member this.Execute (param : obj) =
execute(param :> 'a)
However, being new to F#, I'm not sure if I should use this implementation or if there is some other approach I should be leveraging.
Here's a test that I would like to execute once I figure out how to execute a DelegateCommand:
module CreateProfileViewModel.Tests
open FsUnit
open NUnit.Framework
open CreateProfile.UILogic
[<Test>]
let ``create profile`` () =
// Setup
let viewModel = ViewModel()
viewModel.FirstName <- "Scott"
viewModel.LastName <- "Nimrod"
// Test
viewModel.Submit.Execute();
// Verify
let expected = false // TODO - implement some state-change
expected |> should equal true
My viewmodel is the following:
module CreateProfile
open Core.UILogic
type ViewModel() =
inherit ViewModelBase()
let mutable firstName = ""
let mutable lastName = ""
member this.FirstName
with get() = firstName
and set(value) =
firstName <- value
base.NotifyPropertyChanged(<@ this.FirstName @>)
member this.LastName
with get() = lastName
and set(value) =
lastName <- value
base.NotifyPropertyChanged(<@ this.LastName @>)
I have the following base-viewmodel:
module Core.UILogic
open System.ComponentModel
open Microsoft.FSharp.Quotations.Patterns
type ViewModelBase () =
let propertyChanged =
Event<PropertyChangedEventHandler,PropertyChangedEventArgs>()
let getPropertyName = function
| PropertyGet(_,pi,_) -> pi.Name
| _ -> invalidOp "Expecting property getter expression"
interface INotifyPropertyChanged with
[<CLIEvent>]
member this.PropertyChanged = propertyChanged.Publish
member private this.NotifyPropertyChanged propertyName =
propertyChanged.Trigger(this,PropertyChangedEventArgs(propertyName))
member this.NotifyPropertyChanged quotation =
quotation |> getPropertyName |> this.NotifyPropertyChanged
Update:
I have modified the RelayCommand defined in the MVVM project template for F# to the following:
module UILogic.Interaction
open System
open System.Windows
open System.Windows.Input
open System.ComponentModel
type DelegateCommand (action:(obj -> unit), canExecute:(obj -> bool)) =
let event = new DelegateEvent<EventHandler>()
interface ICommand with
[<CLIEvent>]
member this.CanExecuteChanged = event.Publish
member this.CanExecute arg = canExecute(arg)
member this.Execute arg = action(arg)
I then updated my viewmodel as follows:
module CreateProfile.UILogic
open UILogic.State
open UILogic.Interaction
type ViewModel() =
inherit ViewModelBase()
let mutable _firstName = ""
let mutable _lastName = ""
let mutable _submitted = false
member this.FirstName
with get() = _firstName
and set(value) =
_firstName <- value
base.NotifyPropertyChanged(<@ this.FirstName @>)
member this.LastName
with get() = _lastName
and set(value) =
_lastName <- value
base.NotifyPropertyChanged(<@ this.LastName @>)
member this.IsSubmitted
with get() = _submitted
and set(value) = _submitted <- value
member this.Submit =
new DelegateCommand ((fun _ -> this.IsSubmitted <- true), (fun _ -> true))
However, I am not sure how to invoke the Execute function on the Submit (DelegateCommand):
module CreateProfileViewModel.Tests
open FsUnit
open NUnit.Framework
open UILogic.State
open CreateProfile.UILogic
[<Test>]
let ``create profile`` () =
// Setup
let viewModel = ViewModel()
viewModel.FirstName <- "Scott"
viewModel.LastName <- "Nimrod"
// Test
ignore viewModel.Submit.Execute(); // How to invoke execute?
// Verify
viewModel.IsSubmitted |> should equal true
I know this is trivial, but I honestly have no clue how to do this.
Any suggestions?
A delegate command calls methods (delegates) that you assigned to the command when the command's Execute and CanExecute logic is invoked. The following delegate commands are available: DelegateCommand<T> - Specifies a command whose Execute and CanExecute delegates accept a single parameter of type T.
DelegateCommand(Action<Object>) Initializes a new instance of the DelegateCommand class. Using this constructor to initialize the DelegateCommand results in a command that can always execute. DelegateCommand(Action<Object>, Predicate<Object>) Initializes a new instance of the DelegateCommand class.
The ICommand interface is the code contract for commands that are written in . NET for Windows Runtime apps. These commands provide the commanding behavior for UI elements such as a Windows Runtime XAML Button and in particular an AppBarButton .
The RelayCommand and RelayCommand<T> are ICommand implementations that can expose a method or delegate to the view. These types act as a way to bind commands between the viewmodel and UI elements.
Change the Submit
implementation to this:
member this.Submit =
DelegateCommand ((fun _ -> this.IsSubmitted <- true), (fun _ -> true)) :> ICommand
and call it like this:
viewModel.Submit.Execute() |> ignore
The important change is that the Submit
method's return type is now ICommand
instead of DelegateCommand
. This is due to the use of the upcast operator :>
.
In F#, all interfaces are explicitly implemented. This means that although DelegateCommand
implements ICommand
, the methods of ICommand
aren't visible on objects declared (or inferred) as DelegateCommand
. When the value is declared (or inferred) to be of the type ICommand
, on the other hand, only the members of ICommand
are available.
Since I have not used MVC or MVVM with F# I cannot give a specific code example.
For
However, being new to F#, I'm not sure if I should use this implementation or if there is some other approach I should be leveraging.
If you use Visual Studio, which also has a community edition that can be download for free, there are templates for MVC and MVVM.
To access the templates from VS using the menu.
File -> New -> Project
Expand Online
Expand Templates
Expand Visual F#
In the upper right for "Search Online Templates" enter a term such as MVC or MVVM
Pick one or examine a few.
Note: Some of the templates are a few years old and F# and Windows has progressed much along the way so I would tend to avoid the older ones. Also the authors of the popular ones can typically be found online and even some are here so ask questions about specifics.
You can also view other templates, controls and extensions to VS at the Visual Studio Gallery using an Internet browser.
Caution: Some of the extensions will cause problems when installed, especially the older or less popular ones, so be careful and don't install them on a production machine until you test them on a different machine first.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With