Saturday, October 20, 2012

How the JSON Android.Dialog project works - and how WP.Dialog might work

Here's a very rough description of what I'm thinking - https://speakerdeck.com/u/cirrious/p/cross-plat ...

WP.Dialog is (I think) just the 'Form' part of that - just like Android.Dialog and MonoTouch.Dialog - although later it might grow in scope to the entire project - baby steps first:)

Also to be clear... I think WP.Dialog can exist and run without any dependency on MvvmCross - I don't see why it couldn't be useful for code-behind projects, for MvvmLight, etc

The projects
There are 5 projects:

  • Core.Dialog - a PCL containing:
    • Descriptions - the structs which describe a UI
    • Elements - the basic interfaces which UI components have to obey
    • Builder - the abstract code which turns Descriptions into Elements
  • Android
    • Android.Dialog - an Android Library containing:
        • Attributes - not currently used but provide a *very* nice way to turn C# models into UIs - see MonoTouch.Dialog for more
        • Builder - inherits from Core.Dialog.Builder - provides the *very small* Android specific building part
          • Elements - the default elements... the ones to start with are:
            • RootElement (which is a mess because it is a RootElement and also has RadioGroup functionality built in)
            • StringElement - displays a Caption and a Value
            • ValueElement - displays a Caption and an Editable Value
              • EntryElement
              • FloatElement
              • CheckboxElement
            • DO NOT START with RadioElement, WebElement, HtmlElement, etc - it's confusing!
        • Enums - mainly ignored... most seem to be there for MT.Dialog API compatability
        • Root-Level classes - DialogListView and DialogAdapter - together these 2 things provide the 'UI Control'
      • DialogSampleApp - the Android Demo project
        • MainDialogActivity - is the only activity that has been updated to the new JSON
  • Touch - ****nowhere near working****
    • Cirrious.MvvmCross.Dialog.Touch - my branch of MonoTouch.Dialog
    • Sample - the MonoTouch Sample

Within this layout... I guess WP should work in a new folder WindowsPhone and have two projects - a Dialog and a Sample :)

Naming: I'd like to put these projects in some namespace - for Mvx I used Cirrious (which is my company name) but that's mainly because of the way the project started - it was a company job! No idea what namespace to use, but I'd like to use Something.Dialog.Core rather than just Dialog.Core...


The MainDialogActivity code
For understanding Android.Dialog:
  • a good place to start might be MainDialogActivity.
  • This contains:
    • a big block of JSON
    • some code at the start of OnCreate to load the JSON
    • a big block of commented out C# which is equivalent to the JSON
Putting the big block of comment out code side-by-side with the JSON should help work out what is happening - and maybe looking at Dialog.Core.Descriptions will help with working out what the structure of the API is.

A quick walkthrough the code at the start of OnCreate:
            DroidResources.Initialise(typeof(Resource.Layout));
            var parser = new DroidElementBuilder();
 
            var setter = new ExampleActionPropertySetter();
            setter.Actions["ShowDialogActivity"] = (sender, args) => StartNew();
            setter.Actions["ShowDialogListViewActivity"] = (sender, args) => ClickList();
            setter.Actions["ElementTest"] = (sender, args) => ClickElementTest();
            parser.CustomPropertySetters["Action"] = setter;
            var description = Newtonsoft.Json.JsonConvert.DeserializeObject<ElementDescription>(JsonText);
            Root = parser.Build(description) as RootElement;
Breaking this down:

            DroidResources.Initialise(typeof(Resource.Layout));

The first line initialise the DroidResources - what this does is it tells the DroidResources where to look for numeric Android ResourceIds - e.g. when you load a StringElement then the framework might look for some AXML called dialog_string_layout (or similar) - these resources are in the resources folder.

            var parser = new DroidElementBuilder();
This creates a builder (not a parser - sorry!).

The Builder stores a lookup list of string names to Element Types

There is a default parameter to DroidElementBuilder which tells the Builder to reflect the Android.Dialog namespace and to look for the default set of Element Types.

Users can also register custom Element Types if they want to - so if you invent a RuneElement, then you can add it.

            var setter = new ExampleActionPropertySetter();
            setter.Actions["ShowDialogActivity"] = (sender, args) => StartNew();
            setter.Actions["ShowDialogListViewActivity"] = (sender, args) => ClickList();
            setter.Actions["ElementTest"] = (sender, args) => ClickElementTest();
            parser.CustomPropertySetters["Action"] = setter;

This block of code sets up a custom property setter for 'Action'. This means that if ever a property is marked in the Json with a value "@Action:foobar" then this property and foobar will be passed to the custom setter.

In a 'coming soon' step I expect to add an MvxBind custom property setter...

            var description = Newtonsoft.Json.JsonConvert.DeserializeObject<ElementDescription>(JsonText);

This uses PCL JSON.Net to deserialize the ElementDescription JSON. Note that the framework is decoupled from JSON - so users could use XML, ProtoBuf, C#, etc instead!


            Root = parser.Build(description) as RootElement;
Finally this line passes the description to the builder :)


How an Android Element is built
If some JSON comes in like:

                {
                    'Key':'String',
                    'Properties':{
                        'Caption':'Click for EntryElement Test',
                        'Click':'@Action:ElementTest'
                    }
                }
then this maps to an ElementDescription.

The builder uses this:
  • The Key 'String' is mapped to 'StringElement' - so it uses Reflection to call the parameterless constructor of StringElement (or the constructor with default parameters)
  • The builder then iterates the Properties 
    • uses reflection to set the Caption property on the StringElement to 'Click for EntryElement Test'
    • notices the '@Action:' prefix - so passes the Click PropertyInfo and 'ElementTest' to the custom property setter
That's it! You can set as many properties as there are available - it's up to the StringElement to turn those properties into something on the display.

Note that property values can be strings, numerics or booleans - anything else has to go through a special handler (e.g. a string lookup or a JSON serialised object)

Note that there is no real data binding right now - but that will come with '@MvxBind;' :)

