FreshMvvm is designed to be easy and simple. So getting started is also fairly simple.
Step 1. Start new project
Start a new Xamarin.Forms Project using Portable Class Libraries.
Step 2. Obtain FreshMvvm from Nuget
Obtain FreshMvvm from Nuget by searching for FreshMvvm, make sure to do this on your Xamarin.Forms PCL project.
Step 3. Create QuoteList Page
Once you’ve got the packages you can then create your first Page and PageModel. In the Xamarin.Forms PCL project, let’s create a QuoteListPage.xaml and corresponding QuoteListPageModel.cs.
QuoteListPage.xaml
<?xml version="1.0" encoding="UTF-8"?> <BasePage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="FreshMvvmSampleApp.QuoteListPage"> <BasePage.Content> <ListView ItemsSource="{Binding Quotes}" SelectedItem="{Binding SelectedQuote}" > <ListView.ItemTemplate> <DataTemplate> <TextCell Text="{Binding Total}" Detail="{Binding CustomerName}"></TextCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </BasePage.Content> </BasePage>
QuoteListPageModel.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | [ImplementPropertyChanged] // uses fody for property changed public class QuoteListPageModel : FreshBasePageModel { IDatabaseService _databaseService; public QuoteListPageModel (IDatabaseService databaseService) // injected from IOC { _databaseService = databaseService; } public ObservableCollection<Quote> Quotes { get; set; } public override void Init (object initData) { Quotes = new ObservableCollection<Quote> (_databaseService.GetQuotes ()); } // Methods are automatically wired up to page protected override void ViewIsAppearing (object sender, System.EventArgs e) { CoreMethods.DisplayAlert ("Page is appearing", "", "Ok"); base.ViewIsAppearing (sender, e); } protected override void ViewIsDisappearing (object sender, System.EventArgs e) { base.ViewIsDisappearing (sender, e); } // This is called when a page id pop'd public override void ReverseInit (object value) { var newContact = value as Quote; if (!Quotes.Contains (newContact)) { Quotes.Add (newContact); } } public Command AddQuote { get { return new Command (async () => { await CoreMethods.PushPageModel<QuotePageModel> (); }); } } Quote _selectedQuote; public Quote SelectedQuote { get { return _selectedQuote; } set { _selectedQuote = value; if (value != null) QuoteSelected.Execute (value); } } public Command<Quote> QuoteSelected { get { return new Command<Quote> (async (quote) => { await CoreMethods.PushPageModel<QuotePageModel> (quote); }); } } |
Step 4. Create Quote Page
We will also need a page which shows the details of a quote. So we can create a QuotePage.xaml and a corresponding QuotePageModel.cs.
QuotePage.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?xml version="1.0" encoding="UTF-8"?> <BasePage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="FreshMvvmSampleApp.QuotePage"> <BasePage.Content> <StackLayout Padding="15"> <Label Text="Quote Amount" ></Label> <Entry Text="{Binding Quote.Total}"></Entry> <Label Text="Customer Name" ></Label> <Entry Text="{Binding Quote.CustomerName}"></Entry> <Button Text="Save" Command="{Binding SaveCommand}"></Button> <BoxView HeightRequest="30"></BoxView> <Button Text="Test Modal" Command="{Binding TestModal}"></Button> </StackLayout> </BasePage.Content> </BasePage> |
QuotePageModel.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | [ImplementPropertyChanged] public class QuotePageModel : FreshBasePageModel { IDatabaseService _databaseService; public Quote Quote { get; set; } public QuotePageModel (IDatabaseService databaseService) { _databaseService = databaseService; } public override void Init (object initData) { Quote = initData as Quote; if (Quote == null) Quote = new Quote (); } public Command SaveCommand { get { return new Command (async () => { _databaseService.UpdateQuote (Quote); await CoreMethods.PopPageModel (); }); } } public Command TestModal { get { return new Command (async () => { await CoreMethods.PushPageModel<ModalPageModel> (null, true); }); } } } |
Step 5. Setup Navigation
You have the options of using a built-in navigation or implement your own.
With the built in navigation items you have the options of:
-
FreshNavigationContainer – Which is a basic navigation with push and pop
-
FreshMasterDetailNavigationContainer – Use for a master detail style app
-
FreshTabbedNavigationContainer – User for a tabbed style app
-
For some thing more complex you can implement IFreshNavigationService
In this sample we can use a tabbed style app. In your Xamarin.Forms PCL open your App.cs and in the constructor add the following code.
1 2 3 4 5 | var tabbedNavigation = new FreshTabbedNavigationContainer (); tabbedNavigation.AddTab<ContactListPageModel> ("Contacts", null); MainPage = tabbedNavigation; |
And that’s it, we now have made the first steps to implementing FreshMvvm. If you wanted a different Navigation style then you could use one of the other types of built in Navigation or even implement your own.
The great sample project similar to this can be found in the sample directory on the project.
https://github.com/rid00z/FreshMvvm
Just some minor feedback.
I was confused with the BasePage. I thought for whateve reason this would be in the FreshMvvm namespace…now that I think about it that is just silly of me.
Second, at the end you have this:
tabbedNavigation.AddTab (“Contacts”, null);
But I believe you should be passing in the QuoteListPageModel.
Cheers!
Michael, working with FreshMvvm I am having difficulty getting the ReverseInit method to work. It appears that the private field PageModelCoreMethods._pageModel is never set and is required for ReverseInit to fire. Is _pageModel set somewhere using reflection which I have not found? Or is this a bug?
I’m very much enjoy your Mvvm implementation. Thanks,
Mike
Hi Michael,
Great post, and your framework looks really easy to use.
In the GitHub README you give your reasons for rolling your own framework rather than using MvvmCross. I can understand your reasons, though one of useful features it provides is the Plugin framework – it would be great to see a future post that shows a cross platform plugin which uses your IoC container for the platform specific implementation.
Also, did you take a look at MvvmLight? Perhaps that wasn’t ready for XF when you started looking for a framework?
Thanks , Jason