heoo.lib
1.2.1
See the version list below for details.
dotnet add package heoo.lib --version 1.2.1
NuGet\Install-Package heoo.lib -Version 1.2.1
<PackageReference Include="heoo.lib" Version="1.2.1" />
paket add heoo.lib --version 1.2.1
#r "nuget: heoo.lib, 1.2.1"
// Install heoo.lib as a Cake Addin #addin nuget:?package=heoo.lib&version=1.2.1 // Install heoo.lib as a Cake Tool #tool nuget:?package=heoo.lib&version=1.2.1
half-elmish-oo
This library is kind of experimental. I want to create elmish program loops (message processing loops) with a simple callback.
Example
Step1 - Design your program
open heoo.lib
open System
//Elmish programs need a model a message and update function.
type Model = { Count: int; SomeText:string }
type Message =
| Increase
| Decrease
| Reset
| SetText of string
let Update (model:Model) (msg:Message) =
match msg with
| Increase -> { model with Count = model.Count + 1 }
| Decrease -> { model with Count = model.Count - 1 }
| Reset -> { model with Count = 0 }
| SetText text -> { model with SomeText = text }
Step2 - Create your viewmodel
type MyVm(initialModel,messageCallback) =
inherit ViewModelBase.T<Model,Message>(initialModel)
//Remember that this is async.
//Wait for InotifyPropertyChanged until getter is properly updated.
member this.GetSetSomeText
with get() =
this.getPropertyError(
fun m ->
match m.SomeText with
| "" -> "SomeText cannot be empty"
| _ -> ""
)//empty string is no error
this.getPropertyValue(fun m -> m.SomeText)
and set v = v |> SetText |> messageCallback
member this.GetCounter
with get() = this.getPropertyValue(fun m -> m.Count)
member this.IncreaseCmd =
CommandBase.AlwaysExecutableCommand(fun _ -> messageCallback Increase)
member this.DecreaseCmd =
CommandBase.AlwaysExecutableCommand(fun _ -> messageCallback Decrease)
member this.ResetCmd
with get() =
this.getPropertyValue(fun m ->
let canExecute = fun _ -> m.Count <> 0//already reset
let execute = fun _ -> messageCallback Reset
CommandBase.T(canExecute,execute)
)
member this.GetAllErrorMessages
//ignore the keys (propertynames) and just get the values in an array
with get():string array = this.getPropertyValue(
fun model ->
//Errors are stored as key,value pairs.
//Where value is a function that returns a string from given model.
this.GetErrorsArray()
|> Array.map(fun (_,errorFunc) -> errorFunc model)
)
Step3 - Instantiate your program loop and viewmodel
let initialModel = { Count = 0; SomeText = "Hello World" }
let program = ElmishProgramAsync.T(initialModel,Update)
//WARNING!, once you call (IDisposable)Dispose() on the program loop, you can't use it anymore.
//like this: program.AsIDisposable().Dispose()
let viewModelInstance = MyVm(initialModel,program.PostMessage)
Step3.1 - wire OnModelUpdated to viewmodel
//Remember to wire your programs OnModelUpdated action to your viewmodel
//It might be a good idea to not write this here and move it into your gui application instead.
program.OnModelUpdated <-
Action<Model>(
fun m ->
//if this is a gui application, thread synchronization is (usually) needed.
//This might be a good place for it to happen.
//...
//example: Dispatcher.Invoke(viewMModelInstance.updateModel m)
viewModelInstance.updateModel m
)
|> Some
Step4 - Consume your viewmodel
Consume your viewmodel in your application (wpf, Winforms, Avalonia, MAUI.net,Uno, Unity3D etc) As you would with any other INotifyPropertyChanged,INotifyDataErrorInfo, IDataErrorInfo, ICommand implementation.
Additional comments
It should be no problem to create more elmishprograms to avoid the whole monolithic approach.
It's also possible to have multiple viewmodels from one program.
I'm trying to leave the door open for more advanced scenarios.
Where you as a consumer is in control.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.1 is compatible. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- FSharp.Core (>= 6.0.6)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated | |
---|---|---|---|
1.3.1 | 270 | 3/1/2023 | |
1.3.0 | 228 | 2/15/2023 | |
1.2.5 | 246 | 2/7/2023 | |
1.2.4 | 481 | 10/12/2022 | |
1.2.3 | 443 | 10/6/2022 | |
1.2.2 | 441 | 10/5/2022 | |
1.2.1 | 464 | 9/27/2022 | |
1.2.0 | 466 | 9/25/2022 | |
1.1.3-rc | 274 | 9/15/2022 | |
1.1.2-rc | 502 | 9/14/2022 | |
1.1.1-rc | 122 | 9/13/2022 | |
1.1.0-rc | 140 | 9/13/2022 | |
1.0.1-rc | 121 | 9/6/2022 | |
1.0.0-rc | 118 | 9/5/2022 |
Caching properties in viewmodels so we can properly trigger propertychanged between model updates.