Note that later there may be some chances to add platform specific properties - e.g. something like:

                    'Properties':{
                        'Caption':'Click for EntryElement Test',
                        'Click':'@Action:ElementTest',
                        '@Droid:WarpSpeed':4,
                        '@WindowsPhone:Pinned':false,
                    }


How an entire Dialog is displayed
In Android and in Touch, the Dialog is displayed using a ListView

The reason for this is because it allows UI virtualisation... and also because MonoTouch doesn't really have a StackPanel!

This use of a ListView makes the UI a bit more complicated than is really needed... e.g. for small forms it would actually be a lot easier to not have any cell reuse.

For WindowsPhone, it might be easier to just use a StackPanel with fixed members - but you could use a List if you wanted to....

In Android, the basic approach is:

- the UI View (Activity) is a List (including Groupings)
- the UI View gets help from an Adapter
- the Adapter stores the list of Elements
- when it comes to time to render the UI, then the Adapter's GetView gets called for every visible 'index'
- the Adapter passes the GetView call through to the GetView on the individual Element - this is passed through to GetViewImpl
- currently the GetViewImpl passes everything through eventually to DroidResources - which loads 'axml' for the element.
- calls like UpdateDetailDisplay and UpdateCaptionDisplay are used in the Element to actually fill in values in the Element

Note that because it uses a list, then there is an opportunity for cell reuse. In Mt.Dialog this works quite well. In Android.Dialog I think it's currently broken - but I will fix it.

So for WP.Dialog
I would expect for WP:
  • the same JSON will be used
  • the JSON will be parsed by JSON.Net
  • a WindowsPhoneBuilder will be used
  • this WindowsPhoneBuilder will (by default) know about a set of WindowsPhone Elements - which it will construct using reflection
  • these Elements will contain some C# and will somehow map to XAML...
  • the XAML will be parented either in a StackPanel (inside a ScrollViewer) or inside a ListView
  • if you use a ListView it's just a bit more complicated to route the bindings and to reuse controls (it's a standard 'ListItemSelector' type thing)
  • it would be really nice if the XAML is very easily styleable - like custom controls are
To get started...
  • maybe just try some JSON with some StringElements - each has a Caption and Value
  • then try adding an EntryElement - Caption and Value
  • then try adding a CheckboxElement - Caption and Boolean Value
The idea would be to creative native looking form UIs from the same JSON:

