MorseCode.Mvvm 0.2.2

dotnet add package MorseCode.Mvvm --version 0.2.2
                    
NuGet\Install-Package MorseCode.Mvvm -Version 0.2.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MorseCode.Mvvm" Version="0.2.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MorseCode.Mvvm" Version="0.2.2" />
                    
Directory.Packages.props
<PackageReference Include="MorseCode.Mvvm" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MorseCode.Mvvm --version 0.2.2
                    
#r "nuget: MorseCode.Mvvm, 0.2.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package MorseCode.Mvvm@0.2.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=MorseCode.Mvvm&version=0.2.2
                    
Install as a Cake Addin
#tool nuget:?package=MorseCode.Mvvm&version=0.2.2
                    
Install as a Cake Tool

Building blocks for view models written in a functional reactive style on SodaFlow.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  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.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 is compatible.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
0.2.2 37 10/2/2026
0.2.1 39 10/1/2026
0.2.0 37 9/30/2026
0.1.0 60 9/30/2026 0.1.0 is deprecated because it has critical bugs.

0.2.2

The registrations of a view model now stay open while the constructor that
Construct calls runs, and they close when that constructor returns. In 0.2.1
and before, they closed before the constructor ran, so a registration in the
constructor of a view model failed. Now the constructor of a view model that
derives from ViewModelBase can add its own subscriptions to IOutput, and Dispose
releases them with the others. A registration after the constructor returns
still fails with an InvalidOperationException.

Dispose on the base now releases the registrations made so far, also when it
runs inside the constructor or on a different thread, and it closes the
registrations. If the constructor throws, the base releases the registrations
made so far, and the exception goes to the caller unchanged. If a registration
also throws as it is released, the caller gets an AggregateException that holds
the exception of the constructor first. The message of the
InvalidOperationException for a late registration now says that the
registrations are closed. No signature changed.

0.2.1

ViewModelBase is no longer sealed. A view model can derive from it: its
constructor gives the base that Construct gives to the new protected
constructor, ViewModelBase(ViewModelBase), and the view model then is an
IViewModel with no members of its own for that. The protected constructor takes
the registrations of that base, and Dispose on the view model releases them.

One view model only can take a base. A second call to the protected constructor
with the same base fails with an InvalidOperationException, because two view
models cannot own the same registrations. A null base fails with an
ArgumentNullException.

Dispose now calls GC.SuppressFinalize, so a view model that derives from
ViewModelBase and adds a finalizer does not have to implement IDisposable again.

A view model that keeps the base in a field, as in 0.2.0, works as before. This
release adds to the API and changes nothing that a view model built against
0.2.0 uses.

0.2.0

This package now targets net472, net6.0, and netstandard2.0, and not net10.0
only. The behavior is the same on every target.

Breaking change: ViewModelBase.CreateBase takes a
StageContinuation<IOutput, Constructor<ViewModelBase>, TResult>, and not an
IConstruct<ViewModelBase>. MorseCode.StagedConstruction 0.2.0 replaced the
IConstruct interface with the Constructor class, and this package depends on
0.2.0 or a later 0.2.x. Change the signature of each view model that calls
CreateBase, and compile it again.

CreateBase now refuses a null continuation with an ArgumentNullException, as it
refuses a null scheduler.

The dependency on MorseCode.StagedConstruction now has the next minor version as
its ceiling while the version is below 1.0.0, and not 1.0.0. MorseCode.Mvvm
0.1.0 admits MorseCode.StagedConstruction 0.2.0, and does not work with it. Do
not use MorseCode.Mvvm 0.1.0 with MorseCode.StagedConstruction 0.2.0 or later.

0.1.0

The first release. It contains ViewModelBase, the IViewModel interface, and the
Disposable helpers that ViewModelBase uses.

A view model that SodaFlow builds holds subscriptions into the graph: one for
each bindable value, command, and listener that it exposes. The view model must
release all of them when it is disposed, and must not read a part of itself
before that part exists.

ViewModelBase does both, with MorseCode.StagedConstruction. A view model's
static Create method calls ViewModelBase.CreateBase. The base gives it an
ViewModelBase.IOutput to register each subscription with, and its
BindableFactory registers each bindable value and action that it makes. When
the view model calls Construct, the base seals the registrations and gives
itself to the view model's constructor. The view model keeps it and sends its
Dispose and PropertyChanged to it:

 public static CounterViewModel Create(IBindingScheduler bindingScheduler) =>
     Transaction.Run(() =>
         ViewModelBase.CreateBase(bindingScheduler, (output, construct) =>
         {
             StreamSink<Unit> increments = Stream.CreateSink<Unit>();
             Cell<int> count = increments.Accum(0, (_, total) => total + 1);

             IOneWayBindableValue<int> countValue = output.BindableFactory.CreateOneWay(count);
             IBindableAction increment = output.BindableFactory.CreateBindableAction(increments);

             return construct.Construct(viewModelBase =>
                 new CounterViewModel(viewModelBase, countValue, increment));
         }));

Dispose releases each registration one time, the last registration first,
listeners and disposables together. Thus, a registration stops before the
registrations that it uses. A second call does nothing, also when two threads
call at the same time. An exception from one registration does not stop the
others.

A registration after Construct fails with an InvalidOperationException, and so
does a second Construct. Thus, nothing that the construction made can be left
out of Dispose, and nothing can be added to it later. A null registration fails
at the call, with an ArgumentNullException.

AddListener keeps a reference to the listener. Thus, the garbage collector does
not remove a weak listener while the view model is alive.

PropertyChanged never occurs and keeps no handler. The properties of a view
model do not change, and each bindable value sends its own notifications. The
event is there for INotifyPropertyChanged, because WPF watches a binding source
without that interface through a PropertyDescriptor, which keeps the source
alive.

Disposable.Composite, Disposable.FromAction, and Disposable.Empty are public
too. Composite disposes a fixed list as one, in the order of the list, with the
once-only and exception behavior above. FromAction calls an action at the first
Dispose only. Empty does nothing.

This package is pre-1.0. Its API can change in a minor version until 1.0.0.

---

About this package

Building blocks for view models written in a functional reactive style on
SodaFlow. It is part of the MorseCode toolkit, which holds the conventions that
MorseCode Software builds its own applications with.

Targets net472, net6.0, and netstandard2.0. Depends on SodaFlow.Bindable.ObjectModel and
MorseCode.StagedConstruction.

Source: https://github.com/MorseCode-Software/MorseCode.Toolkit