All Projects → aspnetde → Mvvmnano

aspnetde / Mvvmnano

Licence: mit
The small and smart MVVM framework made with ❤ for Xamarin.Forms.

Projects that are alternatives of or similar to Mvvmnano

Restaurant App
Restaurant App 🍔 is a sample open-source e-Commerce 🛒 application for ordering foods, powered by polyglot microservices architecture and cross-platform development including mobile and web
Stars: ✭ 471 (+788.68%)
Mutual labels:  xamarin, mvvm, xamarin-forms
Reactiveui
An advanced, composable, functional reactive model-view-viewmodel framework for all .NET platforms that is inspired by functional reactive programming. ReactiveUI allows you to abstract mutable state away from your user interfaces, express the idea around a feature in one readable place and improve the testability of your application.
Stars: ✭ 6,709 (+12558.49%)
Mutual labels:  xamarin, mvvm, xamarin-forms
Reactivemvvm
Cross-platform ReactiveUI sample app built for a talk at MSK .NET conf.
Stars: ✭ 94 (+77.36%)
Mutual labels:  xamarin, mvvm, xamarin-forms
Caliburn.micro
A small, yet powerful framework, designed for building applications across all XAML platforms. Its strong support for MV* patterns will enable you to build your solution quickly, without the need to sacrifice code quality or testability.
Stars: ✭ 2,404 (+4435.85%)
Mutual labels:  xamarin, mvvm, xamarin-forms
Mvvmcross
The .NET MVVM framework for cross-platform solutions, including Xamarin.iOS, Xamarin.Android, Windows and Mac.
Stars: ✭ 3,594 (+6681.13%)
Mutual labels:  xamarin, mvvm, xamarin-forms
Xamarin Demos
This repository contains the Syncfusion Xamarin UI control’s samples and the guide to use them.
Stars: ✭ 218 (+311.32%)
Mutual labels:  xamarin, mvvm, xamarin-forms
Xaml Code Experiences
A collection of the experiences I have collected during days of Xamarin and Wpf, while following the MVVM design pattern.
Stars: ✭ 114 (+115.09%)
Mutual labels:  xamarin, mvvm, xamarin-forms
Professionalcsharp7
Code samples for the book Professional C# 7 and .NET Core 2.0 (with updates for 2.1), Wrox Press
Stars: ✭ 403 (+660.38%)
Mutual labels:  xamarin, mvvm, xamarin-forms
Mvvmlight
The main purpose of the toolkit is to accelerate the creation and development of MVVM applications in Xamarin.Android, Xamarin.iOS, Xamarin.Forms, Windows 10 UWP, Windows Presentation Foundation (WPF), Silverlight, Windows Phone.
Stars: ✭ 973 (+1735.85%)
Mutual labels:  xamarin, mvvm, xamarin-forms
Facialrecognitionlogin
An iOS and Android app that uses facial recognition to enhance the security of a login page. Built using Xamarin.Forms and Microsoft Cognitive Services.
Stars: ✭ 46 (-13.21%)
Mutual labels:  xamarin, xamarin-forms
Realm Dotnet
Realm is a mobile database: a replacement for SQLite & ORMs
Stars: ✭ 927 (+1649.06%)
Mutual labels:  xamarin, xamarin-forms
Aprende Xamarin
Aprende C# y Xamarin desde cero! Auto-guiado y a tu ritmo. Dale ⭐si te gusta. Documentación disponible en el Wiki (website)
Stars: ✭ 53 (+0%)
Mutual labels:  xamarin, xamarin-forms
Xtoolkit.whitelabel
Modular MVVM framework for fast creating powerful cross-platform applications with Xamarin.
Stars: ✭ 22 (-58.49%)
Mutual labels:  xamarin, mvvm
Brainpowerapp
A visual memory training game, a mobile game made with Xamarin for both Android and IOS .
Stars: ✭ 17 (-67.92%)
Mutual labels:  xamarin, xamarin-forms
Xamarin Forms Walkthrough
Mobile App Walkthrough created with Xamarin.Forms
Stars: ✭ 46 (-13.21%)
Mutual labels:  xamarin, xamarin-forms
Essential Ui Kit For Xamarin.forms
Free and beautiful XAML template pages for Xamarin.Forms apps.
Stars: ✭ 780 (+1371.7%)
Mutual labels:  xamarin, xamarin-forms
Csla
A home for your business logic in any .NET application.
Stars: ✭ 865 (+1532.08%)
Mutual labels:  xamarin, xamarin-forms
Formswpflive
Live XAML development for Xamarin Forms Apps using WPF Backend.
Stars: ✭ 14 (-73.58%)
Mutual labels:  xamarin, xamarin-forms
Tabstrip
Tab Strip control for Xamarin.Forms
Stars: ✭ 25 (-52.83%)
Mutual labels:  xamarin, xamarin-forms
Xamarin.forms.artoolkit
Augmented Reality Toolkit for Xamarin Forms
Stars: ✭ 14 (-73.58%)
Mutual labels:  xamarin, xamarin-forms