And then (if we're lucky) people can add platform specific styling to those UIs.

Cross Platform Views for MvvmCross... ideas...

This is the sort of thing I'm currently thinking about....

Friday, October 19, 2012

Update on the Portable Dialog JSON UI idea

Just an update on this - I just (this morning) have this sample below working.
sample
Full image: http://i.imgur.com/XJHpD.png

Obviously there is still a need for:
  • event handling - using ICommand or Delegates somehow
  • some elements need tweaking - especially custom Views and Images
  • integration with binding (for MvvmCross)
However, I think the basic idea should work pretty well across Android.Dialog and also the mvvmcross fork of MonoTouch.Dialog.

And I do intend to add a WinRT.Dialog and a WindowsPhone.Dialog too...

If anyone's interested, then post here or on https://github.com/slodge/Android.Dialog/issues/4

{
    'Key':'Root',
    'Properties':{
        'Caption':'TestRootElement'
    },
    'Sections':[
        {
            'Elements':[
                {
                    'Key':'String',
                    'Properties':{
                        'Caption':'Label',
                        'Value':'Only Element in a Blank Section'
                    }
                }
            ]
        },
        {
            'Properties':{
                'Header':'Test Header',
                'Footer':'Test Footer'
            },
            'Elements':[
                {
                    'Key':'Button',
                    'Properties':{
                        'Caption':'DialogActivity - needs ICommand'
                    }
                },
                {
                    'Key':'String',
                    'Properties':{
                        'Caption':'DialogListViewActivity - needs ICommand',
                        'LayoutName':'dialog_labelfieldright'
                    }
                },
                {
                    'Key':'Boolean',
                    'Properties':{
                        'Caption':'Push my button',
                        'Value':true
                    }
                },
                {
                    'Key':'Boolean',
                    'Properties':{
                        'Caption':'Push this too',
                        'Value':false
                    }
                },
                {
                    'Key':'String',
                    'Properties':{
                        'Caption':'Click for EntryElement Test - needs ICommand'
                    }
                }
            ]
        },
        {
            'Properties':{
                'Header':'Part II'
            },
            'Elements':[
                {
                    'Key':'String',
                    'Properties':{
                        'Caption':'This is the String Element',
                        'Value':'This is it\'s value'
                    }
                },
                {
                    'Key':'Checkbox',
                    'Properties':{
                        'Caption':'Check this out',
                        'Value':true
                    }
                },
                {
                    'Key':'Entry',
                    'Properties':{
                        'Caption':'Username',
                        'Value':'',
                        'Hint':'Enter Login'
                    }
                },
                {
                    'Key':'Entry',
                    'Properties':{
                        'Caption':'Password',
                        'Value':'',
                        'Hint':'Enter Password',
                        'Password':true
                    }
                }
            ]
        },
        {
            'HeaderElement': {
                'Key':'String',
                'Properties':{
                    'Caption':'Can Populate be done?',
                    'Value':'Need to look at how ViewElement works...'
                }
            },
            'Properties':{
                'Header':'Group'
            },
            'Elements':[
                {
                    'Key':'Root',
                    'Properties':{
                        'Caption':'Radio Group - needs work!'
                    }
                }
            ]
        }
    ]
}

Thursday, October 18, 2012

Starting to play with the idea of a cross platform UI framework

Hi All

I've started playing with the idea of doing a cross platform UI framework - at least for those UIs that can be done by MonoTouch.Dialog type displays.

See the idea in very raw form at: https://github.com/slodge/Android.Dialog/issues/4

Is this of interest... if it is then comment here or on GitHub

Stuart

Wednesday, October 17, 2012

Creating custom views is easy to do...

This answer came from a question about creating custom view behaviour inside a list in MvvmCross for MonoDroid - http://stackoverflow.com/questions/12934654/how-to-create-views-actions-listener-for-mvxitemtemplate


---

Creating custom views is easy to do...

namespace Angevelle.App1.UI.Droid.Controls
{
    public class MyText : EditText
    {
        public MyText(Context context, IAttributeSet attrs)
            : base(context, attrs)
        {
            this.EditorAction += OnEditorAction;
        }

        private void OnEditorAction(object sender, EditorActionEventArgs editorActionEventArgs)
        {
            if (editorActionEventArgs.ActionId == ImeAction.Done)
            {
                // this code not tested - but something like this should work
                var imm = (InputMethodManager)Context.GetSystemService(Context.InputMethodService);
                imm.HideSoftInputFromWindow(WindowToken, 0);
            }
        }
    }
}

Then you can use that View in your AXML just as you do Android or Mvx views:

<angevelle.app1.ui.droid.controls.MyText
         android:layout_height=....
     />

If you are finding angevelle.app1.ui.droid.controls too verbose, then you could shorten this using an abbreviation in setup.cs:

    protected override IDictionary ViewNamespaceAbbreviations
    {
        get
        {
            var abbreviations = base.ViewNamespaceAbbreviations;
            abbreviations["Abv"] = "angevelle.app1.ui.droid.controls";
            return abbreviations;
        }
    }
then you can just use:

<Abv.MyText
android:layout_height=.... />

Build a new plugin for mvvmcrosss

Update: This advice below is for vNext. For more up to date advice, see: http://stackoverflow.com/questions/16788164/custom-plugin-in-mvvmcross

-----

 1. Create a central shared plugin

This would be Portable Class library - say MyCompany.MvvmCross.Plugins.Mega
Within that central shared PCL, you would put whatever portable code was available - often this might only be a few service Interface definitions - e.g.

public interface IAlphaService { ... }

and

public interface IPageService { ... }

You'd then add the PluginManager for that plugin which would just add the boiler-plate of:

public class PluginLoader
    : IMvxPluginLoader

    , IMvxServiceConsumer<IMvxPluginManager>

{
    public static readonly PluginLoader Instance = new PluginLoader();


    #region Implementation of IMvxPluginLoader

    public void EnsureLoaded()

    {
        var manager = this.GetService<IMvxPluginManager>();

        manager.EnsureLoaded<PluginLoader>();
    }


    #endregion
}

2. Create the specific plugin implementations

For each platform, you would then implement the plugin - e.g. you might implement MyCompany.MvvmCross.Plugins.Mega.WindowsPhone and MyCompany .MvvmCross.Plugins.Mega.Droid

Within each of these you will implement the native classes which provide the services:
public class MyAlphaService : IAlphaService { ... } 

and
public class MyPageService : IPageService { ... }

Finally each plugin would then provide the boilerplate plugin implementation:

public class Plugin
    : IMvxPlugin

    , IMvxServiceProducer
{
    #region Implementation of IMvxPlugin


    public void Load()
    {

        // alpha registered as a singleton
        this.RegisterServiceInstance<IAlphaService>(new MyAlphaService());

        // page registered as a type
        this.RegisterServiceType<IPageService, MyPageService>();

    }

    #endregion
}

3. Instantiation of plugins

Each UI client will have to initialise the plugins.
This is done by the end UI client adding library references to:
  • the shared core plugin
  • the appropriate plugin implementation

3.1 WinRT, WindowsPhone and MonoTouch

Then, for WinRT, WindowsPhone and MonoTouch clients, you also need to provide a Loader accessor in setup.cs - like:
    protected override void AddPluginsLoaders(Cirrious.MvvmCross.Platform.MvxLoaderPluginRegistry loaders)

    {
        loaders.AddConventionalPlugin<MyCompany.MvvmCross.Plugins.Mega.WindowsPhone.Plugin>();

        base.AddPluginsLoaders(loaders);
    }

Note that Convention is used here - so it's important that MyCompany.MvvmCross.Plugins.Mega.WindowsPhone.Plugin implements the WindowsPhone plugin for MyCompany.MvvmCross.Plugins.Mega.PluginLoader

3.2 MonoDroid

For MonoDroid clients, you don't need to add this setup step - because MonoDroid has less Assembly.Load restrictions than the other platforms - and ao can load the plugins from file. But for this to work, it's important that the assembly names match - if the PluginLoader is AlphaPage.MvvmCross.Plugins.Mega.PluginLoader then the conventions will try to load the plugin from MyCompany.MvvmCross.Plugins.Mega.Droid.dll

4. Use of plugin services

After this setup, then applications should finally be able to access the plugins by:
  • adding a reference the Shared core portable library
  • at some time calling MyCompany.MvvmCross.Plugins.Mega.PluginLoader.Instance.EnsureLoaded()
  • then accessing the individual services using this.GetService() or this.GetService()

5. Pure portable plugins

Some plugins can be 'pure portable'

In this case they don't need any specialization for each platform, and no step 3 is required.

For an example of this, see the Json implementation - https://github.com/slodge/MvvmCross/tree/vnext/Cirrious/Plugins/Json

How to bind an Android ImageView to an image loaded from Monodroid Assets

From StackOverflow 

Quick answer:

  • if your Android image file is stored in assets/images/i1.png
  • then make sure it is marked as an AndroidAsset
  • then your path needs to be images/i1.png

Longer answer:

Ideally your ViewModel should be platform independent and not know about View concerns.

So your ViewModel might perhaps expose a property like:

 private GameState _state;
 
public GameState State
 
{
     get
{ return _state; }
     set
{ _state = value; RaisePropertyChanged(() => State); }
 
}

where GameState is an enumeration like:

 public enum GameState
 
{
     
Stopped,
     
Running,
     
Paused,
     
GameOver
 
}

you might then have images representing these states in an assets structure like:

/assets/gamestates/stopped.png
/assets/gamestates/running.png
/assets/gamestates/paused.png
/assets/gamestates/gameover.png

where each of those files is marked with BuildAction of AndroidAsset.

To then display the correct image in the UI, you would need a value converter like:

public class GameStateConverter
   
: MvxBaseValueConverter
{
   
public override object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
   
{
       
return string.Format("gamestates/{0}.png", ((GameState)value).ToString().ToLower());
   
}
}

mapped in using a Converters wrapper like:

public class Converters
{
   
public readonly GameStateConverter GameState = new GameStateConverter();
}

which is configured in setup.cs using:

    protected override IEnumerable<Type> ValueConverterHolders
   
{
        get
{ return new[] { typeof(Converters) }; }
   
}

With this in place, then your axml binding statement would be:

    {'AssetImagePath':{'Path':'State', 'Converter':'GameState'}}

For an alternative approach using resources instead of assets, see MvxButtonIconBinding in Іssue with binding to GridLayout to Android

Tuesday, October 16, 2012

Building mvvmcross projects in visual studio 2012

I've recently been building almost all my vNext mvvmcross projects in all of "Visual Studio 2010", "Visual Studio 2012" and in MonoDevelop.

My basic setup for this has been the same one described in: http://slodge.blogspot.co.uk/2012/09/mvvmcross-vnext-portable-class.html
  • I've installed VS, the Portable Class Library VS2010 extensions, VS2012, MonoDroid and VSMonoTouch
  • I've then altered the registered Portable Library platforms just a little in order for Droid and Touch to both work under the magical Profile 104
All in all, the setup works reasonably well - well enough indeed that I decided to switch over to vNext as the default GitHub branch now.

However, working this way, I do admit I've experienced several small problems, and I thought I might list them here in case they help others:
  1. VSMonoTouch doesn't yet work in VS2012 - so there's no iOS support in VS2012 yet. There are some people who have got this working over on GitHub, but I've held off implementing anything in case Xamarin pull some magic out of the hat during this week's MonkeySpace conference.
  2. MonoDevelop refuses to open any solution that Visual Studio 2012 has opened - this is due to a Version number - 12 instead of 11 - at the start of the .sln file - it takes seconds to fix in NotePad++, but it is annoying
  3. There are some issues building MonoDroid portable projects in VS2012 sometimes - sometimes it takes 2 builds rather than 1 - no idea what this is yet - it feels like its somehow not quite hooking up the dependencies correctly between PCL and MonoDroid. I've not seen this problem at all in VS2010.
  4. There are some issues sometimes on putting breakpoints in the PCL code - again I've not identified what this is completely yet - and I have a feeling it may be a more general MonoDroid bug, and nothing to do with VS2012.
  5. I have seen some TargetFrameworkAttribute errors in VSMonoTouch projects - see http://slodge.blogspot.co.uk/2012/09/the-type-or-namespace-name.html for my hacky solution.

However.... overall, that's it - I'm up and running and Resharper is working too :)

