Skip to content

Commit

Permalink
Add Xamarin.Forms and Avalonia support for ViewModelBase.IsInDesignMode
Browse files Browse the repository at this point in the history
  • Loading branch information
yariker committed Aug 28, 2022
1 parent 228bb43 commit d7aa4cc
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 26 deletions.
1 change: 1 addition & 0 deletions MvvmMicro.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Avalonia/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Bugaria/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Mvvm/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Reentrancy/@EntryIndexedValue">True</s:Boolean>
Expand Down
26 changes: 21 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,39 @@
# <img src="src/MvvmMicro/icon.png" alt="logo" width="32" height="32" /> MvvmMicro
<a href="https://www.nuget.org/packages/MvvmMicro" target="_blank"><img alt="Nuget" src="https://img.shields.io/nuget/v/MvvmMicro" /></a>

A clean and lightweight MVVM framework for WPF, UWP and .NET Standard 2.0 inspired by MVVM Light Toolkit.
A lightweight MVVM framework for .NET inspired by [MVVM Light Toolkit](https://github.com/lbugnion/mvvmlight).

## Goals

- No third party dependencies, such as `CommonServiceLocator` or `System.Windows.Interactivity`.
- Avoid [feature kreep](https://en.wikipedia.org/wiki/Feature_creep) – only core MVVM types and services are included, such as `RelayCommand`, `AsyncRelayCommand`, `ObservableObject` and a simple `IMessenger`.
- No feature kreep – only core MVVM types and services are included, such as `RelayCommand`, `AsyncRelayCommand`,
`ObservableObject`, and a simple `IMessenger`.

## Supported platforms

- .NET Framework 4.6.2 & .NET 5.0 (WPF)
- Universal Windows Platform (UWP)
- .NET Standard 2.0
- .NET Standard 2.0 (Xamarin.Forms, Avalonia, MAUI, etc.)

## Installation

The primary way to use MvvmMicro is by adding the [nuget](https://www.nuget.org/packages/MvvmMicro) package to your project:
```
Install-Package MvvmMicro
```

## Classes and interfaces
Here's an overview of classes and interfaces exposed by the library:
## Overview

| Type | Description |
| ----- | ----------- |
| ObservableObject | The base class for objects that support property change notification. |
| ViewModelBase | The base class for view models with the _Messenger_ and _IsInDesignMode_ properties. |
| Messenger | A service for sending and receiving messages, typically between view models and views. |
| RelayCommand,<br/>RelayCommand\<T\> | An _ICommand_ implementation based on a synchronous delegate for _Execute_ and _CanExecute_. |
| AsyncRelayCommand,<br/>AsyncRelayCommand\<T\> | An _ICommand_ implementation based on an asynchronous delegate for _Execute_ with cancellation support. |

![Class diagram](src/MvvmMicro/Diagrams/ClassDiagram.png)

## License

Code licensed under the [MIT License](LICENSE).
34 changes: 20 additions & 14 deletions src/MvvmMicro/Diagrams/ClassDiagram.cd
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,11 @@
<Lollipop Position="0.2" />
</Class>
<Class Name="MvvmMicro.Messenger">
<Position X="0.5" Y="3" Width="2" />
<Position X="0.5" Y="2.75" Width="2" />
<Members>
<Field Name="_actionInvoker" Hidden="true" />
<Field Name="_callbackListPool" Hidden="true" />
<Field Name="_registry" Hidden="true" />
<Method Name="Publish" Hidden="true" />
<Method Name="Subscribe" Hidden="true" />
<Method Name="Unsubscribe" Hidden="true" />
</Members>
<NestedTypes>
<Class Name="MvvmMicro.Messenger.Channel" Collapsed="true">
Expand All @@ -30,7 +28,7 @@
</Class>
</NestedTypes>
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAEAAEAAIAAAAAAiAAAAQAAAAAAAAAA=</HashCode>
<HashCode>AAAAAAAQAAAAAAEAAEAAIAAAAAAhAAAAAAAAAAAAEAA=</HashCode>
<FileName>Messenger.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.192" />
Expand All @@ -44,20 +42,24 @@
<Lollipop Position="0.2" />
</Class>
<Class Name="MvvmMicro.ViewModelBase">
<Position X="3" Y="3" Width="2" />
<Position X="3" Y="2.75" Width="2" />
<Members>
<Method Name="GetIsInDesignMode" Hidden="true" />
<Method Name="GetIsInDesignMode_Avalonia" Hidden="true" />
<Method Name="GetIsInDesignMode_UWP" Hidden="true" />
<Method Name="GetIsInDesignMode_WPF" Hidden="true" />
<Method Name="GetIsInDesignMode_XamarinForms" Hidden="true" />
<Field Name="IsInDesignModeLazy" Hidden="true" />
<Method Name="ViewModelBase" Hidden="true" />
</Members>
<InheritanceLine Type="MvvmMicro.ObservableObject" FixedFromPoint="true">
<Path>
<Point X="4" Y="2.497" />
<Point X="4" Y="3" />
<Point X="4" Y="2.75" />
</Path>
</InheritanceLine>
<TypeIdentifier>
<HashCode>AAAAAAAAABAAAAAAAAQAAAAAAASAAAAAAAAAAAAAAAA=</HashCode>
<HashCode>AAAAAAAAAFAAAgAAAgQAAAAAAASAAAQAAAAAAAAAAAA=</HashCode>
<FileName>ViewModelBase.cs</FileName>
</TypeIdentifier>
</Class>
Expand All @@ -68,6 +70,7 @@
<Field Name="_execute" Hidden="true" />
<Method Name="CanExecute" Hidden="true" />
<Method Name="Execute" Hidden="true" />
<Method Name="RelayCommand" Hidden="true" />
</Members>
<TypeIdentifier>
<HashCode>AAAAAAAAAEAAAAQAAECAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
Expand All @@ -81,6 +84,7 @@
<Field Name="_execute" Hidden="true" />
<Method Name="CanExecute" Hidden="true" />
<Method Name="Execute" Hidden="true" />
<Method Name="RelayCommand" Hidden="true" />
</Members>
<TypeIdentifier>
<HashCode>AAAAAAAAAEAAAAQAAECAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
Expand All @@ -89,10 +93,11 @@
<Lollipop Position="0.2" />
</Class>
<Class Name="MvvmMicro.AsyncRelayCommand">
<Position X="5.75" Y="8" Width="2.75" />
<Position X="5.75" Y="7.75" Width="2.75" />
<Members>
<Field Name="_canExecute" Hidden="true" />
<Field Name="_execute" Hidden="true" />
<Method Name="AsyncRelayCommand" Hidden="true" />
<Method Name="CanExecute" Hidden="true" />
<Method Name="ExecuteAsync" Hidden="true" />
</Members>
Expand All @@ -103,10 +108,11 @@
<Lollipop Position="0.2" />
</Class>
<Class Name="MvvmMicro.AsyncRelayCommand&lt;T&gt;">
<Position X="9.25" Y="8" Width="2.75" />
<Position X="9.25" Y="7.75" Width="2.75" />
<Members>
<Field Name="_canExecute" Hidden="true" />
<Field Name="_execute" Hidden="true" />
<Method Name="AsyncRelayCommand" Hidden="true" />
<Method Name="CanExecute" Hidden="true" />
<Method Name="ExecuteAsync" Hidden="true" />
<Method Name="IAsyncCommand.ExecuteAsync" Hidden="true" />
Expand All @@ -119,7 +125,7 @@
<Lollipop Position="0.2" />
</Class>
<Class Name="MvvmMicro.AsyncCommandBase">
<Position X="7.5" Y="5.25" Width="2.75" />
<Position X="7.5" Y="4.75" Width="2.75" />
<Members>
<Field Name="_cancellationTokenSource" Hidden="true" />
<Field Name="_isExecuting" Hidden="true" />
Expand All @@ -132,19 +138,19 @@
<Interface Name="MvvmMicro.IMessenger">
<Position X="0.5" Y="0.75" Width="2" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAEAAAAAAAAACAAAAQAAAAAAAAAA=</HashCode>
<HashCode>AAAAAAAAAAAAAAAAAEAAAAAAAAABAAAAAAAAAAAAEAA=</HashCode>
<FileName>IMessenger.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="MvvmMicro.ICommand&lt;T&gt;">
<Position X="3" Y="5" Width="2" />
<Position X="3" Y="5.25" Width="2" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAQAAEAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>ICommand{T}.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="MvvmMicro.IAsyncCommand">
<Position X="0.5" Y="5" Width="2" />
<Position X="0.5" Y="5.25" Width="2" />
<TypeIdentifier>
<HashCode>AAAAAAAAQAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA=</HashCode>
<FileName>IAsyncCommand.cs</FileName>
Expand Down
4 changes: 2 additions & 2 deletions src/MvvmMicro/Diagrams/ClassDiagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 38 additions & 5 deletions src/MvvmMicro/ViewModelBase.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Yaroslav Bugaria. All rights reserved.

using System;
using System.Reflection;

namespace MvvmMicro;

Expand All @@ -26,8 +27,9 @@ public ViewModelBase(IMessenger messenger = null)
/// <summary>
/// Gets a value indicating whether the application is running in the context of a designer.
/// </summary>
/// <value><c>true</c> if a designer context was detected; otherwise, <c>false</c>.</value>
/// <remarks>
/// Supported for WPF and UWP targets only; otherwise, always returns <c>false</c>.
/// The following UI frameworks are supported: WPF, UWP, Xamarin.Forms, and Avalonia.
/// </remarks>
public static bool IsInDesignMode => IsInDesignModeLazy.Value;

Expand All @@ -37,17 +39,48 @@ public ViewModelBase(IMessenger messenger = null)
protected IMessenger Messenger { get; }

private static bool GetIsInDesignMode()
{
return GetIsInDesignMode_WPF() ??
GetIsInDesignMode_UWP() ??
GetIsInDesignMode_XamarinForms() ??
GetIsInDesignMode_Avalonia() ??
false;
}

private static bool? GetIsInDesignMode_WPF()
{
#if NETFRAMEWORK || NET5_0
// WPF.
var descriptor = System.ComponentModel.DependencyPropertyDescriptor.FromProperty(
System.ComponentModel.DesignerProperties.IsInDesignModeProperty, typeof(System.Windows.FrameworkElement));

return (bool)descriptor.Metadata.DefaultValue;
#elif WINDOWS_UWP
// UWP.
#else
return null;
#endif
}

private static bool? GetIsInDesignMode_UWP()
{
#if WINDOWS_UWP
return Windows.ApplicationModel.DesignMode.DesignModeEnabled;
#else
return false;
return null;
#endif
}

private static bool? GetIsInDesignMode_XamarinForms()
{
var design = Type.GetType("Xamarin.Forms.DesignMode, Xamarin.Forms.Core")?.GetProperty(
"IsDesignModeEnabled", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);

return design is bool value ? value : null;
}

private static bool? GetIsInDesignMode_Avalonia()
{
var design = Type.GetType("Avalonia.Controls.Design, Avalonia.Controls")?.GetProperty(
"IsDesignMode", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);

return design is bool value ? value : null;
}
}

0 comments on commit d7aa4cc

Please sign in to comment.