MvvmEssence 1.4.1
See the version list below for details.
dotnet add package MvvmEssence --version 1.4.1
NuGet\Install-Package MvvmEssence -Version 1.4.1
<PackageReference Include="MvvmEssence" Version="1.4.1" />
paket add MvvmEssence --version 1.4.1
#r "nuget: MvvmEssence, 1.4.1"
// Install MvvmEssence as a Cake Addin #addin nuget:?package=MvvmEssence&version=1.4.1 // Install MvvmEssence as a Cake Tool #tool nuget:?package=MvvmEssence&version=1.4.1
MvvmEssence
This is a .NET standard 2.0 library, can be used in WPF, Xamarin Forms and MAUI projects as well. To help the adoption of this library a sample MAUI application was added, the few existing unit tests could also help.
Usage
Define your ViewModel class as:
using Brain2CPU.MvvmEssence;
public class MyViewModel : ViewModelBase
In the XAML file do the binding in the usual way. In the ViewModel instead of the traditional way to declare a property used in binding or a command:
private DateTime _dateFrom = DateTime.Today;
public DateTime DateFrom
{
get => _dateFrom;
set
{
if (_dateFrom == value)
return;
_dateFrom = value;
NotifyPropertyChanged();
RefreshCommand.ChangeCanExecute();
}
private Xamarin.Forms.Command _refreshCommand;
public Xamarin.Forms.Command RefreshCommand =>
_refreshCommand ?? (_refreshCommand = new Command(Refresh, () => !IsBusy && DateFrom > DateTime.Now));
}
use the following:
public DateTime DateFrom
{
get => Get(defaultVal:DateTime.Today);
set => Set(value, RefreshCommand);
}
public RelayCommand RefreshCommand => Get(Refresh, () => !IsBusy && DateFrom > DateTime.Now);
with the same
private void Refresh() { ... }
ViewModelBase
will take care of the storage and notifications.
The Get
method used in the property definition must have specified the generic type or the default value.
The Set
method has an optional command list parameter, for commands that must update their CanExecute state based on the property value.
Set
supports a custom comparer too:
public DateTime DateTo
{
get => Get<DateTime>(); //will have the type's default value
set => Set(value, RefreshCommand, (d1, d2) => d1.Date == d2.Date);
}
The Get
method used in the command definition has a first parameter of type Action
or Action<T>
and an optional canExecute Func<bool>
parameter.
For the case of an asynchronous method servicing a command, instead of a fire-and-forget approach async void Handler()
you can use RelayCommandAsync
with a
proper async Task HandlerAsync()
. Keep in mind that this is a syntactic sugar, the execution of the method won't be awaited, so handle all exceptions inside the method!
The IsBusy
property setter will call RaiseCanExecuteChanged
for every command.
There is a Get
overload having a delegate parameter bool IsValid(object o)
, in this case every set
will trigger a validaton,
the global result is in the IsObjectValid
property, a collection of the names of the invalid properties is stored in InvalidFields
.
If a validation againts the default values are required you must call the InitializeObject()
method.
In order to help in situations where asynchronous initialization is required during the view model construction there is a virtual method InitializeAsync
called from the default constructor. Important: please pay attention to the fact that StartInitialization
is called before the child class
constructor is even started, so the auto-initialized constructor can be used only if the child constructor is empty or whatever initialization is done in it
will not affect the async initialization. Otherwise you should use the constructor with a boolean parameter and start the initialization in the child class.
The end of initialization can be observed using the IsInitialized
property or/and by subscribing to the OnInitialized
event.
ObservableCollectionEx
This class is not strictly required for the MVVM pattern but it is very useful in many situations. It extends ObservableCollection
restricting it to
observable items and allows temporary notification suppression and range operations (AddRange
, RemoveRange
).
The main addition though is that the OnCollectionChanged
event is triggered not only when the collection is changed (add/remove items) but
also when an observable property of any contained item is modified.
DiscoverComponents
Another addition to the package, used mainly to help component registration in the MAUI DI engine (check the sample app).
var discover = new DiscoverComponents(typeof(MauiProgram).Assembly,
type =>
{
if (type.Namespace.Equals("Sample.Views") && type.Name.EndsWith("Page"))
return ClassRegistrationOption.AsTransient;
if (type.Namespace.Equals("Services"))
return ClassRegistrationOption.AsSingleton;
return ClassRegistrationOption.Skip;
});
discover.RegisterItems(sd => builder.Services.AddSingleton(sd),
td => builder.Services.AddTransient(td),
(sc, si) => builder.Services.AddSingleton(si, sc),
(tc, ti) => builder.Services.AddTransient(ti, tc));
You can use the registration based on naming conventions, a selector method or explicitly marked classes with RegisterAsTransientAttribute
or RegisterAsSingletonAttribute
.
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 | 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 was computed. 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. |
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.