Trying to build up the list of mvvmcross in the wild....

For the mvx readme on GitHub, I'm trying to build up a list of known users of MvvmCross.

Does anyone have any examples they would like included?

So far...

Public projects that have used this framework include:

and listed under International inspiration are:

Any more links... please post them as comments - once the spam filter lets you past then I'll include them as items.

Thanks :)

Monday, October 15, 2012

vNext is now the default branch on GitHub

I've now made vNext the default branch on GitHub - https://github.com/slodge/MvvmCross/

This means the portable library code is now the default view.

I do anticipate that this may cause some problems, especially while the MonoDevelop/Monotouch tooling is still a little behind the curve. If anyone needs the original version, then the old non-portable version is stil there and is still labelled master - https://github.com/slodge/MvvmCross/tree/master

However, I hope that most of you will be able to join me in developing portable code :)

The future is portable - and I'm really glad to be switching over to vNext - it's much cleaner and even more powerful than the first generation of MvvmCross.

Collection binding in vNext - now switched to include IEnumerable

Until a stackoverflow question today, I hadn't actually remembered that the Android MvvmCross binding insists that classes use IList instead of IEnumerable collections.

The reason for this decision was simple - performance.

Within Android, the ListView Adapter class relies on random access to the collection and it needs to use values like Count. This is why IList was selected for binding - because IList provides the [position] operator and it provides the Count property, whereas IEnumerable can only provide random element access and element counting through step-by-step enumeration - which, obviously, is slow

However.... despite this, it appears that Silverlight and Wpf databinding allows users to use IEnumerable collections - and I *guess* it does this in a less than optimal way, but that this doesn't matter for small collection sizes...

So... Mvx Droid is now following the same route - the binding will use IList when it's available, but will drop down to step-by-step enumeration when IList is not available. This means that if you want to, then your Android code can now bind to IEnumerable. However, just beware that this is never going to be super efficient!

For a look at the changes in details, see https://github.com/slodge/MvvmCross/commit/2b2be9878b0c84d12fdf6ba5b9e7d022b4ce6e42

Piggybank for Hadoop on Azure

I needed some time conversion scripts for my Pig on HadoopOnAzure...

I looked around and could only find this http://www.bimonkey.com/2012/08/no-piggybank-for-pig-on-hadoop-on-azure/

Fortunately, building one didn't seem too bad.... basically you just have to:
  • have JDK 7 installed
  • download ant from Apache
  • set up some path variables (ANT_HOME and JAVA_HOME)
  • download the Pig source
  • open a cmd prompt, cd to the pig directory, then type `ant`
  • cd to the piggybank directory and type `ant`
  • download the Jodatime source
  • cd to the Jodatime directory and type `ant`
If this feels like too much effort... then here's some readymade jar's - http://slodge.com/pig/piggybank.zip

Sunday, October 14, 2012

Changes to IoC in vNext

Just wanted to post a quick warning about a change to IoC in vNext.

In all previous code, the simple IoC system worked using generic interfaces and generic extension methods.

So, for example, to import a service like IMyService, then the user would write code like:
    public class TwitterViewModel          : MvxViewModel          , IMvxServiceConsumer<ITwitterSearchProvider>
      {
          private ITwitterSearchProvider TwitterSearchProvider
          {
              get { return this.GetService<ITwitterSearchProvider>(); }
          }
      }  
This has some duplication of the generic target - and it can make class declarations quite long winded... To make the code 'cleaner', in vNext, I've removed the generic part from the interface - so now code like this will work:

    public class TwitterViewModel          : MvxViewModel
          , IMvxServiceConsumer
      {
          private ITwitterSearchProvider TwitterSearchProvider
          {
              get { return this.GetService<ITwitterSearchProvider>(); }
          }
      }  