MvvmNano

The small and smart MVVM framework made with ❤ for Xamarin.Forms.

Build Status NuGet Package
Build status NuGet version
  1. Manifesto
  2. Download
  3. Demo
  4. Getting started
  5. Data Binding
  6. Navigation
  7. Dependency Injection
  8. Messaging
  9. Cleaning up
  10. XAML Support
  11. MasterDetailPage

Manifesto

  1. Each View (aka Page) must have its own View Model.
  2. Views know their View Models, but not vice versa: View Models never know their Views.
  3. Therefore navigation works from View Model to View Model only, without involving the View.
  4. When navigating, passing complex objects along must be possible.
  5. There should be no limits in how to present Views.
  6. View Models must be easily testable, so Dependency Injection is a basic prerequisite.
  7. Both Views and View Models must be easy to clean up.

Download

Install-Package MvvmNano.Forms

Demo

C#: If you are looking for a C# demo, just download this repo and take a look at the demo app which can be found within the /demo folder. Note: It's not using the NuGet packages.

F#: ixmrm01 ported the current C# demo to F# and was kind enough to share it. You can take a look at it here: https://github.com/ixmrm01/MvvmNanoDemo

Getting started

Preliminary remarks

  • MvvmNano ships as three .netstandard 2.0 libraries (MvvmNano.Core, MvvmNano.TinyIoC, and MvvmNano.Forms) and also provides three Portable Class Libraries (PCL) with profile 259 (MvvmNano.Core, MvvmNano.Ninject, and MvvmNano.Forms). NuGet will detect which libraries are needed based on your project type.
  • MvvmNano.Forms references Xamarin.Forms
  • MvvmNano.Ninject references Portable.Ninject
  • MvvmNano.Core does not have and external dependency

Add the NuGet package

You can add MvvmNano easily via NuGet:

Install-Package MvvmNano.Forms

Important: Add it to your Xamarin.Forms library as well as to your native app projects, so NuGet can resolve the right assemblies of the dependencies Xamarin.Forms and Portable.Ninject/.TinyIoC on each target (for example PCL, Xamarin.iOS, Xamarin.Android).

If you want to use our default IoC container, we provide one for .netstandard2.0 and PCL259. The default container for a PCL project is:

Install-Package MvvmNano.Ninject

For .netstandard2.0 projects:

Install-Package MvvmNano.TinyIoC

Add your first View Model and its Page

Your View Model needs to inherit from MvvmNanoViewModel<TNavigationParameter> or MvvmNanoViewModel. Let's start with the latter and thereby without a parameter.

public class LoginViewModel : MvvmNanoViewModel
{
    // ...
}

Now add the Page. Note that by convention it needs to be named after your View Model, except for the ViewModel suffix (so LoginViewModel becomes LoginPage). You also need to inherit from MvvmNanoContentPage<TViewModel>.

public class LoginPage : MvvmNanoContentPage<LoginViewModel>
{
    // ...
}

Set up your App class

Each Xamarin.Forms app has an entry point – a class called App which is derived from Application. Change that base class to MvvmNanoApplication.

Next you are asked to implement the method GetIoCAdapter() which is expected to return an implementation of IMvvmNanoIoCAdapter. Just go with our default choice (MvvmNano.Ninject in a PCL project, which uses Portable.Ninject, MvvmNano.TinyIoC in a .netstandard2.0 project), or go with your own.

You also want to tell your application the first Page and View Model which should be used when the app gets started for the first time. Put this setup inside of OnStart(), but don't forget to call base.OnStart(). This is important in order to set up the Presenter correctly (for more on that see below).

public class App : MvvmNanoApplication
{
    protected override void OnStart()
    {
        base.OnStart();

		SetUpMainPage<LoginViewModel>();
    }
    
    protected override IMvvmNanoIoCAdapter GetIoCAdapter()
	{
	    return new MvvmNanoNinjectAdapter();
	}
}

That's it!

If you now build and run your app(s), you'll see your first Page which is running with it's View Model behind. Nothing spectacular so far, but the fun is just getting started.

Data Binding

Xamarin.Forms comes with really powerful data binding features which you're fully able to leverage with MvvmNano, so we are not reinventing the wheel here.

NotifyPropertyChanged()

MvvmNano View Models implement INotifyPropertyChanged and offer a small helper method called NotifyPropertyChanged() (without the leading I).

private string _username;
public string Username
{
    get { return _username; }
    set
    {
        _username = value;
        NotifyPropertyChanged();
        NotifyPropertyChanged("IsFormValid");
    }
}

