Triggered by a stackoverflow question I thought I'd try to explain that a ViewModel is just a Model for a View.
I'm not sure if I succeeded or not... but at least I got a chance to demo an iPad app - and I got a chance to talk about the very lovely but underused MvxView
The code is at: https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-32-ViewModels
The excellent N+1 index is at:
Friday, June 28, 2013
NDC2013 Mobile Mvvm and Xamarin talks
I really enjoyed my few days in Oslo - the NDC team really know how to throw a good conference and a good party - including some really great speakers (not me - the others!) and including 'continuous delivery' of food :)
My talk's now available on: http://vimeo.com/68375201 - and embedded below.
I'll be watching lots of others too - e.g. I just enjoyed watching Andy Hunt's talk on Agile. But for mobile and Mvvm, others to watch out for are:
For a full list for all of NDC2013 - there are a *lot* of great sessions - see http://vimeo.com/ndcoslo/
Stuart Lodge: Sharing C# across Windows, Android and iOS using MvvmCross from NDCOslo on Vimeo.
My talk's now available on: http://vimeo.com/68375201 - and embedded below.
I'll be watching lots of others too - e.g. I just enjoyed watching Andy Hunt's talk on Agile. But for mobile and Mvvm, others to watch out for are:
- Craig's intros to Xamarin.Android and Xamarin.iOS - http://vimeo.com/68378928 and http://vimeo.com/68383292
- Chris's talk through the Days Before Xmas - http://vimeo.com/68378230
- Gill's talk on Mvvm in Windows 8 - http://vimeo.com/68331993
- Paul's talk on Mvvm in Reactive UI - including Xamarin platforms - http://vimeo.com/68331765
- Laurent's talk on sharing Mvvm code in Windows - http://vimeo.com/68327407
- Iris on advanced WP8 - http://vimeo.com/68320540
- Kevin on WinStore - http://vimeo.com/68320464
- Rocky on from WinForms to WinStore - http://vimeo.com/68236545
- Me on C# and Mvvm to share code across them all - http://vimeo.com/68375201
For a full list for all of NDC2013 - there are a *lot* of great sessions - see http://vimeo.com/ndcoslo/
Stuart Lodge: Sharing C# across Windows, Android and iOS using MvvmCross from NDCOslo on Vimeo.
Wednesday, June 26, 2013
A Brief History of MvvmCross
No N+1 today, but I did a quick practice run through for my current MvvmCross presentation this morning. This is almost the same presentation as I gave at NDC, but I practiced it here just ahead of presenting in Southampton tomorrow and in Glasgow next week.
If you've watched the N+1's then you definitely don't need to watch this as well :)
But if you want an introduction into the history of MvvmCross, then this might be interesting to you :)
Stuart
If you've watched the N+1's then you definitely don't need to watch this as well :)
But if you want an introduction into the history of MvvmCross, then this might be interesting to you :)
Stuart
Possible breaking changes caused by Tibet binding ideas
We're continuing to explore the Tibet binding ideas - discussed in http://slodge.blogspot.co.uk/2013/06/tibet-binding.html
These ideas should be an add-on to MvvmCross - so they will not break existing v3 Swiss or fluent binding code.
However, if anyone is using Json binding, or if they are directly using the MvxSerializableBindingDescription or MvxBindingDescription structures, then the current approach might cause some issues.
In order to gauge whether this is a problem, please get in touch via comments or twitter if anyone is currently using v3 and is currently:
If this turns out to be anything other than a very, very small issue, then we'll change our approach - we'll make Tibet a totally separate module rather than building it on top of Swiss.
So.... please let me know if you fall into this category of user - I'm keen to stick to my promise of making v3 stable.
These ideas should be an add-on to MvvmCross - so they will not break existing v3 Swiss or fluent binding code.
However, if anyone is using Json binding, or if they are directly using the MvxSerializableBindingDescription or MvxBindingDescription structures, then the current approach might cause some issues.
In order to gauge whether this is a problem, please get in touch via comments or twitter if anyone is currently using v3 and is currently:
- using Json format binding
- directly accessing MvxSerializableBindingDescription
- or directly accessing MvxeBindingDescription
If this turns out to be anything other than a very, very small issue, then we'll change our approach - we'll make Tibet a totally separate module rather than building it on top of Swiss.
So.... please let me know if you fall into this category of user - I'm keen to stick to my promise of making v3 stable.
Tuesday, June 25, 2013
N=31 - Injection of Platform Specific Services - N+1 Days of MvvmCross
One of the common questions I get asked is how to consume non-portable functionality into portable class library functionality.
My answer to this is to use dependency injection where possible.
This N+1 covers two ways of doing that:
In my 'real-world' projects I generally:
The video for today is at:
At one point, you see that I have an assembly version mismatch - sorry about this - it's due to me talking from a development rather than production setup, and it was easily solved using the nuget `Update-Package` command to update all my projects to the same MvvmCross NuGet version.
The code is at: https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-31-Injection
For more info on this, please also see:
For more on N+1, see:
My answer to this is to use dependency injection where possible.
This N+1 covers two ways of doing that:
- firstly by defining interfaces in the core project, and manually registering implementations in each UI project
- secondly by using testable, reusable plugins
In my 'real-world' projects I generally:
- start with the first approach - it's quick and very easy to do
- migrate to plugins where I find I have functionality I need to test, or if I think that I might want to reuse that functionality across projects
- sometimes, rarely, I do also switch back to non-portable code (to file-linking) for cases where the native API which needs consuming is too large to wrap with an interface - but I try to avoid this wherever possible.
The video for today is at:
At one point, you see that I have an assembly version mismatch - sorry about this - it's due to me talking from a development rather than production setup, and it was easily solved using the nuget `Update-Package` command to update all my projects to the same MvvmCross NuGet version.
The code is at: https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-31-Injection
For more info on this, please also see:
- a presentation on plugins at https://speakerdeck.com/cirrious/plugins-in-mvvmcross
- a full explanation of MvvmCross IoC on http://stackoverflow.com/a/16980207/373321
- the 'fractal' example which shows a real example of injecting a 'screen size' service at https://github.com/slodge/MvvmCross-Tutorials/tree/master/FractalGen
- the 'good vibrations' sample for plugins at https://github.com/slodge/MvvmCross-Tutorials/tree/master/GoodVibrations
For more on N+1, see:
Any Unity Developers want to assist the MvvmCross NGui Unity fork?
Over the last 6 months a few developers have worked hard to get Unity working well with MvvmCross.
Now they are looking to share this port - and they'd like to get some expert advice to work out how best to share this onto GitHub.
If anyone out there wants to help, then please get in touch :)
Now they are looking to share this port - and they'd like to get some expert advice to work out how best to share this onto GitHub.
If anyone out there wants to help, then please get in touch :)
Any Unity3D developers want to help migrate the MvvmCross NGui Unity fork into its own GitHub repository? If yes, then get in touch :)
— MvvmCross (@MvvmCross) June 25, 2013
Monday, June 24, 2013
N=30 - CrossLight (aka Project Chimp) - N+1 Days of MvvmCross
This is a very technical topic today.
It's aimed mainly at people who want to use the MvvmCross plugins or the MvvmCross binding layer in non-MvvmCross applications. This may sound isn't something MvvmCross should want... but I would personally love to see lots of small cross-platform application frameworks pushing away at different ideas/areas. Innovation breeds off of invention, and innovation is fun and profitable :)
Today's video is:
The code is at: https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-30-ChimpCrossLight
The existing CrossLight demos are in: https://github.com/slodge/MvvmCross-Tutorials/tree/master/CrossLight
The original idea for Project Chimp was discussed in http://slodge.blogspot.co.uk/2013/03/a-chimp-is-born-mvvm-on-monodroid.html
The v3 changes that enabled Chimp were also discussed in the slide deck at: http://slodge.blogspot.co.uk/2013/03/hot-tuna-mvvmcross-v3-progress.html
For an excellent index of N+1 try:
It's aimed mainly at people who want to use the MvvmCross plugins or the MvvmCross binding layer in non-MvvmCross applications. This may sound isn't something MvvmCross should want... but I would personally love to see lots of small cross-platform application frameworks pushing away at different ideas/areas. Innovation breeds off of invention, and innovation is fun and profitable :)
Today's video is:
The code is at: https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-30-ChimpCrossLight
The existing CrossLight demos are in: https://github.com/slodge/MvvmCross-Tutorials/tree/master/CrossLight
The original idea for Project Chimp was discussed in http://slodge.blogspot.co.uk/2013/03/a-chimp-is-born-mvvm-on-monodroid.html
The v3 changes that enabled Chimp were also discussed in the slide deck at: http://slodge.blogspot.co.uk/2013/03/hot-tuna-mvvmcross-v3-progress.html
For an excellent index of N+1 try:
N=29 - Testing! - N+1 Days of MvvmCross
Today we cover testing of your core services and view models.
For this we use:
For today's code, see https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-29-TipCalcTest
For @gshackles excellent Evolve session on testing see http://xamarin.com/evolve/2013#session-7wb0etd3r8
For an index of all the N+1 videos, please see:
For this we use:
- NUnit - http://nunit.org/
- Moq - http://code.google.com/p/moq/
For today's code, see https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-29-TipCalcTest
For @gshackles excellent Evolve session on testing see http://xamarin.com/evolve/2013#session-7wb0etd3r8
For an index of all the N+1 videos, please see:
Friday, June 21, 2013
N=28 - Custom Bindings - N+1 Days of MvvmCross
Today, I thought I'd try something Deeply Technical
Actually it's not that technical... but it's a topic that people might feel a bit nervous about.
There's no need to worry - custom bindings are actually pretty simple.
For most UI controls/widgets in Android and iOS, MvvmCross binding "just works"
It does this using Reflection.
This works brilliantly well for many (most!) controls.
Problems only arise when whoever has written the control hasn't followed this convention - e.g.
In these cases, you can work around the challenge by using a Custom Binding.
The code for today is in: https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-28-CustomBinding
For an excellent index of all the N+1 videos, check out:
Custom Bindings
Actually it's not that technical... but it's a topic that people might feel a bit nervous about.
There's no need to worry - custom bindings are actually pretty simple.
For most UI controls/widgets in Android and iOS, MvvmCross binding "just works"
It does this using Reflection.
- Wherever Mvx sees a property - e.g. public int Count {get;set;} - then it knows it can do one-way binding to it using Reflection.
- Further, when it sees that there is also an event with a name ~Changed - e.g. public event EventHandler CountChanged; - then it also guesses that the event can be used for TwoWay binding too.
This works brilliantly well for many (most!) controls.
Problems only arise when whoever has written the control hasn't followed this convention - e.g.
- if they've just provided arbitrary get/set methods instead of a public C# property
- or if they've decided to signal their changes using a delegate or watcher pattern instead of a C# event.
In these cases, you can work around the challenge by using a Custom Binding.
The code for today is in: https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-28-CustomBinding
For an excellent index of all the N+1 videos, check out:
Thursday, June 20, 2013
Tibet Binding
Today,
I'd like to share an early preview of some new MvvmCross work - especially to ask
whether people feel it is a feature they will want, and whether anyone has any further
requirements, ideas or code they'd like to contribute.
This new work all applies within the heart of MvvmCross data-binding. As many of you know, earlier this year we rewrote the binding engine in MvvmCross to use the simpler, cleaner 'Swiss' binding. More recently, we've now been working hard to extend this clean 'Swiss' syntax in some new directions - and this work is codenamed Tibet
Some of the motivation behind Tibet was the work we've already done, but beyond that we've also received some really valuable ideas and input from users and from community comments, including blog posts like "Knockout - what Mvvm should have been like in Xaml"
We hope that the output of Tibet will allow us to databind to viewmodels using a richer syntax including:
As an example of the syntax we can build, I've recorded this short introduction:
Within this introduction we build up to a 'complicated' and 'artificial' binding of:
This binding says that the value of Text should be dynamically calculated by:
The basis for this demo code today is a simple ViewModel and 2 simple ValueConverters:
The binding in Android then looks like:
The binding within iOS is similar. Note that we don't yet use the Fluent binding for this new binding, although we would hope to add some fluent code for it in the future:
The binding within Windows is:
I've pushed the code for this first demo to: https://github.com/slodge/Tibet
That's all there is for now.
As I said at the start this is an early preview of a new idea, and I'm especially interested to hear:
Please do let me know if you have any comments :)
This new work all applies within the heart of MvvmCross data-binding. As many of you know, earlier this year we rewrote the binding engine in MvvmCross to use the simpler, cleaner 'Swiss' binding. More recently, we've now been working hard to extend this clean 'Swiss' syntax in some new directions - and this work is codenamed Tibet
Some of the motivation behind Tibet was the work we've already done, but beyond that we've also received some really valuable ideas and input from users and from community comments, including blog posts like "Knockout - what Mvvm should have been like in Xaml"
We hope that the output of Tibet will allow us to databind to viewmodels using a richer syntax including:
- Function-like value converter calling
- Multi-bindings - allowing a single UI field to update in response to any of several ViewModel property changes
- The use of literals (ints, doubles, booleans and strings) within the bindings.
- Simple operator syntax which can be applied across multi-bindings - note that these operations are *not* full .Net operators - instead they just provide a simple interpreter
- Nested application of operators and value converters - allowing you to use multiple bindings and multiple value converters within the same binding expression.
- The unification of binding so that the same engine and syntax is used across all platforms (across all of Windows, Android and iOS)
As an example of the syntax we can build, I've recorded this short introduction:
Within this introduction we build up to a 'complicated' and 'artificial' binding of:
Text Salutation(Counter + Length(Hello)) + ' ' + Hello
This binding says that the value of Text should be dynamically calculated by:
- applying the LengthValueConverter to the Hello property
- adding the value of the Counter property
- applying the SalutationValueConverter to that sum
- concatenating the resulting string with a single space
- concatenating the resulting string with the value of the Hello property
The basis for this demo code today is a simple ViewModel and 2 simple ValueConverters:
The binding in Android then looks like:
The binding within iOS is similar. Note that we don't yet use the Fluent binding for this new binding, although we would hope to add some fluent code for it in the future:
The binding within Windows is:
I've pushed the code for this first demo to: https://github.com/slodge/Tibet
That's all there is for now.
As I said at the start this is an early preview of a new idea, and I'm especially interested to hear:
- whether it's worthwhile continuing...
- whether anyone has any further requirements, ideas or code they'd like to contribute.
Please do let me know if you have any comments :)
N=27 - Ninja for MvvmCross (N+1 Days of MvvmCross)
Last week I saw this tweet
And immediately I knew what my calling was.
My destiny was that I would become a Ninja....
What an awesome plugin from @asudbury
The code generated today is on: https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-27-Ninja
For the amazing index of N+1 videos, see:
@mvvmcross: Ninja Coder for MvvmCross v1.1.5 now available for download. Built with mvvmcross3.0.8 goo.gl/kBrYS
— asudbury (@asudbury) June 11, 2013
And immediately I knew what my calling was.
My destiny was that I would become a Ninja....
What an awesome plugin from @asudbury
The code generated today is on: https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-27-Ninja
For the amazing index of N+1 videos, see:
Wednesday, June 12, 2013
Intercepting RaisePropertyChanged
We've recently pushed an update which allows developers to intercept all MvxNotifyPropertyChanged notifications if you want to.
The aim of this is to allow you to provide custom RaisePropertyChanged functionality.
At this first release, the framework doesn't provide any standard Interceptors - but we might write an initial one at some point soon.
An example Interception
The core of interception is the IMvxInpcInterceptor interface.
public interface IMvxInpcInterceptor
{
MvxInpcInterceptionResult Intercept(IMvxNotifyPropertyChanged sender, PropertyChangedEventArgs args);
}
You might use this, for example, to provide things like automated additional notifications for certain types - e.g. you might use it to send dependent change notifications.
For example, suppose you have a Person ViewModel with properties:
This new functionality would allow you to provide an interceptor which would automatically send a FullName change notification whenever FirstName or LastName change - ie.e you could implement this interceptor as:
public class MyInterceptor : IMvxInpcInterceptor
{
public MvxInpcInterceptionResult Intercept(
IMvxNotifyPropertyChanged sender,
PropertyChangedEventArgs args)
{
if (sender.GetType () == typeof(Person))
{
if (args.PropertyName == "FirstName" ||
args.PropertyName == "LastName")
{
sender.RaisePropertyChanged ("FullName");
}
}
return MvxInpcInterceptionResult.RaisePropertyChanged;
}
}
With this done you could then register your implementation with IoC during Setup.InitializeInpcInterception - e.g.
protected override void InitializeInpcInterception()
{
Mvx.RegisterSingleton((IMvxInpcInterceptor)new MyInterceptor());
}
For release software, I wouldn't normally expect you to use this particular interceptor implementation, but I hope this illustrates how you might be able to use this mechanism.
For inspiration!
For some inspiration about the sort of thing that some people are doing in a similar area, take a look at the excellent: https://github.com/zleao/MvvmCross-PropertyChangedEventPropagation
The aim of this is to allow you to provide custom RaisePropertyChanged functionality.
At this first release, the framework doesn't provide any standard Interceptors - but we might write an initial one at some point soon.
An example Interception
The core of interception is the IMvxInpcInterceptor interface.
public interface IMvxInpcInterceptor
{
MvxInpcInterceptionResult Intercept(IMvxNotifyPropertyChanged sender, PropertyChangedEventArgs args);
}
You might use this, for example, to provide things like automated additional notifications for certain types - e.g. you might use it to send dependent change notifications.
For example, suppose you have a Person ViewModel with properties:
- FirstName
- LastName
- FullName
This new functionality would allow you to provide an interceptor which would automatically send a FullName change notification whenever FirstName or LastName change - ie.e you could implement this interceptor as:
public class MyInterceptor : IMvxInpcInterceptor
{
public MvxInpcInterceptionResult Intercept(
IMvxNotifyPropertyChanged sender,
PropertyChangedEventArgs args)
{
if (sender.GetType () == typeof(Person))
{
if (args.PropertyName == "FirstName" ||
args.PropertyName == "LastName")
{
sender.RaisePropertyChanged ("FullName");
}
}
return MvxInpcInterceptionResult.RaisePropertyChanged;
}
}
With this done you could then register your implementation with IoC during Setup.InitializeInpcInterception - e.g.
protected override void InitializeInpcInterception()
{
Mvx.RegisterSingleton((IMvxInpcInterceptor)new MyInterceptor());
}
For release software, I wouldn't normally expect you to use this particular interceptor implementation, but I hope this illustrates how you might be able to use this mechanism.
For inspiration!
For some inspiration about the sort of thing that some people are doing in a similar area, take a look at the excellent: https://github.com/zleao/MvvmCross-PropertyChangedEventPropagation
CommandParameter binding
We recently added a special CommandParameter parse step to allow the binding to specify fixed values (strings, ints, bools) to ICommand bindings.
This can be used as:
local:MvxBind="Click MyCommand,CommandParameter=Thursday"
which uses a ValueConverter to turn a Click into a call on:
MyCommand.Execute("Thursday")
So can be received in
new MvxCommand
This helps where you want to reuse a command across multiple buttons
However, please note that this cannot be used currently with valueconverters - as it itself uses a valueconverter to achieve the effect.
Hope that helps :)
Tuesday, June 11, 2013
My standard reply to MvvmCross support emails
This is the type of message I generally send to everyone when they send me an email about MvvmCross. I'm afraid I currently get perhaps 5 emails every day and answering them is simply not efficient or practical
Thanks for understanding
Stuart
Hi (friend)
Thanks for the email
I provide lots of support to the community and I do this in public. I find talking in public is better:
Questions
If you need help or have questions, please try asking on StackOverflow or on the Xamarin forums - I and others can help there. Please provide a good level of detail in your question - e.g.:
If you ask a good question, then I and others will often spend hours answering it. If you ask a vague one sentence question that lacks detail, then no-one will be able help you. The better your question - the better the answers.
There are some great tips on asking questions in http://stackoverflow.com/help/on-topic
Bugs and Features
If you believe you have found a bug or if you have a new Feature Request, then please try raising an issue on github - https://github.com/slodge/MvvmCross/issues/new - but please again include a good level of information if you can. It really helps if you can provide a complete github repo which demonstrates the problem - this makes it easier and quicker for people to find, fix and test the problem - so quicker for you to get a solution.
MvvmCross also accepts pull requests from other github repos. Please only send a pull request if you agree to have your code shared under the MvvmCross license. Pull requests including Unit Tests are encouraged - I am trying to improve the test coverage inside MvvmCross. Also please understand that currently I do personally maintain and support MvvmCross - so please do understand that sometimes I may decide not to merge your request. My aim is to try to keep MvvmCross extensible - so even if a Pull Request is not accepted, then you will still hopefully be able to work on a fork or in an extension in order to use that functionality yourself.
Privacy
If after reading this, you decide you still really need 1-to-1 support because of business reasons, then I understand and can provide this, but only as a paid business option. You are welcome to email me about that if you need it.
Thanks for understanding
Best wishes
Stuart
Thanks for understanding
Stuart
Hi (friend)
Thanks for the email
I provide lots of support to the community and I do this in public. I find talking in public is better:
- it helps as many people as possible and
- it allows others to also help out with answers - most of the best ideas come from other people.
Questions
If you need help or have questions, please try asking on StackOverflow or on the Xamarin forums - I and others can help there. Please provide a good level of detail in your question - e.g.:
- if you have a question about an exception, then please include some code near where the error occurred and the exception message and stack trace.
- if you have a question about an idea or concept, then maybe try adding a diagram that will help others understand the concept - and tell everyone what you've already tried
If you ask a good question, then I and others will often spend hours answering it. If you ask a vague one sentence question that lacks detail, then no-one will be able help you. The better your question - the better the answers.
There are some great tips on asking questions in http://stackoverflow.com/help/on-topic
Bugs and Features
If you believe you have found a bug or if you have a new Feature Request, then please try raising an issue on github - https://github.com/slodge/MvvmCross/issues/new - but please again include a good level of information if you can. It really helps if you can provide a complete github repo which demonstrates the problem - this makes it easier and quicker for people to find, fix and test the problem - so quicker for you to get a solution.
MvvmCross also accepts pull requests from other github repos. Please only send a pull request if you agree to have your code shared under the MvvmCross license. Pull requests including Unit Tests are encouraged - I am trying to improve the test coverage inside MvvmCross. Also please understand that currently I do personally maintain and support MvvmCross - so please do understand that sometimes I may decide not to merge your request. My aim is to try to keep MvvmCross extensible - so even if a Pull Request is not accepted, then you will still hopefully be able to work on a fork or in an extension in order to use that functionality yourself.
Privacy
If after reading this, you decide you still really need 1-to-1 support because of business reasons, then I understand and can provide this, but only as a paid business option. You are welcome to email me about that if you need it.
Thanks for understanding
Best wishes
Stuart
Monday, June 10, 2013
N=26 - Down at Android Fragments Rock (N+1 Days of MvvmCross)
Today N+1 is back!
Sorry about the short break... and sorry about before another short break that's coming up - I'm going to NDC Oslo in Norway this week :)
Today, we're talking about Fragments!
Fragments are an Android-only thing. They're a type of User Control and they were invented by Jim Henson*
In this N+1 we talk through:
For more on fragments:
The video is:
Today's source code is available on: https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-26-Fraggle
A full and wonderful index for N+1 is available on
---
* ok, not really :) For more on Fraggle Rock... http://muppet.wikia.com/wiki/Fraggle_Rock - which is where the images above come from (under CC). Also for the full Fraggle Rock theme song, try http://www.youtube.com/watch?v=l_zsz_MlVvI
Sorry about the short break... and sorry about before another short break that's coming up - I'm going to NDC Oslo in Norway this week :)
Today, we're talking about Fragments!
Fragments are an Android-only thing. They're a type of User Control and they were invented by Jim Henson*
In this N+1 we talk through:
- how to data-bind static fragments
- how to data-bind dynamic fragments
- briefly how to data-bind fragments in:
- tabs
- dialogs
- the little-known MvxFrameControl
For more on fragments:
- see the Fragment sample - https://github.com/slodge/MvvmCross-Tutorials/tree/master/Fragments
- see this recent post on navigating using a Custom Presenter and Fragments http://enginecore.blogspot.ro/2013/06/more-dynamic-android-fragments-with.html
The video is:
Today's source code is available on: https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-26-Fraggle
A full and wonderful index for N+1 is available on
---
* ok, not really :) For more on Fraggle Rock... http://muppet.wikia.com/wiki/Fraggle_Rock - which is where the images above come from (under CC). Also for the full Fraggle Rock theme song, try http://www.youtube.com/watch?v=l_zsz_MlVvI
Sunday, June 09, 2013
Presenter roundup
There have been quite a few awesome* custom presenters around recently. Among the highlights have been:
Better Tabbing
A custom tab presenter that combines UINavigationController and UITabBarController more neatly: http://deapsquatter.blogspot.co.uk/2013/06/custom-presenter-for-uitabbarcontroller.html
Navigation by Fragments
An excellent tutorial on how to navigate using fragments in Android - http://enginecore.blogspot.ro/2013/06/more-dynamic-android-fragments-with.html
Stack Clearing
A custom presenter that allows you to request the iOS back stack to be cleared
https://gist.github.com/gshackles/5735595
A Presenter combined with a sliding 'hamburger' menu
A full sample using a sliding hamburger menu - https://github.com/fcaico/MvxSlidingPanels.Touch/blob/master/MvxSlidingPanelsSample.Touch/MvxSlidingPanelsTouchViewPresenter.cs
N+1
There have been a couple of videos recently:
And finally.... A presenter presentation...
* judging for badges of awesomeness still pending!
Better Tabbing
A custom tab presenter that combines UINavigationController and UITabBarController more neatly: http://deapsquatter.blogspot.co.uk/2013/06/custom-presenter-for-uitabbarcontroller.html
Navigation by Fragments
An excellent tutorial on how to navigate using fragments in Android - http://enginecore.blogspot.ro/2013/06/more-dynamic-android-fragments-with.html
Stack Clearing
A custom presenter that allows you to request the iOS back stack to be cleared
https://gist.github.com/gshackles/5735595
A Presenter combined with a sliding 'hamburger' menu
A full sample using a sliding hamburger menu - https://github.com/fcaico/MvxSlidingPanels.Touch/blob/master/MvxSlidingPanelsSample.Touch/MvxSlidingPanelsTouchViewPresenter.cs
N+1
There have been a couple of videos recently:
- N=24 - UISplitView - http://slodge.blogspot.co.uk/2013/05/n24-splitviewpresenter-n1-days-of.html
- N=25 - Tabs - http://slodge.blogspot.co.uk/2013/06/n25-tabs-n1-days-of-mvvmcross.html
And finally.... A presenter presentation...
* judging for badges of awesomeness still pending!
Friday, June 07, 2013
IoC and ServiceLocation in v3 - a brain dump....
Two key ideas that are use in MvvmCross are:
There are lots of articles and introductions available on this - some good starting places are Martin Fowler's introduction and Joel Abrahamsson's IoC introduction. I've also made some animated slides as a simple demonstration.
Specifically within MvvmCross, we provide a single static class
The core idea of MvvmCross Service Location is that you can write classes and interfaces like:
With this pair written you could then register a
As a variation on this, you could register a lazy singleton. This is written
One final option, is that you can register the
If you create several implementations of an interface and register them all:
This can be useful for:
The default NuGet templates for MvvmCross contain a block of code in the core
Technical Note> the lazy singleton implementation here is quite technical - it ensures that if a class implements
The choice of name ending here -
As well as
For example, if we add a class like:
This "Constructor Injection" mechanism is used internally within MvvmCross when creating ViewModels.
If you declare a ViewModel like:
then MvvmCross will use the
This is important because:
Internally, the
This enables you to register implementations which depend on other interfaces like:
Further, this process is recursive - so if any of these returned objects requires another object - e.g. if your
Sometimes you need to use some platform specific functionality in your ViewModels. e.g. for example, you might want to get the current screen dimensions in your ViewModel - but there's no existing portable .Net call to do this.
When you want to include functionality like this, then there are two main choices:
In your core project, you can declare an interface and you can use that interface in your classes there - e.g.:
A Plugin is an MvvmCross pattern for combining a PCL assembly, plus optionally some platform specific assemblies in order to package up some functionality.
This plugin layer is simply a pattern - some simple conventions - for naming related Assemblies, for including small
For example, existing plugins include:
- the Service Locator pattern
- Inversion of Control
There are lots of articles and introductions available on this - some good starting places are Martin Fowler's introduction and Joel Abrahamsson's IoC introduction. I've also made some animated slides as a simple demonstration.
Specifically within MvvmCross, we provide a single static class
Mvx
which acts as a single place for both registering and resolving interfaces and their implementations.Service Location - Registration and Resolution
The core idea of MvvmCross Service Location is that you can write classes and interfaces like:
public interface IFoo
{
string Request();
}
public class Foo : IFoo
{
public string Request()
{
return "Hello World";
}
}
Singleton Registration
With this pair written you could then register a
Foo
instance as a singleton which implements IFoo
using:If you did this, then any code can call:// every time someone needs an IFoo they will get the same one Mvx.RegisterSingleton
<
IFoo>(new Foo());
and every single call would return the same instance of Foovar foo = Mvx.Resolve
<
IFoo>
();
Lazy Singleton Registration
As a variation on this, you could register a lazy singleton. This is written
In this case:// every time someone needs an IFoo they will get the same one // but we don't create it until someone asks for it Mvx.RegisterSingleton
<
IFoo>
(() => new Foo());
- no
Foo
is created initially - the first time any code calls
Mvx.Resolve
<
IFoo>
then a new() Foo
will be created and returned - all subsequent calls will get the same instance that was created the first time
'Dynamic' Registration
One final option, is that you can register the
IFoo
and Foo
pair as:In this case, every call to// every time someone needs an IFoo they will get a new one Mvx.RegisterType
IFoo, Foo>();
<
Mvx.Resolve
<
IFoo>()
will create a new Foo
- every call will return a different Foo
.Last-registered wins
If you create several implementations of an interface and register them all:
Then each call replaces the previous registration - so when a client callsMvx.RegisterType
IFoo, Foo1>
<
(); Mvx.RegisterSingleton
IFoo>(new Foo2()); Mvx.RegisterType
<
IFoo, Foo3>();
<
Mvx.Resolve
<
IFoo>()
then the most recent registration will be returned.This can be useful for:
- overwriting default implementations
- replacing implementations depending on application state - e.g.
after a user has been authenticated then you could replace an empty
IUserInfo
implementation with a real one.
Bulk Registration by Convention
The default NuGet templates for MvvmCross contain a block of code in the core
App.cs
like: CreatableTypes()
.EndingWith("Service")
.AsInterfaces()
.RegisterAsLazySingleton();
This code uses Reflection to:- find all classes in the Core assembly
- which are
creatable
- i.e.:- have a public constructor
- are not
abstract
- with names ending in Service
- which are
- find their interfaces
- register them as lazy singletons according to the interfaces they support
Technical Note> the lazy singleton implementation here is quite technical - it ensures that if a class implements
IOne
and ITwo
then the same instance will be returned when resolving both IOne
and ITwo
.The choice of name ending here -
Service
- and the
choice to use Lazy singletons are only personal conventions. If you
prefer to use other names or other lifetimes for your objects you can
replace this code with a different call or with multiple calls like: CreatableTypes()
.EndingWith("SingleFeed")
.AsInterfaces()
.RegisterAsLazySingleton();
CreatableTypes()
.EndingWith("Generator")
.AsInterfaces()
.RegisterAsDynamic();
CreatableTypes()
.EndingWith("QuickSand")
.AsInterfaces()
.RegisterAsSingleton();
There you can also use additional Linq
helper methods to help further define your registrations if you want to - e.g. Inherits
, Except
. WithAttribute
, Containing
, InNamespace
... e.g. CreatableTypes()
.StartingWith("JDI")
.InNamespace("MyApp.Core.HyperSpace")
.WithAttribute(typeof(MySpecialAttribute))
.AsInterfaces()
.RegisterAsSingleton();
And you can also, of course, use the same type of registration logic on assemblies other than Core - e.g.: typeof(Reusable.Helpers.MyHelper).Assembly.CreatableTypes()
.EndingWith("Helper")
.AsInterfaces()
.RegisterAsDynamic();
Alternatively, if you prefer not to use this Reflection based
registration, then you can instead just manually register your
implementations:The choice is your'sMvx.RegisterSingleton
(new MyMixer()); Mvx.RegisterSingleton
(new MyCheese()); Mvx.RegisterType
(); Mvx.RegisterType
();
Constructor Injection
As well as
Mvx.Resolve
, the Mvx
static class provides a reflection based mechanism to automatically resolve parameters during object construction.For example, if we add a class like:
public class Bar
{
public Bar(IFoo foo)
{
// do stuff
}
}
Then you can create this object using: What happens during this call is:Mvx.IocConstruct
();
- MvvmCross:
- uses Reflection to find the constructor of
Bar
- looks at the parameters for that constructor and sees it needs an
IFoo
- uses
Mvx.Resolve
to get hold of the registered implementation for
()IFoo
- uses Reflection to call the constructor with the
IFoo
parameter
- uses Reflection to find the constructor of
Constructor Injection and ViewModels
This "Constructor Injection" mechanism is used internally within MvvmCross when creating ViewModels.
If you declare a ViewModel like:
public class MyViewModel : MvxViewModel
{
public MyViewModel(IMvxJsonConverter jsonConverter, IMvxGeoLocationWatcher locationWatcher)
{
// ....
}
}
then MvvmCross will use the
Mvx
static class to resolve objects for jsonConverter
and locationWatcher
when a MyViewModel
is created.This is important because:
- It allows you to easily provide different
locationWatcher
classes on different platforms (on iPhone you can use a watcher that talk toCoreLocation
, on WindowsPhone you can use a watcher that talks toSystem.Device.Location
- It allows you to easily provide mock implementations in your unit tests
- It allows you to override default implementations - if you don't like the
Json.Net
implementation for Json, you can use aServiceStack.Text
implementation instead.
Constructor Injection and Chaining
Internally, the
Mvx.Resolve
mechanism uses constructor injection when new objects are needed.This enables you to register implementations which depend on other interfaces like:
public interface ITaxCalculator
{
double TaxDueFor(int customerId)
}
public class TaxCalculator
{
public TaxCalculator(ICustomerRepository customerRepository, IForeignExchange foreignExchange, ITaxRuleList taxRuleList)
{
// code...
}
// code...
}
If you then register this calculator as:Then when a client callsMvx.RegisterType
<
ITaxCalculator, TaxCalculator>();
Mvx.Resolve
<
ITaxCalculator>()
then what will happen is that MvvmCross will create a new TaxCalculator
instance, resolving all of ICustomerRepository
IForeignExchange
and ITaxRuleList
during the operation.Further, this process is recursive - so if any of these returned objects requires another object - e.g. if your
IForeignExchange
implementation requires a IChargeCommission
object - then MvvmCross will provide Resolve for you as well.How do I use IoC when I need different implementations on different platforms?
Sometimes you need to use some platform specific functionality in your ViewModels. e.g. for example, you might want to get the current screen dimensions in your ViewModel - but there's no existing portable .Net call to do this.
When you want to include functionality like this, then there are two main choices:
- Declare an interface in your core library, but then provide and register an implementation in each of your UI projects.
- Use or create a plugin
1. PCL-Interface with Platform-Specific Implementation
In your core project, you can declare an interface and you can use that interface in your classes there - e.g.:
public interface IScreenSize
{
double Height { get; }
double Width { get; }
}
public class MyViewModel : MvxViewModel
{
private readonly IScreenSize _screenSize;
public MyViewModel(IScreenSize screenSize)
{
_screenSize = screenSize;
}
public double Ratio
{
get { return (_screenSize.Width / _screenSize.Height); }
}
}
In each UI project, you can then declare the platform-specific implementation for IScreenSize
- e.g. a trivial example is: public class WindowsPhoneScreenSize : IScreenSize
{
public double Height { get { return 800.0; } }
public double Width { get { return 480.0; } }
}
You can then register these implementations in each of the platform-specific Setup files - e.g. you could override MvxSetup.InitializeFirstChance
withWith this done, thenprotected override void InitializeFirstChance() { Mvx.RegisterSingleton
IScreenSize>
<
(new WindowsPhoneScreenSize()); base.InitializeFirstChance(); }
MyViewModel
will get provided with the correct platform specific implementation of IScreenSize
on each platform.2. Use or create a plugin
A Plugin is an MvvmCross pattern for combining a PCL assembly, plus optionally some platform specific assemblies in order to package up some functionality.
This plugin layer is simply a pattern - some simple conventions - for naming related Assemblies, for including small
PluginLoader
and Plugin
helper classes, and for using IoC. Through this pattern it allows
functionality to be easily included, reused and tested across platforms
and across applications.For example, existing plugins include:
- a File plugin which provides access to
System.IO
type methods for manipulating files - a Location plugin which provides access to GeoLocation information
- a Messenger plugin which provides access to a Messenger/Event Aggregator
- a PictureChooser plugin which provides access to the camera and to the media library
- a ResourceLoader plugin which provides a way to access resource files packaged within the .apk, .app or .ipa for the application
- a SQLite plugin which provides access to
SQLite-net
on all platforms.
Plugin Use
If you want to see how these plugins can be used in your applications, then:
- the N+1 videos provide a good starting point - see http://mvvmcross.wordpress.com/ - especially :
- N=8 - Location http://slodge.blogspot.co.uk/2013/05/n8-location-location-location-n1-days.html
- N=9 - Messenger http://slodge.blogspot.co.uk/2013/05/n9-getting-message-n1-days-of-mvvmcross.html
- N=10 - SQLite http://slodge.blogspot.co.uk/2013/05/n10-sqlite-persistent-data-storage-n1.html
- N=12 -> N=17 - the Collect-A-Bull app http://slodge.blogspot.co.uk/2013/05/n12-collect-bull-full-app-part-1-n1.html
Plugin Authoring
Writing plugins is easy to do, but can feel a bit daunting at first.
The key steps are:
I'm not going to go into any more detail on writing plugins here.
If you'd like to see more about writing your own plugin, then:
If you don't want to use this in your code, then don't.
Simply remove the
There are lots of excellent libraries out there including AutoFac, Funq, MEF, OpenNetCF, TinyIoC and many, many more!
If you want to replace the MvvmCross implementation, then you'll need to:
There is an example Property Injection implementation for IoC provided.
This can be initialised using a Setup override of:
The IoC container in MvvmCross is designed to be quite lightweight and is targeted at a level of functionality required in the mobile applications I have built.
If you need more advanced/complex functionality, then you may need to use a different provider or a different approach - some suggestions for this are discussed in: Child containers in MvvmCross IoC
Note: this article is part of the v3 attempt to get MvvmCross documentation produced. If you'd like to help with this work, please say hello on https://github.com/slodge/MvvmCross/issues/252 - we need you!
The key steps are:
- Create the main PCL Assembly for the plugin - this should include:
- the interfaces your plugin will register
- any shared portable code (which may include implementations of one or more of the interfaces)
- a special
PluginLoader
class which MvvmCross will use to start the plugin
- Optionally create platform specific assemblies which:
- is named the same as the main assembly but with a platform specific extension (.Droid, .WindowsPhone, etc(
- contains
- any platform specific interface implementations
- a special
Plugin
class which MvvmCross will use to start this platform-specific extension
- Optionally provide extras like documentation and nuget packaging which will make the plugin easier to reuse.
I'm not going to go into any more detail on writing plugins here.
If you'd like to see more about writing your own plugin, then:
- there's a presentation on this at https://speakerdeck.com/cirrious/plugins-in-mvvmcross
- there's a sample which creates a
Vibrate
plugin at https://github.com/slodge/MvvmCross-Tutorials/tree/master/GoodVibrations
What if...
What if... I don't want to use Service Location or IoC
If you don't want to use this in your code, then don't.
Simply remove the
CreatableTypes()...
code from App.cs and then use 'normal code' in your ViewModels - e.g.: public class MyViewModel : MvxViewModel
{
private readonly ITaxService _taxService;
public MyViewModel()
{
_taxService = new TaxService();
}
}
What if... I want to use a different Service Location or IoC mechanism
There are lots of excellent libraries out there including AutoFac, Funq, MEF, OpenNetCF, TinyIoC and many, many more!
If you want to replace the MvvmCross implementation, then you'll need to:
- write some kind of
Adapter
layer to provide their service location code as anIMvxIoCProvider
- override
CreateIocProvider
in yourSetup
class to provide this alternativeIMvxIoCProvider
implementation.
What if... I want to use Property Injection as an IoC mechanism
There is an example Property Injection implementation for IoC provided.
This can be initialised using a Setup override of:
protected override IMvxIoCProvider CreateIocProvider()
{
return MvxPropertyInjectingIoCContainer.Initialise();
}
What if... I want advanced IoC features like child containers
The IoC container in MvvmCross is designed to be quite lightweight and is targeted at a level of functionality required in the mobile applications I have built.
If you need more advanced/complex functionality, then you may need to use a different provider or a different approach - some suggestions for this are discussed in: Child containers in MvvmCross IoC
Note: this article is part of the v3 attempt to get MvvmCross documentation produced. If you'd like to help with this work, please say hello on https://github.com/slodge/MvvmCross/issues/252 - we need you!
Thursday, June 06, 2013
Mobile market share stats...
Some sources for market share stats are:
- WindowsPhone - http://blog.adduplex.com/2013/05/adduplex-windows-phone-statistics.html
- Android: http://developer.android.com/about/dashboards/index.html
- Unity (Android+iOS) http://stats.unity3d.com/
Wednesday, June 05, 2013
An MvvmCross v1 Xamarin.Android app for crime witnesses
Just heard that Self Evident has been published on the Google Play store: https://play.google.com/store/apps/details?id=org.witnessconfident.app
It's built using the original v1 of MvvmCross with input from a few UK developers including Matthew at Sky Fish Technologies and Gavin at GB Software Solutions.
Self Evident is a free app that records, validates and secures evidence. While the android version has been designed primarily as a crime reporting app, it also lets you file a report for work, notify an adviser or business of a claim, send the media a news story or just secure the evidence in your private account.
It's built using the original v1 of MvvmCross with input from a few UK developers including Matthew at Sky Fish Technologies and Gavin at GB Software Solutions.
Tuesday, June 04, 2013
Small Breaking Change for Dialog code
I've just committed some MvvmCross Touch and Android dialog code which will cause a small breaking change for existing implementations.
The main breaking change is that the `Bind` extension methods have moved from the individual Dialog projects to a shared location:
If you use Dialog, then you will soon need to change your code to include a using for this namespace.
Beyond that, I've also included some excellent AutoView updates from @csteeg and I've committed some additional changes which:
You can see this new Expression based binding in:
To compare this to the previous code, see the diff in the revision history: https://gist.github.com/slodge/5706116/revisions - the old code will still work, but the new Expression based code may be easier to use because of its intellisense and refactoring support.
The main breaking change is that the `Bind` extension methods have moved from the individual Dialog projects to a shared location:
Cirrious.MvvmCross.Binding.BindingContext
If you use Dialog, then you will soon need to change your code to include a using for this namespace.
Beyond that, I've also included some excellent AutoView updates from @csteeg and I've committed some additional changes which:
- unify the DateTime Element behaviour across both platforms
- includes a default binding target name of Value for all ValueElements
- includes Expression based binding for all Elements.
You can see this new Expression based binding in:
To compare this to the previous code, see the diff in the revision history: https://gist.github.com/slodge/5706116/revisions - the old code will still work, but the new Expression based code may be easier to use because of its intellisense and refactoring support.
Monday, June 03, 2013
N=25 - Tabs - N+1 Days of MvvmCross
Following on from splitview presenters, this talk gives an introduction into using tabs on Xamarin.Android, Xamarin.iOS and WindowsPhone.
For WindowsPhone, we use a Panorama as the local equivalent of Tabs - and we also mention Pivots.
For iOS, we show how to use a custom presenter to perform navigation within a tab child.
For Android, we hint at a future discussion of Fragments, but for now we discuss only Activities.
The video is:
The code is at https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-25-Tabbed
For more on the N+1 series, check out this excellent index - http://mvvmcross.wordpress.com/ - thanks Aboo!
For WindowsPhone, we use a Panorama as the local equivalent of Tabs - and we also mention Pivots.
For iOS, we show how to use a custom presenter to perform navigation within a tab child.
For Android, we hint at a future discussion of Fragments, but for now we discuss only Activities.
The video is:
The code is at https://github.com/slodge/NPlus1DaysOfMvvmCross/tree/master/N-25-Tabbed
For more on the N+1 series, check out this excellent index - http://mvvmcross.wordpress.com/ - thanks Aboo!
Subscribe to:
Posts (Atom)