Some Project Templates for vNext

I've just uploaded some VisualStudio project templates to http://slodge.com/mvx/mvxTemplates.zip

If you download these then they should allow you to get new vNext projects up and running a bit more quickly.

Basically, these templates are created using the Visual Studio 'Export' menu item, and these templates are based on the code in: https://github.com/slodge/MvvmCross/tree/vnext/Templates

To use them:
- unzip the wrapper file to get to each individual item
- copy them to C:\Users\Stuart\Documents\Visual Studio 11\My Exported Templates
- or to C:\Users\Stuart\Documents\Visual Studio 2010\My Exported Templates
- that should (I hope) automatically import the templates into visual studio
- so when you do "new project" then type mvvmCross in the top right
- the options like MyApplication.Core should then automatically appear in the new project options:

http://i.imgur.com/d2GhO.png

There will be problems in the projects you create - especially there will be references which don't link together perfectly... but these should be small problems to resolve by hand - so it should be possible to get new projects up and running really quickly!

//

I think it's almost time to ship vNext ...

Friday, October 12, 2012

A sqlite example (vNext portable)

I thought I'd try some sqlite-net - especially following on from the discussion on the Xamarin forum, and from ConceptDev's link to his portable port of Tasky - https://github.com/conceptdev/xamarin-samples

My initial attempt was to try to remove the #if statements from sqlite-net by using inheritance - see https://gist.github.com/3857333

However.... Craig (ConceptDev) pointed out to me that heading this way would mean that it would be harder to keep up to date with changes, fixes, etc in sqlite-net

So instead of inheriting out of sqlite-net, I adapted sqlite-net so it used an interface:

    public interface ISQLiteConnection : IDisposable
    {
        string DatabasePath { get; }
        bool TimeExecution { get; set; }
        bool Trace { get; set; }
        int CreateTable<T>();
        ISQLiteCommand CreateCommand(string cmdText, params object[] ps);
        int Execute(string query, params object[] args);
        List<T> Query<T>(string query, params object[] args) where T : new();
        IEnumerable<T> DeferredQuery<T>(string query, params object[] args) where T : new();
        List<object> Query(ITableMapping map, string query, params object[] args);
        IEnumerable<object> DeferredQuery(ITableMapping map, string query, params object[] args);
        ITableQuery<T> Table<T>() where T : new();
        T Get<T>(object pk) where T : new();
        bool IsInTransaction { get; }
        void BeginTransaction();
        void Rollback();
        void Commit();
        void RunInTransaction(Action action);
        int InsertAll(System.Collections.IEnumerable objects);
        int Insert(object obj);
        int Insert(object obj, Type objType);
        int Insert(object obj, string extra);
        int Insert(object obj, string extra, Type objType);
        int Update(object obj);
        int Update(object obj, Type objType);
        int Delete<T>(T obj);
        void Close();
    }


This then made the changes to Sqlite-net really simple - just maybe 4 or 5 classes to add inheritance to, and 4 or 5 methods to add `where T : new()` constraints too.

-

The result is this portable plugin: vnext/Cirrious/Plugins/Sqlite
With a MonoDroid implementation in vnext/Cirrious/Plugins/Sqlite/Cirrious.MvvmCross.Plugins.Sqlite.Droid/SQLiteNet.cs

Note that I've only done the Droid implementation of this plugin so far, but I think all of the rest - WP7, MonoTouch, and WinRT (and beyond) should be straight-forward - and that the same SQLiteNet.cs file (#if's and all) will be link-shared between those plugins.

-

As a first example of use I created a 'simple' style project
- SimpleDroidSql.Core
- SimpleDroidSql

This simple example isn't a good architecture (all the logic is in the ViewModel), but it does make it easy(ish) to see the SQLite connection at work - e.g. you can see how it is created in the ViewModel :

        public ListViewModel()
        {
            Cirrious.MvvmCross.Plugins.Sqlite.PluginLoader.Instance.EnsureLoaded();
            var factory = this.GetService<ISQLiteConnectionFactory>();
            var connection = factory.Create("SimpleList");
            connection.CreateTable<ListItem>();
            _items = new DatabaseBackedObservableCollection<ListItem, int>(connection, listItem => -listItem.Id);
        }

And you can see how it is queried in my DatabaseBackedObservableCollection<T> :

        public void Add(T item)
        {
            _connection.Insert(item);
            RaiseCollectionChanged();
        }

        public int Count { get { return _connection.Table<T>().Count(); }}

        public bool Remove(T item)
        {
            var result = _connection.Delete(item);
            return true;
        }

        public T this[int index]
        {
            get { return _connection.Table<T>().OrderBy(_sortOrder).Skip(index).FirstOrDefault(); }
            set { throw new NotImplementedException(); }
        }

Note - DatabaseBackedObservableCollection<T> is definitely not optimal code -but it works well for a demo :)

And the MonoDroid specific code.... it is, of course, just XML with bindings:

[Activity(Label = "SimpleDroidSql", MainLauncher = true, Icon = "@drawable/icon")]
public sealed class MainActivity : MvxSimpleBindingActivity<ListViewModel>
{

   public MainActivity()  
   {
   }


   protected override void OnCreate(Bundle bundle)  
   {
   
   base.OnCreate(bundle);
      if (ViewModel == null)
   
     ViewModel = new ListViewModel();

      // Set our view from the "main" layout resource         
      SetContentView(Resource.Layout.Main);
   }
}


Loading an xml list binding of:

    local:MvxBind="{'ItemsSource':{'Path':'Items'}}"  
And list item templates that include:


 local:MvxBind="{'Text':{'Path':'Name'}}"
 local:MvxBind="{'Text':{'Path':'WhenCreated'}}"
 

Really glad this conversation happened - adding a proper SQLite layer has been on the TODO list for MvvmCross for a long time.

I'll update this further with the other platforms at some point soon - and I may also add Vici plugins at some point too - I've used their sqlite wrapper before - it worked really well - http://viciproject.com/wiki/projects/coolstorage/home

Tuesday, October 09, 2012