As you can see, NotifyPropertyChanged() can be called with and without the name of the property it should be notifying about. If you leave it out, it will automatically use the name of the property you're calling it from.

(Scared from so much boilerplate code? Take a look at Fody PropertyChanged.)

BindToViewModel()

This is a small helper method baked in to MvvmNanoContentPage, which makes binding to your View Model a no-brainer when writing your views (pages) in code:

var nameEntry = new Entry
{
    Placeholder = "Your name"
};

BindToViewModel(nameEntry, Entry.TextProperty, x => x.Username);

Commands

Xamarin.Forms supports ICommand, and so does MvvmNano.

View Model:

public MvvmNanoCommand LogInCommand
{
	get { return new MvvmNanoCommand(LogIn); }
}

private void LogIn()
{
	// ...
}

Page:

BindToViewModel(loginButton, Button.CommandProperty, x => x.LogInCommand);

Commands with parameters

View Model:

public MvvmNanoCommand<string> LogInCommand
{
    get { return new MvvmNanoCommand<string>(LogIn); }
}

private void LogIn(string userName)
{
	// ...
}

Page:

BindToViewModel(loginButton, Button.CommandProperty, x => x.LogInCommand);
BindToViewModel(loginButton, Button.CommandParameterProperty, x => x.Username);

Navigation

Navigation works from View Model to View Model only, not involving the View aka Page directly. Instead all work is delegated to a central Presenter, which is responsible for creating the Page, its View Model and also passing a parameter, if specified.

This way you can keep your application independent from the UI implementation – if you ever have to switch to Xamarin.iOS or Xamarin.Android, in parts or even completely, you don't have to throw your View Models away.

Navigation without parameter

NavigateTo<AboutViewModel>();

Navigates to AboutViewModel without passing a parameter.

Navigation with a parameter

Let's say you want to get a parameter of the type Club each time your View Model is being called. Then you have to derive from MvvmNanoViewModel<TViewModel> and make TViewModel Club.

public class ClubViewModel : MvvmNanoViewModel<Club>
{
    public override void Initialize(Club parameter)
    {
        // ...
    }
}

Overriding the Initialize() method will now make that Club being passed available after the View Model is being created.

To actually pass that parameter, navigate to your ClubViewModel from the calling View Model as follows:

NavigateTo<ClubViewModel, Club>(club);

Opening Pages modally or in a completely customized fashion

The default presenter coming with MvvmNano will push a page to the existing navigation stack. But you are completely free to customize that, so you can define on a per-View Model basis how its view should be presented (maybe displayed modally or rendered in a completely different way).

A custom presenter could look like this:

public class DemoPresenter : MvvmNanoFormsPresenter
{
    public DemoPresenter(Application app) : base(app)
    {
    }

    protected override void OpenPage(Page page)
    {
        if (page is AboutPage)
        {
            Device.BeginInvokeOnMainThread(async () =>
                await CurrentPage.Navigation.PushModalAsync(new MvvmNanoNavigationPage(page)
            ));

            return;
        }

        base.OpenPage(page);
    }
}

In order to pass every navigation request through it, you have register it within your App class:

protected override void SetUpPresenter()
{
    MvvmNanoIoC.RegisterAsSingleton<IPresenter>(
        new DemoPresenter(this)
    );
}

Dependency Injection

Having a Initialize() or Initialize(TNavigationParameter parameter) method in your View Model comes with a benefit: the constructor is still free for parameters being automatically injected.

We're not inventing the wheel here neither, because the portable version of Ninject does a fabolous job for us behind the scenes.

In front of it there is a small static helper class called MvvmNanoIoC, which provides the following methods for registering dependencies:

  • MvvmNanoIoC.Register<TInterface, TImplementation>()
  • MvvmNanoIoC.RegisterAsSingleton<TInterface, TImplementation>()
  • MvvmNanoIoC.RegisterAsSingleton<TInterface>(TInterface instance)
  • MvvmNanoIoC.Resolve<TInterface>()

Sample: Registering a dependency

public class App : MvvmNanoApplication
{
    protected override void OnStart()
    {
        base.OnStart();

        SetUpDependencies();
    }

    private static void SetUpDependencies()
    {
        MvvmNanoIoC.Register<IClubRepository, MockClubRepository>();
    }
}

Sample: Constructor Injection

public class WelcomeViewModel : MvvmNanoViewModel
{
    public List<Club> Clubs { get; private set; }

    public WelcomeViewModel(IClubRepository clubs)
    {
        Clubs = clubs.All();
    }
}

PS: Usually you won't need the Resolve<TInterface>() method, because constructor injection works out of the box.

Using another IoC Container than Ninject

If you want to use another IoC Container, just implement IMvvmNanoIoCAdapter and return an instance of this implementation in your App's class GetIoCAdapter() method.