An attempt at making SQLite-net more portable

One of the challenges I've had in making portable C# code is using SQLite across all platforms.
 
To get around this I tried a quick adapter layer approach:
 
 
Still thinking about this....
 
And I bet this embed doesn't work:
<script src="https://gist.github.com/3857333.js"> </script>
 
More discussion over on:

Sunday, October 07, 2012

Portable Class Library discussion in MonoTouch/MonoDroid

Anyone who's interested in the discussion on whether PCLs or linked-file libraries should be used across MonoTouch and MonoDroid, take a look at:
 
 
It's an interesting topic.... I feel this especially as I've been fighting against gaps in the PCL tooling for the last 6 months!
 
At a practical level, is the linked-file approach using #if's better than a PCL approach using Dependency Injection?
 
Comments and opinions on

Friday, October 05, 2012

Error 13 /platform:anycpu32bitpreferred is not a valid setting for option /target:library or /target:module

If you find this error while compiling VS2012 Windows 8 (aka Window Store and/or Windows Metro) applications:
 
Error 13 /platform:anycpu32bitpreferred is not a valid setting for option /target:library or /target:module 
 
then the solution seems to be to edit the csproj file to remove <Prefer32bit>true</Prefer32bit>
 
 

Open the project file in notepad and remove <Prefer32Bit>true</Prefer32Bit> then reload it  (you can also right click on the project in solution explorer, choose unload project, right click on the project again, choose edit someproject.csproj, after making the edit, save, and right click and reload.

Thursday, September 27, 2012

Here's how I setup a fork....

Here's how I setup a fork:

I'm still mainly using http://gitextensions.googlecode.com/. A 2 minute guide to how I work is:

      • choose fork on here to create your own copy of mvx
      • assuming you're on windows, then install http://gitextensions.googlecode.com/ selecting default options along the way
      • once installed, then choose Remotes>Putty>Generate Key to create a new SSH2 Key - save the private key somewhere and copy the public key to https://github.com/settings/ssh
  • after that... with perhaps just a little bit more fiddling through "Load Key" dialogs, then you should be able to:
    • clone your fork to a local git repository on your own hard drive
    • edit the code
    • commit changes in your fork back to you local git repository
    • push changes in your fork up to your github git repository

Tuesday, September 25, 2012

Downloading dynamic Excel files from ASP.Net MVC

Have been using the wonderful EPPlus library today - http://epplus.codeplex.com/

With it, is was really quick and easy to generate an ASP.Net MVC Controller action that allowed me to generate an excel spreadsheet with embedded data and with a chart! And with no Office or COM automation nastiness on the server :)

WooHoo :)


using System;
using System.Web.Mvc;
using Newtonsoft.Json;
using OfficeOpenXml;
using OfficeOpenXml.Drawing.Chart;
using OfficeOpenXml.Style;

namespace MyApp.Controllers
{
    public class ExportController : Controller
    {
        [Authorize]
        public ActionResult SafeDownload()
        {
            using (var package = new ExcelPackage())
            {
                package.Workbook.Worksheets.Add("Test");
                ExcelWorksheet ws = package.Workbook.Worksheets[1];
                ws.Name = "Test"; //Setting Sheet's name
                ws.Cells.Style.Font.Size = 11; //Default font size for whole sheet
                ws.Cells.Style.Font.Name = "Calibri"; //Default Font name for whole sheet

                //Merging cells and create a center heading for out table
                ws.Cells[1, 1].Value = "Sample DataTable Export"; // Heading Name
                ws.Cells[1, 1, 1, 10].Merge = true; //Merge columns start and end range
                ws.Cells[1, 1, 1, 10].Style.Font.Bold = true; //Font should be bold
                ws.Cells[1, 1, 1, 10].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; // Aligmnet is center

                for (var i = 1; i < 11; i++)
                {
                    for (var j = 2; j < 45; j++)
                    {
                        var cell = ws.Cells[j, i];

                        //Setting Value in cell
                        cell.Value = i * (j - 1);
                    }
                }

                var chart = ws.Drawings.AddChart("chart1", eChartType.AreaStacked);
                //Set position and size
                chart.SetPosition(0, 630);
                chart.SetSize(800, 600);

                // Add the data series.
                var series = chart.Series.Add(ws.Cells["A2:A46"], ws.Cells["B2:B46"]);

                var memoryStream = package.GetAsByteArray();
                var fileName = string.Format("MyData-{0:yyyy-MM-dd-HH-mm-ss}.xlsx", DateTime.UtcNow);
                // mimetype from http://stackoverflow.com/questions/4212861/what-is-a-correct-mime-type-for-docx-pptx-etc
                return base.File(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName);
            }
        }
    }
}

The type or namespace name 'TargetFrameworkAttribute' does not exist...

Since installing VS2012, I've seen a few of these errors in my VS2010 VSMonoTouch (Visual Studio MonoTouch) builds:

The type or namespace name 'TargetFrameworkAttribute' does not exist in the namespace 'System.Runtime.Versioning' (are you missing an assembly reference?)   

To workaround these, I've had to resort to adding a hacky line to my project files to prevent the attribute being generated and to keep them compiling:

<!-- somewhere after the Import of Microsoft.somelanguage.targets -->
<Target Name="GenerateTargetFrameworkMonikerAttribute" />

This hack from an answer in http://stackoverflow.com/questions/3104356/in-visual-studio-2010-why-is-the-netframework-version-v4-0-assemblyattributes-c

Cross platform tasks/intents?

I got asked a question on StackOverflow... http://stackoverflow.com/questions/12564272/making-mono-cross-platform-support-for-task-intent/12564548#12564548

-

I have a application for WP7 and Android, and this application must have supporthas support for "any" connection type (WiFi, NFC, Bluetooth etc)

I have then created a layered model with MVVMCross https://github.com/slodge/MvvmCross

I have an interface for example Android Bluetooth must implement

interface IConnectionService
{
    List<TargetDevice> FindDevices();
    void Connect(TargetDevice targetDevice);
    void Disconnect();
    byte[] Read();
    void Write(byte[] command);
}

I want to be able to request the user for Bluetooth Access, but I do not want to program my UI specifically to Android Bluetooth, so the view and view-model should not know which intent is used, all this should be handled by the class implementing IConnectionService

The issue is that it should also work for Windows Phone which do not use intents, it uses tasks, so how do I make an interface that allows me to make either a Intent request or a task request without anyone knowing what type of request is needed?

----------

This is similar to the way MvvmCross allows users to make phone calls.

When using this pattern:

The ViewModel code consumes a platform independent service via an interface - e.g.:

public interface IMvxPhoneCallTask
{
    void MakePhoneCall(string name, string number);
}

consumed by

    protected void MakePhoneCall(string name, string number)
    {
        var task = this.GetService<IMvxPhoneCallTask>();
        task.MakePhoneCall(name, number);
    }

in https://github.com/slodge/MvvmCross/blob/master/Sample%20-%20CirriousConference/Cirrious.Conference.Core/ViewModels/BaseViewModel.cs

The app setup code injects the platform specific implementation for the interface - e.g:

        RegisterServiceType<IMvxPhoneCallTask, MvxPhoneCallTask>();

In WP7 - this uses the PhoneCallTask - https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/WindowsPhone/Platform/Tasks/MvxPhoneCallTask.cs

public class MvxPhoneCallTask : MvxWindowsPhoneTask, IMvxPhoneCallTask
{
    #region IMvxPhoneCallTask Members    

    public void MakePhoneCall(string name, string number)
    {
        var pct = new PhoneCallTask {DisplayName = name, PhoneNumber = number};
        DoWithInvalidOperationProtection(pct.Show);
    }

    #endregion
}

In Droid - it uses the ActionDial Intent - https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Android/Platform/Tasks/MvxPhoneCallTask.cs

public class MvxPhoneCallTask : MvxAndroidTask, IMvxPhoneCallTask
{
    #region IMvxPhoneCallTask Members

    public void MakePhoneCall(string name, string number)
    {
        var phoneNumber = PhoneNumberUtils.FormatNumber(number);
        var newIntent = new Intent(Intent.ActionDial, Uri.Parse("tel:" + phoneNumber));
        StartActivity(newIntent);
    }


    #endregion
}

In Touch - it just uses Urls - https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Touch/Platform/Tasks/MvxPhoneCallTask.cs

public class MvxPhoneCallTask : MvxTouchTask, IMvxPhoneCallTask
{
    #region IMvxPhoneCallTask Members

    public void MakePhoneCall(string name, string number)
    {
        var url = new NSUrl("tel:" + number);
        DoUrlOpen(url);
    }

    #endregion
}


In the vnext version of mvvmcross, this approach is further formalized using plugins - see a brief introduction to these in the 'going portable' presentation at http://slodge.blogspot.co.uk/2012/06/mvvm-mvvmcross-monodroid-monotouch-wp7.html

For example, in vNext the phone call code above is contained in the PhoneCall plugin - https://github.com/slodge/MvvmCross/tree/vnext/Cirrious/Plugins/PhoneCall


One of the challenges of your task may be the word "any" - differences in platform implementation might make it hard to define a cross-platform interface that works across all the platforms for any one of NFC, Bluetooth, etc, let alone all of them.

Wednesday, September 19, 2012

Knockout - NO_MODIFICATION_ALLOWED_ERR: DOM Exception 7

If you're doing any konockout.js data-bind work in Chrome and you see the error:

NO_MODIFICATION_ALLOWED_ERR: DOM 
Exception 7

Then check that you haven't done:

<input data-bind='text: property' />

when you meant to do:

<input data-bind='value: property' />

Doh!

Saturday, September 15, 2012

MvvmCross vNext - portable class libraries - back on track - 4 complete samples building and running...

UPDATE - 19 Dec 2012 - LATEST INFO IS ON http://slodge.blogspot.com/2012/12/cross-platform-winrt-monodroid.html

----------

Three months on from hitting some severe stumbling blocks in the Portable Library support within MonoTouch, I'm pleased to say that the last two weeks have seen huge leaps forwards in the vNext version.

Right now, the Portable Library layer is now running well under all of WP7, MonoDroid and MonoTouch :)

There are still some tooling issues... but overall, this is now working really well - so I'd like to invite users to have a play with the new projects!

Although there is some significant tooling hackery required to get portable library mvvm working, once you've done the initial hackery, then this shouldn't affect your existing workspaces and you should then be able to build and run portable versions of:
  • BestSellers (WP7, Droid, Touch)
  • CustomerManagement (WP7, Droid, Touch)
  • SimpleBinding (Droid, Touch)
  • Tutorial (WP7, Droid, Touch)
... and you might be able to run even more... :)

---

And the benefits for doing this are....

1. Simpler project structures:

2. Automated cross-platform refactoring - e.g. using resharper

3. Simpler porting to new platforms

4. A new plugin structure which makes mvvmcross lighter (smaller executables), which provides developers with more choice and which makes contributing new IoC modules more straightforward - now anyone can provide and consume new "plugins"

---

If you are interested in all this, then here's the instructions:

----

To get the source...

- you will need to download from the vNext branch on https://github.com/slodge/MvvmCross/tree/vnext

- the only working solution in this download is the MvvmCross_All.sln file - which contains all the projects - portable and platform specific.

---

To get your Windows development environment working with this portable branch:

- assuming you start from Visual Studio 2010, Windows Phone SDK 7.5, MonoDroid on a PC

1. Install the Portable Library tools for the VS2010 - http://visualstudiogallery.msdn.microsoft.com/b0e0b5e9-e138-410b-ad10-00cb3caf4981

2. Install VisualStudio 2012 on the same PC... this updates the Portable Library tools to include v2 PCL support (which includes some MVVM/DataBinding helpers)


1 and 2. Install the latest PCL plugin from http://visualstudiogallery.msdn.microsoft.com/b0e0b5e9-e138-410b-ad10-00cb3caf4981 - thanks to @dsplaisted for the update.

3. Install VSMonoTouch - https://github.com/follesoe/VSMonoTouch
- be sure to also copy across the v1.0 MonoTouch framework assemblies in the instructions there