Messaging

This is very opinionated and certainly optional, but the official interface for messaging within Xamarin.Forms seems a bit odd. See more about it here.

The solution of IMessenger presented in that blog post comes with MvvmNano and is automatically registered in MvvmNanoApplication.

Inject IPresenter to your View Model

public class MyViewModel : MvvmNanoViewModel
{
    private readonly IMessenger _messenger;

    public WelcomeViewModel(IMessenger messenger)
    {
        _messenger = messenger;
    }
}

Define your message

public class AlbumCreatedMessage : IMessage
{
    public readonly Album Album;

    public AlbumCreatedMessage(Album album)
    {
        Album = album;
    }
}

Send it around

var album = new Album
{
    Id = Guid.NewGuid(),
    Title = "Hello World"
};

_messenger.Send(new AlbumCreatedMessage(album));

Subscribe to it

_messenger.Subscribe<AlbumCreatedMessage>(this, AlbumAdded);

private void AlbumAdded(object sender, AlbumCreatedMessage message)
{
    // Do something
}

When you're done, unsubscribe

_messenger.Unsubscribe<AlbumCreatedMessage>(this);

Cleaning up

Cleaning up your View Models and your Views aka Pages is a must in order to prevent memory leaks. Read more about it here. Unfortunately Xamarin doesn' think that way, so their whole Xamarin.Forms framework lacks IDisposable implementations.

MvvmNano fixes that. Both MvvmNanoViewModel and MvvmNanoContentPage implement IDisposable, so you can use the Dispose() method in both to detach event handlers, dispose "heavy resources" such as images etc.

Important: In order to get that Dispose() method actually called, you must use MvvmNanoNavigationPage instead of the framework's default Navigationpage. It takes care of calling Dispose() at the right time whenever a Page is being removed from the stack.

XAML Support

XAML is fully supported, take a look at the demo or these snippets.

View Model:

public class ClubViewModel : MvvmNanoViewModel<Club>
{
    private string _name;
    public string Name
    {
        get { return _name; }
        private set { _name = value; NotifyPropertyChanged(); }
    }

    private string _country;
    public string Country
    {
        get { return _country; }
        private set { _country = value; NotifyPropertyChanged(); }
    }

    public override void Initialize(Club parameter)
    {
        Name = parameter.Name;
        Country = parameter.Country;
    }
}

Page:

<?xml version="1.0" encoding="UTF-8"?>
<pages:MvvmNanoContentPage xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:pages="clr-namespace:MvvmNano.Forms"
    xmlns:vm="clr-namespace:MvvmNanoDemo"
    x:Class="MvvmNanoDemo.ClubPage"
    x:TypeArguments="vm:ClubViewModel"
    Title="{Binding Name}">
    <ContentPage.Content>
        <StackLayout>
            <Label Text="{Binding Country}" />
        </StackLayout>
    </ContentPage.Content>
</pages:MvvmNanoContentPage>

Master Detail Page

Master detail pages are supported in MvvmNano, its a page type that contains a fly out menu (master) and page area (detail). The master is typically populated with a listview or something similiar to chose the detail from.

Create a page that inherits from the MvvmNanoDefaultMasterDetailPage and a corresponding view model. You can add details with the AddDetailData<TViewModel>(MvvmNanoMasterDetailData data) method available in your master detail page. Information about each detail are stored in a MvvMNanoMasterDetailData, which you can inherit from and add additional properties to. You can use these properties to present additional informations in the master area.

The MvvmNanoDefaultMasterDetailPage is using a ListView to display all available details. You can override DataTemplate GetItemTemplate() to create your own DataTemplate or override the Page CreateMasterPage() to add a header, footer or embed the ListView in a view. An example for that can be found in the Demo.Pages.MasterPage.cs.

Create your own master detail layout

If you decide to create your complete own layout however, the MvvmNanoMasterDetailPage provides multiple methods to hook up your layout. Use the MvvmNanoMasterDetailPage to inherit from, instead of the MvvmNanoDefaultMasterDetailPage in this case.

Override Page CreateMasterPage() and return your own layout that will be used in the master area. Override void DetailDataAdded<TViewModel>(MvvmNanoMasterDetailData detailData) to execute some logic when a new detail data item is added. All added items are available in the ObservableCollection<MvvmNanoMasterDetailData> MasterDetails.

You can call void SetDetail(Type viewModelType) or void SetDetail(MvvmNanoMasterDetailData data) to present a new page in the detail area. MvvmNano will take care of disposing the old page, creating the new view and viewmodel and hook up the binding context. After a new detail is set, void DetailSet(MvvmNanoMasterDetailData lastDetailData, MvvmNanoMasterDetailData newDetailData, Page page) is called. You can override that aswell, for example to highlight the current detail in the master area.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].