4. Follow instructions based on http://jpobst.blogspot.co.uk/2012/04/mono-for-android-portable-libraries-in.html
- these say to install a file called "MonoAndroid,Version=v1.6+.xml" in "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.0\Profile\Profile104\SupportedFrameworks" with content:



BUT PLEASE NOTE - the target directory is Profile104

5. Install a similar file called "VSMonoTouch,Version=v1.0+.xml" in the same directory and for its content use:


(Note: this file is even hackier than the MonoDroid one - it points the portable tools at Full .Net v1.0 in line with what the VSMonoTouch plugin does!)

After you have done this.... then you should be able to load and run the WP7 and Droid samples within MvvmCross_All.sln 

... and you should also be able to build MonoTouch solutions too. And you should be able to refactor across all 3 platforms!

---

For the Mac:

Assuming you are starting with MonoDevelop with MonoTouch installed on a Mac

1. Follow the instructions in http://stackoverflow.com/questions/12041290/monodevelop-is-it-possible-to-switch-pcls-compiler/12062589#12062589

This is only a temporary hack - it's a workaround for: https://bugzilla.xamarin.com/show_bug.cgi?id=6649

2. Before opening the MvvmCross_All.sln solution, you need to run a search and replace in "*.csproj" files - this search and replace will:
- search for : <targetframeworkprofile>Profile104</targetframeworkprofile>
- replace with : <targetframeworkprofile>Profile1</targetframeworkprofile>

This is only a temporary hack - it's a workaround for: https://bugzilla.xamarin.com/show_bug.cgi?id=7173
3. Sometimes (if I've checked in the wrong .sln file version) then before opening the MvvmCross_All.sln solution, you may need to change the first line from

Microsoft Visual Studio Solution File, Format Version 12.00
to

Microsoft Visual Studio Solution File, Format Version 11.00
This is only a temporary hack - it's a workaround for: https://bugzilla.xamarin.com/show_bug.cgi?id=4919


After you've done these 3 steps.... then you should be able to:
- open the solution
- switch to the Debug|iPhoneSimulator branch
- run the BestSellers, CustomerManagement, SimpleDialogBinding, and Tutorial projects - other projects currently still have unresolved problems.

---

Further Notes....

- I'll be trying to get this branch fully working in the next month (that's my aim!)
- My intention is to switch all future MvvmCross development across to this portable approach 
- If this happens, then I expect the existing non-portable tree will only get bug fixes - not new features.
- The exact timing of any switchover may depend a bit on tool changes from both Microsoft and Xamarin (and it may depend on clashes in my work and leisure time too!)
- There are a number of class and namespace breaking changes in the vNext (portable libraries) branch - most notably:
-- all Cirrious.MvvmCross.Android namespaces have moved to Cirrious.MvvmCross.Droid - this is to avoid name clashing issues with the global::Android namespace.
-- FirePropertyChanged has become RaisePropertyChanged - as this seems to be the more normal method name
- There are a number of fixes on the master branch which are not yet on the vnext branch
- There are a number of changes still to make in the vnext branch - e.g. IMvxServiceConsumer might switch to a simpler IMvxServiceConsumer - following a request/suggestion from @dsplaisted
- There are several dead files and directories left in the tree at present - mainly left over after refactoring - these will get tidied away soon.
- I've not yet tried much WinRT, console or PSS development on the vnext branch - so don't be surprised if those projects don't build or work!
- If anyone wants to help - with code, documentation, tools, samples or suggestions, then you are very welcome - just get in touch.
- As ever, bugs to GitHub issues please, and questions to StackOverflow :)

Wednesday, September 05, 2012

Bootstrap + ASP.Net MVC - [Bootstrap] "object has no method on" error

Just a quickie

If you add Bootstrap to an ASP.Net MVC project and then see a few "object [Object] has no method on" errors which cause $.ready to fail, then.... check your jquery version 

Shifting to:
    <script src="http://code.jquery.com/jquery-latest.js"></script>  
solved it for me :)
  

A helper on getting MonoTouch building Portable Library code

I've not had a lot of time to play with this yet, but in the last 24 hours I've managed to get a lot more of the Mvx vNext portable code building using the hint:

You may be able to fix this by editing the file /Library/Frameworks/Mono.framework/Versions/Current/lib/mono/xbuild/Microsoft/Portable/v4.0/Microsoft.Portable.CSharp.targets, finding the PropertyGroup that sets
MonoTouchAnd to it, adding the lines:
smcs/Developer/MonoTouch/usr/bin

Found this hint via http://stackoverflow.com/questions/12041290/monodevelop-is-it-possible-to-switch-pcls-compiler/12062589#12062589 and https://bugzilla.xamarin.com/show_bug.cgi?id=5329 - wish I'd found it months ago (note to self - don't give up so easy next time!)

For Mac newbies, note that this file is in the root from the hard disk (not from the user) and that you will need to edit file (and folder?) permissions in order to edit it - you can do this from finder using 'more info'.


Tuesday, September 04, 2012

A cross platform dropbox client written in mvvmcross

Rune Grimstad (@runegri) has published this sample.

https://github.com/runegri/CrossBox

More to follow when I've played with it :)

Sunday, September 02, 2012

Monocross now moved to github

Just discovered that monocross - the cross platform library that I started mvvmcross from - is now on GitHub

If you prefer mvc to mvvm, or if you need webkit support, then follow it at: https://github.com/ToeJam/MonoCross

Thursday, August 30, 2012

Some useful mvvmcross links

A great 3 part tutorial - in French - really good walk through:

http://www.e-naxos.com/Blog/post/2012/08/26/Strategie-de-developpement-Cross-Platform–Partie-3.aspx-3.aspx

Mono for Android data binding for spinner controls

http://blog.ostebaronen.dk/2012/08/mvvmcross-binding-spinner.html

An enterprise app using MVX:

http://www.aviva.co.uk/ratemydrive/

Featured in: http://www.bbc.co.uk/iplayer/episode/b01m9396/Click_18_08_201/ - ffwd to 9 minutes in

A picker based element for monotouch.dialog:

https://gist.github.com/3552565