{"id":16352159,"url":"https://github.com/vincenth-net/quickcross","last_synced_at":"2025-09-17T18:31:04.924Z","repository":{"id":11662113,"uuid":"14170430","full_name":"VincentH-Net/QuickCross","owner":"VincentH-Net","description":"Quickly create cross-platform MVVM apps in C# for iOS (Xamarin), Android (Xamarin), Windows Store and Windows Phone","archived":false,"fork":false,"pushed_at":"2015-10-08T11:13:22.000Z","size":5597,"stargazers_count":54,"open_issues_count":1,"forks_count":12,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-08-23T05:54:18.746Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/VincentH-Net.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-11-06T11:11:35.000Z","updated_at":"2024-11-28T07:37:24.000Z","dependencies_parsed_at":"2022-08-29T20:21:57.476Z","dependency_job_id":null,"html_url":"https://github.com/VincentH-Net/QuickCross","commit_stats":null,"previous_names":["macawnl/quickcross"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/VincentH-Net/QuickCross","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VincentH-Net%2FQuickCross","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VincentH-Net%2FQuickCross/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VincentH-Net%2FQuickCross/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VincentH-Net%2FQuickCross/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/VincentH-Net","download_url":"https://codeload.github.com/VincentH-Net/QuickCross/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VincentH-Net%2FQuickCross/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275640704,"owners_count":25501640,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-17T02:00:09.119Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T01:25:10.516Z","updated_at":"2025-09-17T18:31:04.006Z","avatar_url":"https://github.com/VincentH-Net.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"NuGet package: [http://nuget.org/packages/QuickCross](http://nuget.org/packages/quickcross)\r\n\u003e NOTE: This readme describes version 2.0, which is the current NuGet release.\r\n\r\n# QuickCross #\r\nQuickly build cross-platform apps in C# with the MVVM pattern and [Xamarin](http://xamarin.com/).\r\n![QuickCross for Android](https://raw.github.com/MacawNL/QuickCross/master/assets/QuickCross.gif)\r\n\r\n## Summary ##\r\n**QuickCross** is a lightweight (no binaries) cross-platform MVVM pattern to quickly build native Xamarin.iOS, Xamarin.Android, Windows Phone and Windows Store Apps with shared C# code.\r\n\r\nQuickCross provides data binding for Android and for iOS. It accelerates development with scaffolders and code snippets, also for a single platform app. For cross-platform apps QuickCross increases code sharing with an Application-Navigator pattern.\r\n\r\nQuickCross aims to leave you in full control; it does not get in the way if you want to do some things differently, and you can simply extend or modify it.\r\n\r\n\u003e Versions before 2.0 were published under the name **MvvmQuickCross**. They will continue to be supported at the [existing MvvmQuickCross GitHub repository](https://github.com/MacawNL/MvvmQuickCross), and [the existing MvvmQuickCross NuGet packages](http://nuget.org/packages/mvvmquickcross) will remain available.\r\nUpgrading from MvvmQuickCross to QuickCross is simple; see [here](#how-to-upgrade-from-mvvmquickcross-to-quickcross) how.\r\n\r\n## Why another cross-platform Mvvm framework? ##\r\nWe developed QuickCross after trying [MvvmCross](http://github.com/mvvmcross). We were looking for an Mvvm framework to let us maximize code sharing across Windows Store, Windows Phone, Xamarin.iOS and Xamarin.Android platforms, and MvvmCross was the most promising option for us. In our opinion MvvmCross is a mature framework that offers a lot of functionality and has an impressive architecture. However, MvvmCross is also binary based (you use it as dlls in your app) and we found it to be too heavily engineered for our needs. It has lots of nuget packages and dlls, a plugin system, uses IoC, has many internal layers etc. It's a *lot* to take in - there are over 40(!) [video's](http://www.youtube.com/playlist?list=PLR6WI6W1JdeYSXLbm58jwAKYT7RQR31-W) on it.\r\n\r\nIf we were to build an app with MvvmCross and we would run across something - anything, either big or small - that is not supported (yet) out of the box, we would either need to wait for someone else to add it, or take on an additional - potentially complex - project to create a new plugin for the framework or even a modified version of existing framework component(s). We did not want to put ourselves in this situation. Not finding a suitable alternative, we set out to create a **lightweight**, pragmatic framework with a focus on **productivity** and **simple customization**: *QuickCross*.\r\n\r\nQuickCross is not based on or derived from MvvmCross; it solves some of the same problems but is quite different. QuickCross supports most common data binding scenario's out of the box and lets you implement other scenario's by adding a few lines of code in your app project. It is simple in both usage and internal implementation; it is distributed in a single NuGet package, included as source in your app projects, and this single readme page contains the complete reference plus an example app tutorial.\r\n\r\nWhile QuickCross has some unique [features](#features) (e.g. customizable code templates and scaffolder commands to quickly generate views, viewmodels and navigation code), MvvmCross has been around longer and offers more functionality, e.g. value converters and WPF and Mac platform support. If you are looking for a cross-platform Mvvm framework, we do encourage you to check out all options and decide for yourself which is best for your needs and capabilities. Happy app building!\r\n\r\n## News ##\r\n**August 28, 2014**\r\nGood news for QuickCross fans: **QuickCross 3.0** is coming, with support for [Xamarin Forms](http://xamarin.com/forms)!\r\n\r\nThe QuickCross 2.5 beta release was put on hold when it was nearly completed, due to a high pressure mobile project (which of course used QuickCross - see [here](http://vincenth.net/blog/archive/2014/08/26/poollie-wk-2014-lessons-learned-from-developing-a-successful-multi-platform-app-with-xamarin.aspx) for lessons learned). Then **Xamarin Forms** came out, a game changer for cross-platform native development - with the MVVM pattern already built in. This required a re-evaluation of QuickCross.\r\n\r\nFortunately QuickCross has always been lightweight, and it offers features that speed up working with the MVVM pattern in any form, e.g. with code generation. In contrast to heavier MVVM frameworks (see [here](http://forums.xamarin.com/discussion/17754/xamarin-forms-with-mvvmcross)), QuickCross can speed up Xamarin Forms development without adding a lot of unnecessary overhead.\r\n\r\nOne of the strengths of Xamarin Forms is that it leaves all options open: you can mix and match technologies in the same app, so you can implement some (parts of) views with 'regular' Xamarin and some with Xamarin Forms. QuickCross will follow in the same spirit; in addition to Xamarin Forms you will have the option to mix-in the lightweight data-binding support for pre-Forms Xamarin.\r\n\r\nWith the course determined, work on QuickCross 3.0 has now started in earnest. It is too soon to give an expected release date yet, but ... it should be quick ;-).\r\n\r\n**April 28, 2014**\r\nQuickCross is nearing the 2.5 beta release with a lot of new features! Version 2.5 will add:\r\n\r\n- NavigateToPreviousView to navigate back to the previous view on all platforms\r\n- Dialog support for iOS (MonoTouch.Dialog) and Android (DialogFragment for AlertDialog and custom view dialogs)\r\n- Custom binding actions for iOS and Android, to e.g. simply convert or combine viewmodel property values\r\n- Bind to any object in iOS and Android - no longer limited to just UIView or View; now you can e.g. also bind to UI elements in navigation bars\r\n- Bind to any property or field by name in iOS and Android - no longer code required to bind to non-default field/property\r\n- Optimized release build size with a custom linker description on iOS and Android - save 15 MB on your package.\r\n- Fixed iOS custom table view source support defect\r\n\r\n**Jan 14, 2014**\r\nQuickCross release 2.0 final is published!\r\n\r\n**Jan 3, 2014**\r\nQuickCross release 2.0 beta is published. Adds simple iOS data binding and an iOS example app.\r\n\r\n## Features ##\r\n\r\n### Lightweight and easy to modify ###\r\nNo binaries, only adds a code snippets file and C# source files to your projects.\r\n\r\n### Scaffolders ###\r\nQuickly add viewmodels and views from within the Visual Studio package manager console with the New-ViewModel and New-View [commands](#commands).\r\n\r\n### Viewmodel code snippets ###\r\nQuickly add data-bindable properties and commands to viewmodels with [code snippets](#code-snippets).\r\n\r\n### Application-Navigator pattern ###\r\nMaximize code sharing, including navigation logic, across platforms.\r\n![QuickCross Pattern](https://raw.github.com/MacawNL/QuickCross/master/assets/quickcross_pattern.png)\r\n\r\nSee [these slides](http://www.slideshare.net/VincentHoogendoorn/mvvm-quickcross-windows-phone-devday-2013) for an overview of the QuickCross pattern.\r\n\r\n### Simple iOS data binding ###\r\nSpecify [data bindings in iOS](#ios-data-binding) with a custom runtime attribute in XCode, or in C# code. Supports coded views, Xib views and StoryBoard views. Create performant data-bound table views without writing a table view source.\r\n\r\n\u003e See the [QCTest1 app source](https://github.com/MacawNL/QuickCross/tree/master/Examples/QCTest1) in this repository for an example of a coded view, a Xib view, and a StoryBoard view with a UITableView, including navigation.\r\n\r\nOverride virtual methods in your view controller to handle specific property change events with custom code instead of with data binding. Or customize how the data binding sets a value to a specific control. Add a few lines of code to make new view types data bindable.\r\n\r\n### iOS lifecycle management ###\r\nPrevent memory leaks by [automatically removing and re-adding event handlers](#ios-view-lifecycle-support) during the iOS view life-cycle.\r\n\r\n### Simple Android data binding ###\r\nSpecify [data bindings in Android](#android-data-binding) by using naming conventions, tag markup or code. Use observable collections. Create performant data-bound list views without writing an adapter.\r\n\r\nOverride virtual methods in your activity or fragment to handle specific property change events with custom code instead of with data binding. Or customize how the data binding sets a value to a specific control. Add a few lines of code to make new view types data bindable.\r\n\r\n### Android lifecycle management ###\r\nPrevent [memory leaks in Xamarin](http://docs.xamarin.com/guides/android/application_fundamentals/activity_lifecycle) by [automatically removing and re-adding event handlers](#android-view-lifecycle-support) during the Android activity life-cycle.\r\n\r\n## Documentation and Examples ##\r\nThe remainder of this Readme describes:\r\n\r\n-  **Getting Started** [steps](#getting-started)\r\n-  The complete **QuickCross reference**\r\n-  How to build a simple **Twitter example app** for [Android](#android) and [iOS](#ios) using data binding\r\n-  Upgrade [instructions](#how-to-upgrade-to-a-later-version-of-quickcross)\r\n\r\nSee this more elaborate [Cloud Auction example app](https://github.com/MacawNL/QuickCross/tree/master/Examples/CloudAuction) for how you can use QuickCross. These blog posts describe the full steps and explanation on how to build this app:\r\n\r\n- [Creating a Cross-Platform Native App Using MvvmQuickCross and Xamarin, Part 1: Cross-Platform Code and Windows 8 App](http://vincenth.net/blog/archive/2013/08/30/creating-a-cross-platform-native-app-using-mvvmquickcross-and-xamarin-part-1-cross-platform-code-and-windows-8-app.aspx)\u003cbr /\u003e\r\n- [Creating a Cross-Platform Native App Using MvvmQuickCross and Xamarin, Part 2: Android App](http://vincenth.net/blog/archive/2013/10/23/creating-a-cross-platform-native-app-using-mvvmquickcross-and-xamarin-part-2-android-app.aspx)\r\n\r\n\u003e Note that these blog posts were written for MvvmQuickCross, which is the predecessor to QuickCross. However, except for the name change and some minor details the posts content is also valid for QuickCross. Time permitting, these blog posts will be updated to match the updated example source.\r\n\r\n\r\n## Getting Started ##\r\nTo create an app with QuickCross, follow these steps:\r\n\u003e Note: for how to upgrade an app to a newer version of QuickCross, see [here](#how-to-upgrade-to-a-later-version-of-quickcross).\r\n\r\n1. In Visual Studio, create a new solution with an application project for the **platform** (Windows Store, Windows Phone, Android, iOS) that you are most productive with. Add a class library project **for the same platform** to the solution. Reference the class library from the application project.\r\n\r\n\t**Note for Android:** Set the **API level** to 12 (Android 3.1) or higher in the Project properties for both projects. This is needed to support the Fragment view type. You can target lower API versions by either using the [Android Support Library](http://developer.android.com/tools/support-library/index.html) (which is supported in Xamarin) or by removing the Fragment view base class and template from the QuickCross folder in your application project.\r\n\r\n\t**Notes for iOS:**\r\n\t1) Select iOS 5.0 or higher (set the **Deployment Target** to 5.0 or higher in the **iOS Application** tab of the Project Properties window for the application project). This is needed to specify data binding parameters in XCode, which relies on a User-Defined Runtime Attribute named Bind.\r\n\t\r\n\t2) Check the **Allow unsafe code** option (in the **Build** tab of the Project Properties window) for the application project. This is needed for the QuickCross data binding code, which uses the Objective C runtime library to read the Bind User-Defined Runtime Attribute.\r\n\r\n\t3) Verify that in the Configuration Manager (menu Build) the Active solution platform is set to the emulator or device that you want to target (e.g. iPhoneSimulator).\r\n\r\n\t**Note for Windows Phone:** Select Windows Phone OS 8.0 or higher.\r\n\r\n2. Install the [QuickCross NuGet package](http://nuget.org/packages/quickcross)\r\n\r\n\tThe available QuickCross commands are now displayed in the package manager console.\r\n\tType \"**Get-Help *command* -Online**\" for details.\r\n\r\n3. In the Visual Studio package manager console (*menu View | Other Windows*) enter:\r\n\r\n\t**[Install-Mvvm](#install-mvvm)**\r\n\r\n\tAn QuickCross folder is now added to your library project and your application project, and a few application-specific projects items are generated and opened in Visual Studio.\r\n\r\n\t**Note** that the package installation uses the first part of the solution filename (before the first dot) as the **application name** for naming new project items and classes.\r\n\r\n4. Import the C# code snippets from the QuickCross\\Templates\\QuickCross.snippet file in your class library project into Visual Studio with the Code Snippets Manager (see [how](http://msdn.microsoft.com/en-us/library/ms165394\\(v=vs.110\\).aspx)). If you get a \"Snippet With Same Name Exists\" dialog, select Overwrite. \r\n\t\r\n\t**Note** do not select the QuickCross\\Templates folder itself as the location to import snippets **to**; that may prevent the snippets to be imported correctly, as this would mean copying the snippets file over itself.\r\n\r\n5. Add new views and viewmodels with the [`New-View`](#new-view) and [`New-ViewModel`](#new-viewmodel) commands.\r\n\r\n6. Add data-bindable properties and commands to your viewmodels with the [code snippets](#code-snippets).\r\n\r\n7. Check the TODO comments in the Visual Studio Task List *(menu View | Tast List)* to find guidance on how to complete the viewmodel, application and navigator classes. You can also check out the CloudAuction example app in this GitHub repository (TODO: create iOS implementation).\r\n\r\n## Adding platforms ##\r\nTo code your app for more platforms:\r\n\r\n\r\n1. Create a new solution for each platform, with a class library project for that platform and an application project for that platform, just like you did for the first platform.\r\n\r\n2. Add all code files from the existing class library project to the class library project for the new platform.\r\n\r\n3. Install the QuickCross NuGet package and execute the Install-Mvvm command again (it won't overwrite existing files).\r\n\r\n4. Code the views, navigator and any platform specific service implementations in the application project.\r\n\r\n## Commands ##\r\nAfter installing the QuickCross NuGet package, the below commands are available in the Visual Studio **Package Manager Console**.\r\n\r\n**Note** that except for Install-Mvvm, anything that these commands do can also be done by hand; the manual steps are documented inline in the files that you add to your projects with Install-Mvvm. This makes it possible to create your initial solutions in Visual Studio, and then continue working in [Xamarin Studio](http://xamarin.com/studio) for Android or iOS, if you prefer that.\r\n\r\n### Install-Mvvm ###\r\n\r\n```posh\r\nInstall-Mvvm \r\n```\r\nInstalls the QuickCross support files in both your library project and your application project, in a subfolder QuickCross. The files in the QuickCross folders are not application specific; unless you want to modify the standard QuickCross templates, code snippets and/or functionality you don't need to edit these.\r\n\r\nInstall-Mvvm also generates a few application-specific project items for you. The generated project items are opened in the Visual Studio editor for your inspection.\r\n\r\n**Note** that Install-Mvvm uses the first part of the solution filename (before the first dot) as the **application name** for naming generated project items, classes, properties and methods.\r\n\r\nCheck the **TODO comments** in the Visual Studio **Task List** to find guidance on how to complete the generated project items.\r\n\r\nInstall-Mvvm will not overwrite existing files or code. If you want to recreate the default files, remove the files that you want to recreate before running Install-Mvvm.\r\n\r\n### New-View ###\r\n\r\n```posh\r\nNew-View [-ViewName] \u003cstring\u003e [[-ViewType] \u003cstring\u003e] [[-ViewModelName] \u003cstring\u003e] [-WithoutNavigation]\r\n```\r\nGenerates a new view.\r\n\r\nThe specified `ViewName` will be suffixed with \"View\", and the specified `ViewModelName` will be suffixed with \"ViewModel\". If no ViewModelName is specified, it will be the same as the ViewName. If the viewmodel does not exist, it will be generated with the `New-ViewModel` command.\r\n\r\n- On Windows Phone or Windows Store, the `ViewType` can be `Page` (default) or `UserControl`. \r\n- On Android, it can be `MainLauncher`, `Activity` (default) or `Fragment`.\r\n- On iOS, it can be `Code` (default), `Xib`, `StoryBoard` or `StoryBoardTable`.\r\n\r\n\t\u003e See the [QCTest1 app source](https://github.com/MacawNL/QuickCross/tree/master/Examples/QCTest1) in this repository for an example of a coded view, a Xib view, and a StoryBoard view with a UITableView, including navigation.\r\n\r\nThe specified view type determines which view templates are used. You can find these templates in the QuickCross\\Templates folder of your application project. You can simply modify these templates or add your own (which is better) by adding similar named files there.\r\n\r\nUnless the `-WithoutNavigation` switch is specified, New-View will also add basic navigation code to the navigator and application classes. The -WithoutNavigation switch is useful when creating views such as list item views, that do not need to navigated to directly from the application class.\r\n\r\nE.g. this command:\r\n\r\n```posh\r\nNew-View Person\r\n```\r\nwill generate:\r\n\r\n- A `PersonView` view markup file + class\r\n- A `PersonViewModel` viewmodel class\r\n- A `PersonViewModelDesign` viewmodel class\r\n- A `PersonViewModel` property in the application class\r\n- A `NavigateToPersonView()` method signature in the navigator interface\r\n- A `NavigateToPersonView()` method implementation in the navigator class\r\n- A `ContinueToPerson()` method in the application class\r\n\r\nNow the only thing needed to display the view, bound to the viewmodel, is to call the `ContinueToPerson()` method on the application.\r\n\r\nCheck the **TODO comments** in the Visual Studio **Task List** to find guidance on how to complete the generated project items.\r\n\r\nNew-View will not overwrite existing files or code. If you want to recreate files or code fragments, remove the existing one(s) first.\r\n  \r\n### New-ViewModel ###\r\n\r\n```posh\r\nNew-ViewModel [-ViewModelName] \u003cstring\u003e [-NotInApplication]\r\n```\r\nGenerates a new viewmodel. You can use this command to create viewmodels without creating any corresponding views (yet).\r\n\r\nThe specified `ViewModelName` will be suffixed with \"ViewModel\".\r\n\r\nUnless the `-NotInApplication` switch is specified, New-ViewModel will also add a property to contain the instance of the viewmodel to the application class. The application class will then be responsible for providing an initialized viewmodel instance before navigating to the corresponding view. The -NotInApplication switch is useful when creating viewmodels such as list item viewmodels, that do not need to be instantiated and initialized directly by the application class.\r\n\r\nE.g. this command:\r\n\r\n```posh\r\nNew-ViewModel Person\r\n```\r\nwill generate:\r\n\r\n- A PersonViewModel viewmodel class\r\n- A PersonViewModelDesign viewmodel class\r\n- A PersonViewModel property in the application class\r\n\r\nCheck the **TODO comments** in the Visual Studio **Task List** to find guidance on how to complete the generated project items.\r\n\r\nNew-ViewModel will not overwrite existing files or code. If you want to recreate files or code fragments, remove the existing one(s) first.\r\n\r\n### Customizing and Extending Command Templates ###\r\nAs Described above in the usage of the ViewType parameter of the [New-View command](#new-view), you can add your own code and markup templates for custom view types by adding properly named files in the `QuickCross\\Templates` folder of your application project.\r\n\r\nThe code and markup template files are named:   `_VIEWNAME_\u003cview type name\u003eView.*`\r\nIf no markup file for the specified view type is found, the default markup file `_VIEWNAME_View.*` is used, so you do not need to have multiple copies of the same markup template.\r\n\r\nOf course you can also modify existing templates in the `QuickCross\\Templates` folder.\r\n\r\nThe library project also contains a viewmodel template that can be customized, at `QuickCross\\Templates\\_VIEWNAME_ViewModel.cs`.\r\n\r\nIn addition to the template files, you can also modify the inline code templates in the Application, INavigator and Navigator. Inline templates are used to add properties and methods in these files when a new viewmodel or view is added. An example of an inline template in the Application class for a `view` is:\r\n\r\n```csharp\r\npublic sealed class _APPNAME_Application : ApplicationBase\r\n{\r\n\t...\r\n\r\n    /* TODO: For each view, add a method (with any parameters needed) to initialize its viewmodel\r\n     * and then navigate to the view using the navigator, like this:\r\n\r\n    public void ContinueTo_VIEWNAME_()\r\n    {\r\n        if (_VIEWNAME_ViewModel == null) _VIEWNAME_ViewModel = new _VIEWNAME_ViewModelDesign();\r\n        RunOnUIThread(() =\u003e _navigator.NavigateTo_VIEWNAME_View());\r\n    }\r\n     * Note that the New-View command adds the above code automatically \r\n     * (see http://github.com/MacawNL/QuickCross#new-view). */\r\n}\r\n```\r\nThe format of an inline template is:\r\n\r\n1. An empty line. The instantiated code will be placed directly before this line\r\n2. A line starting with `/* TODO: For each \u003ctemplate name\u003e,`\r\n3. Optionally some lines starting with ` * `\r\n4. Lines of actual template code\r\n5. Optionally some lines starting with ` * `\r\n6. A line ending with  ` */`\r\n\r\nCurrently the template name can be `view` or `viewmodel`.\r\n\r\n## Code Snippets ##\r\nWhen you run the Install-Mvvm command, the C# code snippets file `QuickCross\\Templates\\QuickCross.snippet` is added to your class library project. When you import this snippets file into Visual Studio with the Code Snippets Manager (see [how](http://msdn.microsoft.com/en-us/library/ms165394\\(v=vs.110\\).aspx)), the code snippets described below become available for coding viewmodels.\r\n\r\nNote that the code snippets and their parameters have intellisense when you invoke them in the Visual Studio C# editor.\r\n\r\nTo instantiate a code snippet, place your cursor on an empty line in the `#region Data-bindable properties and commands` of a viewmodel class .cs file, type the code snippet shortcut (e.g. `propdb1`), and press Tab twice. Now you can enter the parameters of the code snippet (press Tab to cycle through all parameters). Press Enter to complete the snippet instance.\r\n\r\n### propdb1 ###\r\nAdds a one-way data-bindable property to a Viewmodel. You can specify the property type and name.\r\n### propdbcol ###\r\nAdds a one-way data-bindable collection property, a corresponding `(name)HasItems` property and an `Update(name)HasItems()` method to a Viewmodel. You can specify the generic collection type (e.g. `ObservableCollection` or `List`), the collection element type and the property name.\r\n\r\nIf you want specific UI elements in your view to only be visible when the collection has elements (e.g. a list of error messages), you can use the HasItems property to bind to the visibility of those UI elements. In that case, you should also call the UpdateHasItems() method after you have added or removed items (this is necessary even if this is an ObservableCollection).\r\n\r\n**Note** that if you suffix a collection property name with **\"List\"**, you can benefit from the [list data binding naming convention in Android](#list-itemssource).\r\n\r\n### propdb2 ###\r\nAdds a two-way data-bindable property to a Viewmodel. You can specify the property type and name.\r\n### propdb2c ###\r\nAdds a two-way data-bindable property and a `On(name)Changed()` method for custom setter code to a Viewmodel. You can specify the property type and name.\r\n### cmd ###\r\nAdds a data-bindable command to a Viewmodel. You can specify the command name, which will be suffixed with **\"Command\"**.\r\n### cmdp ###\r\nAdds a data-bindable command with a parameter to a Viewmodel. You can specify the command name, which will be suffixed with **\"Command\"**, the parameter type and the parameter name.\r\n\r\n## iOS ##\r\nBelow is an overview of using QuickCross with Xamarin.iOS.\r\n\r\n### Create an iOS App ###\r\nHere is how to create an iOS Twitter app that demonstrates simple data binding:\r\n\u003e Note that the complete source for this Twitter app example is available in this repository, [here](http://github.com/MacawNL/QuickCross/tree/master/Examples/Twitter).\r\n\r\nThis is what the Twitter app will look like in iOS:\r\n\r\n![Twitter example on iPhone](https://raw.github.com/MacawNL/QuickCross/master/Examples/Twitter/assets/twitter_ios.png)\r\n\r\nSo let's get started.\r\n\r\n1.  Create a working iOS app by following steps 1 though 4 of [Getting Started](#getting-started) above; make sure you follow the **iOS notes** there!\r\n\r\n\tThese are the project templates and project names you should use while following these steps: an `Empty Project` project from the **iOS\\iPhone** project templates named `Twitter`, and a `Xamarin.iOS Library Project` project from the **iOS** project templates named `Twitter.Shared`.\r\n\r\n\tIn the **iOS Application** tab of the application project properties window, set the **Application name**, **Identifier** and **Version** to some meaningful value. In the **Application** tab of the library project properties window, add the suffix `.ios` to the **Assembly name** - this is useful if you want to build for multiple platforms in the same project folder.\r\n\r\n2.  Remove the `Class1.cs` file that was included by the Xamarin.iOS Library Project template\r\n\r\n3.  Do what the **TODO comments** in the Visual Studio **Task List** say for the file **AppDelegate.cs**. This will ensure that on application startup QuickCross is initialized and the initial view is displayed.\r\n\r\n4.  Now you can run the app on your device and test the example MainView that was generated by the Install-Mvvm command.\r\n\r\n\t\u003e If you already created the shared code library for the example Twitter app in the [Create an Android App](#create-an-android-app) tutorial, you can include the existing C# files from the Android library project also in your iOS library project. Then skip to step 9 below.\r\n\r\n5.  Create a `Models` folder in your Twitter.Shared project and create this `Tweet.cs` class in it:\r\n\r\n\t```csharp\r\n\tusing System;\r\n\tnamespace Twitter.Shared.Models\r\n\t{\r\n\t    public class Tweet\r\n\t    {\r\n\t        public string Text { get; set; }\r\n\t        public string UserName { get; set; }\r\n\t        public DateTime CreatedAt { get; set; }\r\n\t    }\r\n\t}\r\n\t```\r\n\r\n6.  In `ViewModels\\MainViewModel.cs` in your library project, in the `#region Data-bindable properties and commands`, remove the example property and command add these properties and commands with the indicated [code snippets](#code-snippets):\r\n\t\r\n    \u003ctable\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003e\u003cb\u003eSnippet\u003c/b\u003e\u003c/td\u003e\u003ctd\u003e\u003cb\u003eParameters\u003c/b\u003e\u003c/td\u003e\u003ctd\u003e\u003cb\u003eGenerated code\u003c/b\u003e\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003e\u003ca href=\"#propdb2c\"\u003epropdb2c\u003c/a\u003e\u003c/td\u003e\u003ctd\u003eTweet Tweet\u003c/td\u003e\u003ctd\u003e\r\n\t\t\t\tpublic Tweet Tweet { ... }\u003cbr /\u003e\r\n\t\t\t\tprivate void OnTweetChanged() { ... }\r\n            \u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003e\u003ca href=\"#propdbcol\"\u003epropdbcol\u003c/a\u003e\u003c/td\u003e\u003ctd\u003eObservableCollection Tweet TweetList\u003c/td\u003e\u003ctd\u003e\r\n\t\t\t\tpublic ObservableCollection\u003cTweet\u003e TweetList  { ... }\u003cbr /\u003e\r\n\t\t\t\tpublic bool TweetListHasItems { ... }\u003cbr /\u003e\r\n\t\t\t\tprotected void UpdateTweetListHasItems() { ... }\r\n            \u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003e\u003ca href=\"#cmd\"\u003ecmd\u003c/a\u003e\u003c/td\u003e\u003ctd\u003eDelete\u003c/td\u003e\u003ctd\u003e\r\n\t\t\t\tpublic RelayCommand DeleteCommand { ... }\u003cbr /\u003e\r\n\t\t\t\tprivate void Delete() { ... }\r\n            \u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003e\u003ca href=\"#propdb2c\"\u003epropdb2c\u003c/a\u003e\u003c/td\u003e\u003ctd\u003estring Text\u003c/td\u003e\u003ctd\u003e\r\n\t\t\t\tpublic string Text { ... }\u003cbr /\u003e\r\n\t\t\t\tprivate void OnTextChanged() { ... }\r\n            \u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003e\u003ca href=\"#propdb1\"\u003epropdb1\u003c/a\u003e\u003c/td\u003e\u003ctd\u003eint CharactersLeft\u003c/td\u003e\u003ctd\u003e\r\n\t\t\t\tpublic int CharactersLeft { ... }\r\n            \u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003e\u003ca href=\"#cmd\"\u003ecmd\u003c/a\u003e\u003c/td\u003e\u003ctd\u003eSend\u003c/td\u003e\u003ctd\u003e\r\n\t\t\t\tpublic RelayCommand SendCommand { ... }\u003cbr /\u003e\r\n\t\t\t\tprivate void Send() { ... }\r\n           \u003c/td\u003e\r\n        \u003c/tr\u003e\r\n    \u003c/table\u003e\r\n    \t\r\n7.  Add this code in the generated `MainModel` methods:\r\n\t\t\r\n\t```csharp\r\n    public MainViewModel()\r\n    {\r\n        TweetList = new ObservableCollection\u003cTweet\u003e();\r\n        OnTweetChanged();\r\n        Text = \"\";\r\n    }\r\n\t\r\n    private void OnTweetChanged()\r\n    {\r\n        DeleteCommand.IsEnabled = (Tweet != null);\r\n    }\r\n\r\n    private void Delete()\r\n    {\r\n        TweetList.Remove(Tweet);\r\n        Tweet = null;\r\n    }\r\n\r\n    private void OnTextChanged()\r\n    {\r\n        CharactersLeft = 140 - Text.Length;\r\n        SendCommand.IsEnabled = (Text.Length \u003e 0 \u0026\u0026 CharactersLeft \u003e= 0);\r\n    }\r\n\r\n    private void Send()\r\n    {\r\n        var newTweet = new Tweet { Text = this.Text, CreatedAt = DateTime.Now, UserName=\"Me\" };\r\n        TweetList.Insert(0, newTweet);\r\n        Tweet = newTweet;\r\n        Text = \"\";\r\n    }\r\n\t```\r\n\r\n8.  The `MainViewModel.cs` file also contains a `MainViewModelDesign` class where you can put some hardcoded viewmodel data. Put this code in the MainViewModelDesign constructor:\r\n\t\t\r\n\t```csharp\r\n    public MainViewModelDesign()\r\n    {\r\n        Text = \"Text for a new tweet\";\r\n        var now = DateTime.Now;\r\n        TweetList.Insert(0, new Tweet { \r\n\t\t\tText = \"Creating a simple Twitter app with QuickCross\", \r\n\t\t\tUserName = \"Me\", CreatedAt = now.AddSeconds(-115) });\r\n        TweetList.Insert(0, new Tweet { \r\n\t\t\tText = \"Created a solution with an application and a library project\", \r\n\t\t\tUserName = \"Me\", CreatedAt = now.AddSeconds(-63) });\r\n        TweetList.Insert(0, new Tweet { \r\n\t\t\tText = \"Added Tweet model class\", \r\n\t\t\tUserName = \"Me\", CreatedAt = now.AddSeconds(-45) });\r\n        TweetList.Insert(0, new Tweet { \r\n\t\t\tText = \"Added viewmodel properties and commands with code snippets\", \r\n\t\t\tUserName = \"Me\", CreatedAt = now.AddSeconds(-25) });\r\n        TweetList.Insert(0, new Tweet { \r\n\t\t\tText = \"Added some hardcoded design data for the viewmodel\", \r\n\t\t\tUserName = \"Me\", CreatedAt = now.AddSeconds(-1) });\r\n    }\r\n\t```\r\n\r\n9.  We are going to replace the **MainView**, which was generated as a **Code** view, with a **Storyboard** view. First delete the file `MainView.cs` in the application project, and then enter this command in the Package Manager Console:\r\n\r\n\t```posh\r\n\tNew-View Main -ViewType StoryBoard\r\n\t```\r\n\t\r\n\tThis will generate a MainView.TODO.cs file, with TODO comments on how to complete the view with Xamarin Studio and XCode. \r\n\r\n10. Make your source accessible from your build Mac (e.g. on a network share, via source control or just copy it with a USB stick), and open your solution on the Mac in Xamarin Studio.\r\n\r\n11. In Xamarin Studio, set the build configuration for the application project to **Debug | iPhoneSimulator** or **Debug | iPhone**, and set the application project as the startup project.\r\n\r\n12. In Xamarin Studio, add an **Empty iPhone Storyboard** and name it `Main` (could be any name). Open the storyboard with the **Source Code Editor** and then replace its contents by copy+pasting the contents from this [Main.storyboard file](https://github.com/MacawNL/QuickCross/blob/master/Examples/Twitter/assets/Main.storyboard). Save the storyboard and close its editor window. The storyboard now contains only the Twitter UI, without any custom classes or bindings.\r\n\r\n\tYou could create this file yourself by adding an **Empty iPhone Storyboard** project item named `Main` (this could be any name) in Xamarin Studio, double-clicking to open it in XCode and then adding a view controller, with a view at the bottom containing a text field, label and two buttons. Then add a table view with a table cell and add three labels in the cell content.\r\n\r\n13. Now follow the guidance in the **MainView.TODO.cs** comments to create the **MainView.cs** and **MainView.designer.cs** (you can skip adding your view in XCode since it is already in the downloaded storyboard).\r\n\r\n14. Open the **Info.plist** file in Xamarin Studio, and set the **Main Interface** to the **Main** storyboard.\r\n\r\n15. To dismiss the onscreen keyboard when you tap outside the edit view, add a [KeyboardDismissGestureRecognizer](https://gist.github.com/VincentH-Net/8352290) to your main window in FinishedLaunching. Now you can run the app - the Twitter UI should display (without data, because we still need to add bindings).\r\n\r\n16. Now let's add the data binding parameters in XCode to complete the app. In XCode, add the **Bind** custom runtime attribute to these controls (see [how](#ios-binding-parameters-in-xcode)) and set it's value as indicated:\r\n\t\r\n\t\u003ctable\u003e\r\n\t\t\u003ctr\u003e\u003ctd\u003e\u003cb\u003eView\u003c/b\u003e\u003c/td\u003e\u003ctd\u003e\u003cb\u003eBind value\u003c/b\u003e\u003c/td\u003e\u003c/tr\u003e\r\n\t\t\u003ctr\u003e\u003ctd\u003eRound Style Text Field - What's up?\u003c/td\u003e\u003ctd\u003eText, Mode=TwoWay\u003c/td\u003e\u003c/tr\u003e\r\n\t\t\u003ctr\u003e\u003ctd\u003eLabel - 140\u003c/td\u003e\u003ctd\u003eCharactersLeft\u003c/td\u003e\u003c/tr\u003e\r\n\t\t\u003ctr\u003e\u003ctd\u003eButton - Send\u003c/td\u003e\u003ctd\u003eSendCommand, Mode=Command\u003c/td\u003e\u003c/tr\u003e\r\n\t\t\u003ctr\u003e\u003ctd\u003eButton - Delete\u003c/td\u003e\u003ctd\u003eDeleteCommand, Mode=Command\u003c/td\u003e\u003c/tr\u003e\r\n\t\t\u003ctr\u003e\u003ctd\u003eTable View\u003c/td\u003e\u003ctd\u003eTweet, Mode=TwoWay {List ItemsSource=TweetList}\u003c/td\u003e\u003c/tr\u003e\r\n\t\t\u003ctr\u003e\u003ctd\u003eLabel - Me\u003c/td\u003e\u003ctd\u003eUserName\u003c/td\u003e\u003c/tr\u003e\r\n\t\t\u003ctr\u003e\u003ctd\u003eLabel - 10/25/2013 1:28:25 PM\u003c/td\u003e\u003ctd\u003eCreatedAt\u003c/td\u003e\u003c/tr\u003e\r\n\t\t\u003ctr\u003e\u003ctd\u003eLabel - My tweet text\u003c/td\u003e\u003ctd\u003eText\u003c/td\u003e\u003c/tr\u003e\r\n\t\u003c/table\u003e\r\n\r\n\tAs described [here](#list-itemtemplate), the default value for the List ItemTemplate binding parameter for our table view is TweetListItem (because we specified TweetList for the ItemsSource). Now set the (reuse) **Identifier** of the **Table View Cell** to to match the List ItemTemplate value: `TweetListItem`. Now the QuickCross `DataBindableUITableViewSource` can load the prototype cell that should be used for the tweet list items.\r\n\r\n17. **Save** the storyboard, switch back to Xamarin Studio and run the app. Test the MainView. Notice how the Send and Delete buttons are enabled and disabled based on the text length and selected item state, and how the characters remaining count is updated as you type. Also note how the selected list item is highlighted both from the UI when tapped, and from code when adding a new tweet.\r\n\r\nYou have created a working app with QuickCross. Note that the only code that you needed to write is in the viewmodel; no view controller or table view controller code is needed. To get data binding working, the markup specifies some binding parameters in the Bind.\r\n\r\n### iOS Data Binding ###\r\nAn iOS data binding is a one-on-one binding between an iOS `UIView`, such as a `UITextField` or `UIButton`, and a viewmodel property or command. You can specify bindings with (a combination of):\r\n\r\n1. Code in the controller that creates the containing view\r\n2. Segue identifiers\r\n3. Binding parameters in the `Bind` user-defined runtime attribute (of type `String`) in XCode (this is supported in iOS 5.0 or later)\r\n\r\nNote that for performance reasons, iOS data binding allows **no more than one view** (within the same rootview) to be bound to a property. If you need to update multiple views with the same property value, you can do that by overriding the `UpdateView()` method in your view controller class, and adding [a few lines of code](#binding-multiple-ios-views-to-a-viewmodel-property).\r\n\r\nFinally, note that **you do not need to use the QuickCross implementation of iOS data binding** if you prefer not to. You can subscribe to the standard .NET data binding events (`PropertyChanged` on viewmodels, `CanExecuteChanged` on `RelayCommand` viewmodel commands, and `CollectionChanged` on `ObservableCollection` viewmodel properties) from your code in any view type, and handle data binding any way you like. In this case you can keep using the [New-View command](#new-view), if you [add your own view template files](#customizing-and-extending-command-templates).\r\n\r\n#### iOS Binding Parameters in XCode ####\r\niOS `UIViews` do not have a native general-purpose property that can be used to specify binding parameters (such as the `Tag` property on Android `Views`). QuickCross solves this by adding support for a user-defined runtime attribute named `Bind`, of type `String`. In addition to using the Bind attribute, you can **bind a Storyboard Segue** to a command in XCode by setting the Segue identifier to the name of a viewmodel command.\r\n\r\nTo specify binding parameters in XCode through the Bind attribute:\r\n\r\n1. Select the object for which you want to specify the binding parameters (e.g. a `UILabel`, a `UIButton` or a `UITableView`).\r\n2. In the Identity Inspector (in the [utility area](https://developer.apple.com/library/mac/recipes/xcode_help-general/AbouttheUtilityArea/AbouttheUtilityArea.html)), under the **User Defined Runtime Attributes** header, click on the **+** to add an attribute.\r\n3. Change the **Key Path** of the new attribute to `Bind`, set the **Type** to `String`, and specify the binding parameters (see below for details) in **Value**.\r\n\r\nThese are the binding parameters that you can specify in the `Bind` attribute (linebreaks added for readability):\r\n\r\n    .|propertyName, Mode=OneWay|TwoWay|Command\r\n    {List ItemsSource=listPropertyName, ItemTemplate=listItemTemplateName, \r\n          AddCommand=addCommandName, RemoveCommand=removeCommandName, \r\n          CanEdit=false|true|propertyName|fieldName, CanMove=false|true|propertyName|fieldName}\r\n    \r\nAll of these parameters except the `.` or `propertyName` are optional. The iOS syntax is similar to the Android binding parameters syntax, however the {Binding ... } delimiters around .|propertyName and Mode are optional in iOS, since the Bind attribute will never contain anything else than binding parameters.\r\n\r\nNote that you can specify binding parameters through code in addition to / instead of in the Bind attribute.\r\n\r\n##### iOS Binding .|propertyName #####\r\nYou can specify a property name to bind to the property of a viewmodel. For bindings in list items that are not viewmodels, you can also specify the name of a field. Specify `.` to bind to the `ToString()` value of the viewmodel or list item object. Note that viewmodel commands are just a special type of viewmodel property, so you can use the propertyName to specify a command name as well.\r\n\r\n##### iOS Binding Mode #####\r\nIs `OneWay` by default. The mode specifies:\r\n\r\n- `OneWay` data binding where the viewmodel property updates the view - e.g. a display-only UILabel. The bound property can be generated with the propdb1 or propdbcol code snippet.\r\n- `TwoWay` data binding where the viewmodel property updates the view and vice versa, e.g. an editable UITextField. The bound property can be generated with the propdb2, propdb2c or propdbcol code snippet.\r\n- `Command` binding (e.g. a UIButton). The bound command can be generated with the cmd or cmdp code snippet.\r\n\r\nNote that you can also bind to the selected item in a `UITableView` with binding modes `TwoWay` or `Command`. When an item in the list is selected, the bound two-way property is set to the selected list item, or the bound command is invoked with the selected item as the command parameter. E.g. you can bind to a command to navigate to a detail view for the selected list item.\r\n\r\nThe `List` binding parameters are for use with views derived from `UITableView`. Support for collection views will be added soon.\r\n\r\n##### iOS List ItemsSource #####\r\nSpecifies the name of the viewmodel collection property that contains the list items. The property must implement the standard .NET `IList` interface. If the property also implements the standard .NET `INotifyCollectionChanged` interface (e.g an `ObservableCollection`), the view will automatically reflect added, replaced or removed items. The default value of ItemsSource is `propertyName` + \"**List**\".\r\n\r\nThe items in an ItemsSource viewmodel collection property can be:\r\n\r\n- An object with fields or properties (e.g. a POCO model object)\r\n- An value object, meaning an object that implements `ToString()` to present the value of the entire object as a human-readable text\r\n- A viewmodel object that has data-bindable properties and/or commands. This is also called **composite viewmodels**, which makes it possible to e.g. automatically display changes of individual fields within existing list item objects.\r\n\r\n##### iOS List ItemTemplate #####\r\nSpecifies the reuse identifier of the `UITableViewCell` that represents a list item. E.g. the value \"TweetListItem\" corresponds to the UITableViewCell with reuse identifier TweetListItem. You can specify the reuse identifier in XCode by selecting the UITableViewCell and then specifying the **indentifier** field in the **Attributes Inspector**. The default value of the ItemTemplate binding parameter is the value of `ItemsSource` + \"**Item**\".\r\n\r\n##### iOS List AddCommand #####\r\nSpecifies the name of the viewmodel command (e.g. AddProductCommand) that must be executed when the user selects the [Insertion control in table editing mode](https://developer.apple.com/library/ios/documentation/userexperience/conceptual/tableview_iphone/ManageInsertDeleteRow/ManageInsertDeleteRow.html). The command parameter will be the list item object at the insert position, if any. If this binding parameter is not specified, no command will be executed.\r\n\r\n##### iOS List RemoveCommand #####\r\nSpecifies the name of the viewmodel command (e.g. RemoveProductCommand) that must be executed when the user selects the [Deletion control in table editing mode](https://developer.apple.com/library/ios/documentation/userexperience/conceptual/tableview_iphone/ManageInsertDeleteRow/ManageInsertDeleteRow.html). The command parameter will be the list item object to be deleted. If this binding parameter is not specified, no command will be executed.\r\n\r\n##### iOS List CanEdit #####\r\nSpecifies whether list items can be edited in table view editing mode. The value `true` or `false` enables resp. disables editing for all items in the list. You can also enable or disable editing per item by adding a boolean property or field to each list item and then specifying the name of that property or field, e.g. `CanEdit=ProductIsEditable`. The default value of the CanEdit binding parameter is `false`.\r\n\r\n##### iOS List CanMove #####\r\nSpecifies whether list items can be [moved in table view editing mode](https://developer.apple.com/library/ios/documentation/userexperience/conceptual/tableview_iphone/ManageReorderRow/ManageReorderRow.html). The value `true` or `false` enables resp. disables moving for all items in the list. You can also enable or disable moving per item by adding a boolean property or field to each list item and then specifying the name of that property or field, e.g. `CanMove=ProductCanBeReordered`. The default value of the CanMove binding parameter is `false`.\r\n\r\n##### iOS Binding a Storyboard Segue to a Command #####\r\nYou can bind a Storyboard Segue to a Command in XCode by selecting the Segue and then setting the **Storyboard Segue identifier** field to the name of the command, e.g. ShowDetail. When preparing for the segue, the controller base class will call it's `GetCommandParameter()` method, which you can override in your controller class to provide a parameter for the command, and then the base class will execute the command (if a command with the same name as the Segue identifier exists in the viewmodel).\r\n\r\n#### iOS Binding Parameters in Code ####\r\nAs an alternative to using the Bind attribute in XCode, you can also specify bindings in code in an optional parameter of the `InitializeBindings()` method. The InitializeBindings method is implemented in the view controller base classes (e.g. `ViewBase` and `TableViewBase`), and it is called in your controller code from the `ViewDidLoad()` method. Here is an example of specifying binding parameters in code:\r\n\r\n```csharp\r\npublic override void ViewDidLoad()\r\n{\r\n\tbase.ViewDidLoad();\r\n\r\n    var button = ...\r\n    var label = ...\r\n\r\n    var bindingsParameters = new BindingParameters[] {\r\n        new BindingParameters { View = button, PropertyName = MainViewModel.COMMANDNAME_IncreaseCountCommand, Mode = BindingMode.Command },\r\n        new BindingParameters { View = label,  PropertyName = MainViewModel.PROPERTYNAME_Count }\r\n    };\r\n\r\n    InitializeBindings(View, ViewModel, bindingsParameters);\r\n}\r\n```\r\nYou can specify bindings in code for views created in code as well as views loaded from a xib or storyboard file (with outlets). You can specify some or all of the bindings, and in each binding some or all of the binding parameters. If you also specify parameters for a binding in Bind attribute in XCode, those will override or supplement any parameters that you specify in code.\r\n\r\nWhen you specify a binding for a `UITableView`, and it does not have it's `Source` property set, a new `DataBindableUITableViewSource` is created and assigned to the `UITableView` `Source` property automatically when you call `InitializeBindings()`. Alternatively, you can create an instance of a `DataBindableUITableViewSource` (derived) class in code and set that as the `Source` before you call `InitializeBindings()`.\r\n\r\n#### Customizing or Extending iOS Data Binding ####\r\nQuickCross allows you to simply modify or extend it with overrides in the view controller base classes `ViewBase` and `TableViewBase`, and in the `ViewDataBindings` class. You can also add more view controller base classes if you need to derive your controllers from other classes besides `UIViewController` and `UITableViewController`.\r\n\r\n##### Customizing Data Binding in iOS Views #####\r\nBy overriding the `OnPropertyChanged()` method in your view controller class, you can handle changes for specific properties yourself instead of with the standard data binding. E.g:\r\n\r\n```csharp\r\n// Example of how to handle specific viewmodel property changes in code instead of with (or in addition to) data binding:\r\nprotected override void OnPropertyChanged(string propertyName)\r\n{\r\n    switch (propertyName)\r\n    {\r\n        case OrderViewModel.PROPERTYNAME_DeliveryLocationListHasItems:\r\n            var hasItems = ViewModel.GetPropertyValue\u003cbool\u003e(OrderViewModel.PROPERTYNAME_DeliveryLocationListHasItems);\r\n            DeliveryLocationPicker.Hidden = !hasItems;\r\n            break;\r\n        default:\r\n            base.OnPropertyChanged(propertyName); break;\r\n    }\r\n}\r\n```\r\n\r\nYou can also override the `UpdateView()` method to change how the data binding mechanism sets a property value to a specific view (or modify multiple views based on the value etc.). E.g. to display a count value as a color, you could bind a `UILabel` named `CountColorLabel` to the `Count` property of a viewmodel, and then override `UpdateView()` like this:\r\n\r\n```csharp\r\npublic override void UpdateView(UIView view, object value)\r\n{\r\n    if (Object.ReferenceEquals(view, CountColorLabel))\r\n    {\r\n        int count = (int)value;\r\n\t\tview.BackgroundColor = count \u003e 0 ? UIColor.Green : UIColor.Red;\r\n        return;\r\n    }\r\n    base.UpdateView(view, value);\r\n}\r\n```\r\n\r\n\u003e Note that `UpdateView()` is also called for **data bindings in all list items** for all data-bound lists in your view. This makes it possible to customize data binding within list items with code in a normal view, instead of writing a custom data bindable table view source to put that customization code in.\r\n\r\n###### Binding multiple iOS views to a viewmodel property ######\r\nAnother scenario for overriding `UpdateView()` is when you want to update more than one view (within the same root view) from the same viewmodel property:\r\n\r\n```csharp\r\npublic override void UpdateView(UIView view, object value)\r\n{\r\n    if (Object.ReferenceEquals(view, ProductNameLabel))\r\n    {\r\n        base.UpdateView(view, value); // Set the single data-bound view\r\n        string text = value == null ? \"\" : value.ToString();\r\n        if (ProductName2Label.Text != text) ProductName2Label.Text = text;\r\n        return;\r\n    }\r\n    base.UpdateView(view, value);\r\n}\r\n```\r\n\r\nYou can also react to changes in lists that implement INotifyCollectionChanged (e.g. ObservableCollections) by overriding `OnCollectionChanged()` in your view:\r\n\r\n```csharp\r\npublic override void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)\r\n{\r\n    ...\r\n}\r\n```\r\nThe sender parameter is the collection. You could use this e.g. if you want to do some animation when items are added or removed in a list.\r\n\r\nFinally, you can modify or provide a parameter for a command when it is invoked, by overriding `GetCommandParameter()` in your view. E.g. you can pass the currently selected item in a table view to a command:\r\n\r\n```csharp\r\npublic override object GetCommandParameter(string commandName, object parameter = null)\r\n{\r\n    if (commandName == MainViewModel.COMMANDNAME_ViewItemCommand)\r\n    {\r\n        var indexPath = TableView.IndexPathForSelectedRow;\r\n        if (indexPath != null) return ViewModel.Items[indexPath.Row];\r\n    }\r\n    return base.GetCommandParameter(commandName);\r\n}\r\n```\r\n\r\n\u003e Note that `GetCommandParameter()` is also called for **commands in all list items that are viewmodels** for all data-bound lists in your view. This makes it possible to customize command parameter handling within list items with code in a normal view controller, instead of writing a custom data bindable table view source to put that customization code in.\r\n\r\n##### Adding New Data-Bindable iOS Table View Sources #####\r\nThe built-in QuickCross `DataBindableUITableViewSource` class supports a simple list with one section, that can be data-bound to collections that implement the standard .NET interfaces `IList` and optionally `INotifyCollectionChanged`, such as `ObservableCollection\u003cT\u003e`. The collection items can be viewmodels or they can be simple .NET objects with properties and/or fields. If you implement `ToString()` on the list item object, you can also bind to `.` to display the value of an entire list item as text.\r\n\r\nThe `DataBindableUITableViewSource` class also supports using the native iOS table view editing mode to add, remove, edit and move items within a table view.\r\n\r\nYou can create specialized table view sources (e.g. if you want to display a table with multiple sections), by implementing a class derived from `DataBindableUITableViewSource` and then overriding methods from `DataBindableUITableViewSource` and/or the underlying `UITableViewSource` class. The inline documentation on the virtual methods (e.g. `AddHandlers`, `RemoveHandlers`, `OnCollectionChanged` and `UpdateView`) in the `DataBindableUITableViewSource` [source](https://github.com/MacawNL/QuickCross/blob/master/SampleApp.ios/QuickCross/DataBindableUITableViewSource.cs) provides guidance on this.\r\n\r\nAs [described](#ios-binding-parameters-in-code) above, you can create an instance of your custom table view source and assign it to the `Source` property on a table view in the `ViewDidLoad()` method of your view controller, before you call `InitializeBindings()`.\r\n\r\n##### Adding New Data-Bindable iOS View Types #####\r\nOut of the box QuickCross has default data binding support for these view types:\r\n\u003e Note: in 2.0 beta these are very minimal, more will be added in 2.0 final release. Don't let this discourage you to try out the beta; it is really simple to add view types on the fly when you need them.\r\n\r\nOne-Way binding:\r\n\r\n- `UILabel`\r\n\r\nTwo-way binding:\r\n\r\n- `UITextField`\r\n- `UITextView`\r\n- `UITableView` and derived types\r\n\r\nCommand binding:\r\n\r\n- `UIButton`\r\n- `UITableView` and derived types\r\n\r\nTo make more control types data bindable, you can simply add a case to the appropriate switch statements in the `QuickCross\\ViewDataBindings.UI.cs` file in your application project, as indicated by the `// TODO: ` comments. E.g.:\r\n\r\n```csharp\r\npublic static void UpdateView(View view, object value)\r\n{\r\n    if (view != null)\r\n    {\r\n        string viewTypeName = view.GetType().FullName;\r\n        switch (viewTypeName)\r\n        {\r\n            // TODO: Add cases here for specialized view types, as needed\r\n            case \"Macaw.UIComponents.MultiImageView\":\r\n                {\r\n                    if (value is Uri) value = ((Uri)value).AbsoluteUri;\r\n                    var multiImageView = (Macaw.UIComponents.MultiImageView)view;\r\n                    multiImageView.LoadImageList(value == null ? null : new[] { (string)value });\r\n                }\r\n                break;\r\n\t\t\t...\r\n\t\t}\r\n\t}\r\n}\r\n```\r\nTo prevent memory leaks, be sure that if you register an event handler on a view in `AddCommandHandler()` or `AddTwoWayHandler()`, you also unregister that handler in `RemoveCommandHandler()` resp. `RemoveTwoWayHandler()`.\r\n\r\n##### Adding New iOS View Base Classes #####\r\nIf you need to derive your view controllers from other classes besides `UIViewController` and `UITableViewController`, you can simply copy the existing `QuickCross\\ViewBase.cs` or `QuickCross\\TableViewBase.cs` class and change the class that it derives from to the one that you need.\r\n\r\nE.g. to support data bindable classes derived from `UIPageViewController`, you would copy ViewBase.cs to PageViewBase.cs and just change \"UIViewController\" to \"UIPageViewController\" in these lines:\r\n\r\n```csharp\r\npublic class PageViewBase : UIPageViewController, ViewDataBindings.ViewExtensionPoints\r\n{\r\n    public PageViewBase() { }\r\n    public PageViewBase(string nibName, NSBundle bundle) : base(nibName, bundle) { }\r\n    public PageViewBase(IntPtr handle) : base(handle) { }\r\n\r\n    ...\r\n}\r\n```\r\nAnd then you can add some new constructor overloads to pass parameters to the base class constructor. Now you can use the new base class in your view:\r\n\r\n```csharp\r\npublic partial class ProductView : PageViewBase\r\n{\r\n\t...\r\n}\r\n```\r\nIt should take no more than a minute. To complete this, you could also [add a custom view template](#customizing-and-extending-command-templates) for this new view type.\r\n\r\n### iOS View Lifecycle Support ###\r\nTo prevent memory leaks, you should remove and re-add any handlers in your view controller code that you register for external events. External means: events that are not defined on the view controller itself (or on contained objects that are only referenced in the view controller such as a `UIButton`). E.g. an event handler for a viewmodel event or a service event needs to be removed and re-added like this. The QuickCross view controller base classes do this removing and re-adding automatically at the `ViewWillAppear()` and `ViewDidDisappear()` view lifecycle events. To have your own external event handlers added, removed and re-added at the appropriate times, you only need to override the `AddHandlers()` and `RemoveHandlers()` methods and add/remove your handlers there. E.g.:\r\n\r\n```csharp\r\nprotected override void AddHandlers()\r\n{\r\n    base.AddHandlers();\r\n    SomeExternalService.SomeEvent += SomeExternalService_SomeEvent;\r\n}\r\n\r\nprotected override void RemoveHandlers()\r\n{\r\n    SomeExternalService.SomeEvent -= SomeExternalService_SomeEvent;\r\n    base.RemoveHandlers();\r\n}\r\n```\r\nNote: Be sure to always call the base class method as well!\r\n\r\nYou should not call `AddHandlers()` yourself - that would mess up the base class tracking of added handlers. `AddHandlers()` is initially called by the view controller base class in the `InitializeBindings()` method, which you call in your view controller code in the `ViewDidLoad()` method.\r\n\r\n## Android ##\r\nBelow is an overview of using QuickCross with Xamarin.Android.\r\n\r\n### Create an Android App ###\r\nHere is how to create an Android Twitter app that demonstrates simple data binding:\r\n\u003e Note that the complete source for this Twitter app example is available in this repository, [here](http://github.com/MacawNL/QuickCross/tree/master/Examples/Twitter).\r\n\u003e For a more elaborate example, see this [blog post on the Android version of the Cloud Auction example application](http://vincenth.net/blog/archive/2013/10/23/creating-a-cross-platform-native-app-using-mvvmquickcross-and-xamarin-part-2-android-app.aspx).\r\n\r\nThis is what the Twitter app will look like in Android:\r\n\r\n![Twitter Example for Android](https://raw.github.com/MacawNL/QuickCross/master/Examples/Twitter/assets/twitter_android.png)\r\n\r\nSo let's get started.\r\n\r\n1.  Create a working Android app by following steps 1 though 4 of [Getting Started](#getting-started) above - create an `Android Application` project named `Twitter` and an `Android Class Library` project named `Twitter.Shared`.\r\n\r\n2.  Remove the `Activity1.cs`, `Resources\\Layout\\Main.axml` and `Class1.cs` files that were included by the Xamarin.Android project templates\r\n\r\n3.  Now you can run the app on your device and test the example MainView that was generated by the Install-Mvvm command.\r\n\r\n\t\u003e If you already created the shared code library for the example Twitter app in the [Create an iOS App](#create-an-ios-app) tutorial, you can include the existing C# files from the iOS library project also in your Android library project. Then skip to step 8 below.\r\n\r\n4.  Create a `Models` folder in your Twitter.Shared project and create this `Tweet.cs` class in it:\r\n\r\n\t```csharp\r\n\tusing System;\r\n\tnamespace Twitter.Shared.Models\r\n\t{\r\n\t    public class Tweet\r\n\t    {\r\n\t        public string Text { get; set; }\r\n\t        public string UserName { get; set; }\r\n\t        public DateTime CreatedAt { get; set; }\r\n\t    }\r\n\t}\r\n\t```\r\n\r\n5.  In `ViewModels\\MainViewModel.cs` in your library project, in the `#region Data-bindable properties and commands`, remove the example property and command add these properties and commands with the indicated [code snippets](#code-snippets):\r\n\t\r\n    \u003ctable\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003e\u003cb\u003eSnippet\u003c/b\u003e\u003c/td\u003e\u003ctd\u003e\u003cb\u003eParameters\u003c/b\u003e\u003c/td\u003e\u003ctd\u003e\u003cb\u003eGenerated code\u003c/b\u003e\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003e\u003ca href=\"#propdb2c\"\u003epropdb2c\u003c/a\u003e\u003c/td\u003e\u003ctd\u003eTweet Tweet\u003c/td\u003e\u003ctd\u003e\r\n\t\t\t\tpublic Tweet Tweet { ... }\u003cbr /\u003e\r\n\t\t\t\tprivate void OnTweetChanged() { ... }\r\n            \u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003e\u003ca href=\"#propdbcol\"\u003epropdbcol\u003c/a\u003e\u003c/td\u003e\u003ctd\u003eObservableCollection Tweet TweetList\u003c/td\u003e\u003ctd\u003e\r\n\t\t\t\tpublic ObservableCollection\u003cTweet\u003e TweetList  { ... }\u003cbr /\u003e\r\n\t\t\t\tpublic bool TweetListHasItems { ... }\u003cbr /\u003e\r\n\t\t\t\tprotected void UpdateTweetListHasItems() { ... }\r\n            \u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003e\u003ca href=\"#cmd\"\u003ecmd\u003c/a\u003e\u003c/td\u003e\u003ctd\u003eDelete\u003c/td\u003e\u003ctd\u003e\r\n\t\t\t\tpublic RelayCommand DeleteCommand { ... }\u003cbr /\u003e\r\n\t\t\t\tprivate void Delete() { ... }\r\n            \u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003e\u003ca href=\"#propdb2c\"\u003epropdb2c\u003c/a\u003e\u003c/td\u003e\u003ctd\u003estring Text\u003c/td\u003e\u003ctd\u003e\r\n\t\t\t\tpublic string Text { ... }\u003cbr /\u003e\r\n\t\t\t\tprivate void OnTextChanged() { ... }\r\n            \u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003e\u003ca href=\"#propdb\"\u003epropdb\u003c/a\u003e\u003c/td\u003e\u003ctd\u003eint CharactersLeft\u003c/td\u003e\u003ctd\u003e\r\n\t\t\t\tpublic int CharactersLeft { ... }\r\n            \u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003e\u003ca href=\"#cmd\"\u003ecmd\u003c/a\u003e\u003c/td\u003e\u003ctd\u003eSend\u003c/td\u003e\u003ctd\u003e\r\n\t\t\t\tpublic RelayCommand SendCommand { ... }\u003cbr /\u003e\r\n\t\t\t\tprivate void Send() { ... }\r\n           \u003c/td\u003e\r\n        \u003c/tr\u003e\r\n    \u003c/table\u003e\r\n    \t\r\n6.  Add this code in the generated `MainModel` methods:\r\n\t\t\r\n\t```csharp\r\n    public MainViewModel()\r\n    {\r\n        TweetList = new ObservableCollection\u003cTweet\u003e();\r\n        OnTweetChanged();\r\n        Text = \"\";\r\n    }\r\n\t\r\n    private void OnTweetChanged()\r\n    {\r\n        DeleteCommand.IsEnabled = (Tweet != null);\r\n    }\r\n\r\n    private void Delete()\r\n    {\r\n        TweetList.Remove(Tweet);\r\n        Tweet = null;\r\n    }\r\n\r\n    private void OnTextChanged()\r\n    {\r\n        CharactersLeft = 140 - Text.Length;\r\n        SendCommand.IsEnabled = (Text.Length \u003e 0 \u0026\u0026 CharactersLeft \u003e= 0);\r\n    }\r\n\r\n    private void Send()\r\n    {\r\n        var newTweet = new Tweet { Text = this.Text, CreatedAt = DateTime.Now, UserName=\"Me\" };\r\n        TweetList.Insert(0, newTweet);\r\n        Tweet = newTweet;\r\n        Text = \"\";\r\n    }\r\n\t```\r\n\r\n7.  The `MainViewModel.cs` file also contains a `MainViewModelDesign` class where you can put some hardcoded viewmodel data. Put this code in the MainViewModelDesign constructor:\r\n\t\t\r\n\t```csharp\r\n    public MainViewModelDesign()\r\n    {\r\n        Text = \"Text for a new tweet\";\r\n        var now = DateTime.Now;\r\n        TweetList.Insert(0, new Tweet { \r\n\t\t\tText = \"Creating a simple Twitter app with QuickCross\", \r\n\t\t\tUserName = \"Me\", CreatedAt = now.AddSeconds(-115) });\r\n        TweetList.Insert(0, new Tweet { \r\n\t\t\tText = \"Created a solution with an application and a library project\", \r\n\t\t\tUserName = \"Me\", CreatedAt = now.AddSeconds(-63) });\r\n        TweetList.Insert(0, new Tweet { \r\n\t\t\tText = \"Added Tweet model class\", \r\n\t\t\tUserName = \"Me\", CreatedAt = now.AddSeconds(-45) });\r\n        TweetList.Insert(0, new Tweet { \r\n\t\t\tText = \"Added viewmodel properties and commands with code snippets\", \r\n\t\t\tUserName = \"Me\", CreatedAt = now.AddSeconds(-25) });\r\n        TweetList.Insert(0, new Tweet { \r\n\t\t\tText = \"Added some hardcoded design data fot the viewmodel\", \r\n\t\t\tUserName = \"Me\", CreatedAt = now.AddSeconds(-1) });\r\n    }\r\n\t```\r\n\r\n8.  In the application project, in the file `Resources\\Layout\\MainView.axml`, replace the existing markup with this:\r\n\r\n\t```xml\r\n\t\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\r\n\t\u003cLinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n\t    android:id=\"@+id/MainView\"\r\n\t    android:orientation=\"vertical\"\r\n\t    android:layout_width=\"fill_parent\"\r\n\t    android:layout_height=\"fill_parent\"\u003e\r\n\t    \u003cListView\r\n\t        android:layout_width=\"fill_parent\"\r\n\t        android:layout_height=\"0dp\"\r\n\t        android:layout_weight=\"1\"\r\n\t        android:cacheColorHint=\"#FFDAFF7F\"\r\n\t        android:choiceMode=\"singleChoice\"\r\n\t        android:id=\"@+id/MainView_Tweet\"\r\n\t        android:tag=\"{Binding Mode=TwoWay}\" /\u003e\r\n\t    \u003cEditText\r\n\t        android:id=\"@+id/MainView_Text\"\r\n\t        android:tag=\"{Binding Mode=TwoWay}\"\r\n\t        android:text=\"*\"\r\n\t        android:textAppearance=\"?android:attr/textAppearanceLarge\"\r\n\t        android:layout_width=\"fill_parent\"\r\n\t        android:layout_height=\"wrap_content\" /\u003e\r\n\t    \u003cLinearLayout\r\n\t        android:orientation=\"horizontal\"\r\n\t        android:layout_width=\"fill_parent\"\r\n\t        android:layout_height=\"wrap_content\"\u003e\r\n\t        \u003cTextView\r\n\t            android:text=\"Characters left: \"\r\n\t            android:textAppearance=\"?android:attr/textAppearanceSmall\"\r\n\t            android:layout_width=\"wrap_content\"\r\n\t            android:layout_height=\"wrap_content\" /\u003e\r\n\t        \u003cTextView\r\n\t            android:id=\"@+id/MainView_CharactersLeft\"\r\n\t            android:text=\"14*\"\r\n\t            android:textAppearance=\"?android:attr/textAppearanceSmall\"\r\n\t            android:layout_width=\"0dp\"\r\n\t            android:layout_weight=\"1\"\r\n\t            android:layout_height=\"wrap_content\" /\u003e\r\n\t        \u003cButton\r\n\t            android:id=\"@+id/MainView_SendCommand\"\r\n\t            android:layout_width=\"wrap_content\"\r\n\t            android:layout_height=\"wrap_content\"\r\n\t            android:text=\"Send\" /\u003e\r\n\t        \u003cButton\r\n\t            android:id=\"@+id/MainView_DeleteCommand\"\r\n\t            android:layout_width=\"wrap_content\"\r\n\t            android:layout_height=\"wrap_content\"\r\n\t            android:layout_gravity=\"right\"\r\n\t            android:text=\"Delete\" /\u003e\r\n\t    \u003c/LinearLayout\u003e\r\n\t\u003c/LinearLayout\u003e\r\n\t```\r\n8.  Add a new Android Layout named `Resources\\Layout\\TweetListItem.axml`, with this markup:\r\n\r\n\t```xml\r\n\t\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\r\n\t\u003cquickcross.CheckableLinearLayout \r\n\t\txmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n\t    android:id=\"@+id/TweetListItem\"\r\n\t    android:orientation=\"vertical\"\r\n\t    android:background=\"@drawable/CustomSelector\"\r\n\t    android:addStatesFromChildren=\"true\"\r\n\t    android:layout_width=\"fill_parent\"\r\n\t    android:layout_height=\"wrap_content\"\u003e\r\n\t    \u003cLinearLayout\r\n\t        android:orientation=\"horizontal\"\r\n\t        android:layout_width=\"fill_parent\"\r\n\t        android:layout_height=\"wrap_content\"\u003e\r\n\t        \u003cTextView\r\n\t            android:id=\"@+id/TweetListItem_UserName\"\r\n\t            android:text=\"Me*\"\r\n\t            android:textAppearance=\"?android:attr/textAppearanceSmall\"\r\n\t            android:layout_width=\"40dp\"\r\n\t            android:layout_height=\"wrap_content\" /\u003e\r\n\t        \u003cTextView\r\n\t            android:id=\"@+id/TweetListItem_CreatedAt\"\r\n\t            android:text=\"friday october 11, 2013 14:08:2*\"\r\n\t            android:textAppearance=\"?android:attr/textAppearanceSmall\"\r\n\t            android:gravity=\"right\"\r\n\t            android:layout_width=\"0dp\"\r\n\t            android:layout_weight=\"1\"\r\n\t            android:layout_height=\"wrap_content\" /\u003e\r\n\t    \u003c/LinearLayout\u003e\r\n\t    \u003cTextView\r\n\t        android:id=\"@+id/TweetListItem_Text\"\r\n\t        android:text=\"Some example text*\"\r\n\t        android:textAppearance=\"?android:attr/textAppearanceMedium\"\r\n\t        android:layout_width=\"wrap_content\"\r\n\t        android:layout_height=\"wrap_content\" /\u003e\r\n\t\u003c/quickcross.CheckableLinearLayout\u003e\r\n\t```\r\n    Note that the CheckableLinearLayout view is a simple extension of the standard LinearLayout view that implements the ICheckable to better support highlighting checked list items; this view does not add anything specific for data-binding. If you dont care about highlighting checked items, you can use the standard LinearLayout (or any other layout view) for data binding as well.\r\n\r\n9.  Add a new XML File named `Resources\\Drawable\\CustomSelector.xml`, with this markup:\r\n\r\n\t```xml\r\n\t\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\r\n\t\u003cselector xmlns:android=\"http://schemas.android.com/apk/res/android\"\u003e\r\n\t  \u003citem android:state_checked=\"true\" android:drawable=\"@color/cellchecked\" /\u003e\r\n\t  \u003citem android:drawable=\"@color/cellback\" /\u003e\r\n\t\u003c/selector\u003e\r\n\t```\r\n\r\n10. Add a new XML File named `Resources\\Values\\Colors.xml`, with this markup:\r\n\r\n\t```xml\r\n\t\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\r\n\t\u003cresources\u003e\r\n\t  \u003ccolor name=\"cellback\"\u003e#00000000\u003c/color\u003e\r\n\t  \u003ccolor name=\"cellchecked\"\u003e#FF0000FF\u003c/color\u003e\r\n\t\u003c/resources\u003e\r\n\t```\r\n\r\n11. Run the app and test the MainView. Notice how the Send and Delete buttons are enabled and disabled based on the text length and selected item state, and how the characters remaining count is updated as you type. Also note how the selected list item is highlighted both from the UI when tapped, and from code when adding a new tweet.\r\n\r\nYou have created a working app with QuickCross. Note that the only code that you needed to write is in the viewmodel; no Android view or list adapter code is needed. To get data binding working, the markup follows some naming conventions and specifies some binding parameters in the Tag. \r\n\r\n### Android Data Binding ###\r\nAn Android data binding is a one-on-one binding between an Android view, such as a TextBox or Button, and a viewmodel property or command. You can specify bindings with (a combination of):\r\n\r\n1. Code in the activity or fragment that creates the containing view\r\n2. Id naming convention in the view markup\r\n3. Tag binding parameters in the view markup\r\n\r\nNote that for performance reasons, Android data binding allows **no more than one view** (within the same rootview) to be bound to a property. If you need to update multiple views with the same property value, you can do that by overriding the `UpdateView()` method in your activity or fragment class, and adding [a few lines of code](#binding-multiple-android-views-to-a-viewmodel-property).\r\n\r\nFinally, note that **you do not need to use the MvvmQuickCross implementation of Android data binding** if you prefer not to. You can subscribe to the standard .NET data binding events (`PropertyChanged` on viewmodels, `CanExecuteChanged` on `RelayCommand` viewmodel commands, and `CollectionChanged` on `ObservableCollection` viewmodel properties) from your code in any view type, and handle data binding any way you like. In this case you can keep using the [New-View command](#new-view), if you [add your own view template files](#customizing-and-extending-command-templates).\r\n\r\n#### Android Id Naming Convention ####\r\nTo bind a view to a viewmodel property without using code, name the view `id` like this:\r\n\r\n```xml\r\nandroid:id=\"@+id/\u003cactivity-or-fragment-class-name\u003e_\u003cviewmodel-property-or-command-name\u003e\"\r\n```\r\nE.g, the MainView in the Twitter example above is created by this class:\r\n\r\n```csharp\r\npublic class MainView : ActivityViewBase\u003cMainViewModel\u003e { ... }\r\n```\r\nAnd in the markup this is how a child view is bound to the CharactersLeft property on the viewmodel:\r\n\r\n```xml\r\n\u003cTextView android:id=\"@+id/MainView_CharactersLeft\"\t... /\u003e\r\n```\r\nNote that instead of using this id naming convention, you can specify the view in code. You can also change the default name prefix.\r\n\r\n#### Android Binding Parameters in Tag ####\r\nThese are the binding parameters that you can specify in the view tag (linebreaks added for readability):\r\n\r\n```xml\r\n\u003cViewType android:tag=\"...\r\n {Binding propertyName, Mode=OneWay|TwoWay|Command} \r\n {CommandParameter ListId=\u003cview-Id\u003e} \r\n {List ItemsSource=listPropertyName, ItemIsValue=false|true, \r\n       ItemTemplate=listItemTemplateName, ItemValueId=listItemValueId}\r\n ...\" /\u003e\r\n```\r\n\r\nAll of these parameters are optional. You can also put any additional text outside the { } in the tag if you want to. Note that you can also specify binding parameters through code instead of in the tag attribute.\r\n\r\n##### Android Binding propertyName #####\r\nIs known by default from the naming convention for the view `id` = \u0026lt;rootview prefix\u0026gt;\u0026lt;propertyName\u0026gt;; the default for the rootview prefix is the rootview class name + \"_\". Note that viewmodel commands are just a special type of viewmodel property, so you can use the propertyName to specify a command name as well.\r\n\r\n##### Android Binding Mode #####\r\nIs `OneWay` by default. The mode specifies:\r\n\r\n- OneWay data binding where the viewmodel property updates the view - e.g. a display-only TextView. The bound property can be generated with the propdb1 or propdbcol code snippet.\r\n- TwoWay data binding where the viewmodel property updates the view and vice versa, e.g. an editable EditText. The bound property can be generated with the propdb2, propdb2c or propdbcol code snippet.\r\n- Command binding (e.g. a Button). The bound command can be generated with the cmd or cmdp code snippet.\r\n\r\nNote that you can also use the binding mode Command in a view that derives from AdapterView (ListView, Spinner etc). When an item in the list is selected or checked, the bound command is invoked with the selected item as the command parameter. E.g. in below markup, selecting an item in the list navigates to a detail view of the item:\r\n\r\n```xml\r\n\u003cListView\r\n    android:id=\"@+id/ProductsView_ProductList\"\r\n    android:tag=\"{Binding SelectProductCommand, Mode=Command} {List ItemsSource=ProductList}\"\r\n\t... /\u003e\r\n```\r\n\r\n##### Android CommandParameter ListId #####\r\nPasses the selected item of the specified adapter view as the command parameter. The specified view can be any view type that is derived from AdapterView (ListView, Spinner etc). E.g. this Remove button passes the selected item from the view with id=SampleItemListView_Items as the command parameter, when the button is tapped:\r\n\r\n```xml\r\n\u003cListView\r\n    android:id=\"@+id/SampleItemListView_Items\"\r\n    android:tag=\"{List ItemsSource=Items, ItemTemplate=ListItem}\"\r\n    android:choiceMode=\"singleChoice\"\r\n    android:listSelector=\"@android:color/holo_blue_dark\"\r\n\t... /\u003e\r\n\u003cButton\r\n    android:id=\"@+id/SampleItemListView_RemoveItemCommand\"\r\n    android:text=\"Remove\"\r\n    android:tag=\"{Binding Mode=Command} {CommandParameter ListId=SampleItemListView_Items}\"\r\n\t... /\u003e\r\n```\r\n\r\nThe passed command parameter is the selected item object from the bound list, e.g. see the corresponding viewmodel code:\r\n\r\n```csharp\r\npublic ObservableCollection\u003cSampleItem\u003e Items { ... }\r\npublic RelayCommand RemoveItemCommand { ... }\r\n\r\nprivate void RemoveItem(object parameter)\r\n{\r\n    var item = (SampleItem)parameter;\r\n\t...\r\n}\r\n\r\n```\r\n\r\nThe `List` binding parameters are for use with views derived from `AdapterView` (`ListView`, `Spinner` etc):\r\n\r\n##### Android List ItemsSource #####\r\nSpecifies the name of the viewmodel collection property that contains the list items. The property must implement the standard .NET `IList` interface. If the property also implements the standard .NET `INotifyCollectionChanged` interface (e.g an `ObservableCollection`), the view will automatically reflect added, replaced or removed items. The default value of ItemsSource is `propertyName` + \"**List**\".\r\n\r\nThe items in an ItemsSource viewmodel collection property can be:\r\n\r\n- An object with fields or properties (e.g. a POCO model object)\r\n- An 'ValueItem' object, meaning an object that implements `ToString()` to present the value of the entire object as a human-readable text\r\n- A viewmodel object that has data-bindable properties and/or commands. This is also called **composite viewmodels**, which makes it possible to e.g. automatically display changes of individual fields within existing list item objects.\r\n\r\n##### Android List ItemTemplate #####\r\nSpecifies the name of the Android layout that represents a list item. E.g. the value \"TweetListItem\" corresponds to the view markup in the file Resources\\Layout\\TweetListItem.axml. The default value of ItemTemplate is the value of `ItemsSource` + \"**Item**\".\r\n\r\n##### Android List ItemIsValue #####\r\nIs a boolean flag indicating whether the list item should be displayed as a single text string, by calling the `ToString()` method on the object. If this flag is set to `true`, the `ItemValueId` binding parameter is also used. The default for ItemIsValue is `false`.\r\n\r\n##### Android List ItemValueId #####\r\nIf `ItemIsValue` is `true`, this parameter specifies the id of the child view within the item template view that should be used to display the object text. The default value of ItemValueId is the value of `ItemTemplate`. \r\n\r\n#### Android Binding Parameters in Code ####\r\nAs an alternative to using the Id naming convention and tag texts in markup, you can also specify bindings in code in an optional parameter of the **Initialize()** method. The Initialize method is implemented in the view base classes, and it is called in your view code from the `OnCreate()` (for an activity view) or `OnCreateView()` (for a fragment view) method. Here is an example of specifying binding parameters in code:\r\n\r\n```csharp\r\nvar spinner = FindViewById\u003cAndroid.Widget.Spinner\u003e(Resource.Id.OrderView_DeliveryLocation);\r\nspinner.Adapter = new DataBindableListAdapter\u003cstring\u003e(LayoutInflater, \r\n    itemTemplateResourceId: Resource.Layout.TextListItem, \r\n    idPrefix:               \"TextListItem_\", \r\n    itemValueResourceId:    Resource.Id.TextListItem);\r\n\r\nvar bindingsParameters = new BindingParameters[] {\r\n   new BindingParameters {\r\n       Mode                                    = BindingMode.TwoWay,\r\n       View                                    = spinner,\r\n       PropertyName                            = OrderViewModel.PROPERTYNAME_DeliveryLocation,\r\n       ListPropertyName                        = OrderViewModel.PROPERTYNAME_DeliveryLocationList,\r\n       CommandParameterSelectedItemAdapterView = null\r\n   }\r\n};\r\n\r\nInitialize(\r\n\tFindViewById(Resource.Id.OrderView),\r\n\tCloudAuctionApplication.Instance.OrderViewModel, \r\n\tbindingsParameters, \r\n\tidPrefix: \"OrderView_\"\r\n);\r\n```\r\nYou can specify some or all of the bindings, and in each binding some or all of the binding parameters. If you also specify parameters for a binding in a markup tag, those will override or supplement any parameters that you specify in code.\r\n\r\nNote that you do not need to use the [view id naming convention](#android-id-naming-convention) for normal views, since you specify a view instance in the `View` parameter. You could create the view entirely in code and not even give it an id. If you do use the id naming convention, you can specify a custom id name prefix in the `idPrefix` parameter of the `Initialize()` method (for normal views) and the `DataBindableListAdapter()` constructor (for list item views).\r\n\r\nMost binding parameters are specified in the Initialize call, while some List binding parameters are specified when constructing a data bindable list adapter for an AdapterView. When you use markup for data bindings and an AdapterView does not have an adapter assigned to it, a data bindable adapter is created and assigned to the AdapterView automatically.\r\n\r\nHere is how the code binding parameters correspond to the tag binding parameters:\r\n\u003ctable\u003e\r\n\u003ctr\u003e\u003ctd colspan=\"2\"\u003e\u003cb\u003eCode\u003c/b\u003e\u003c/td\u003e\u003ctd colspan=\"2\"\u003e\u003cb\u003eMarkup\u003c/b\u003e\u003c/td\u003e\u003c/tr\u003e\r\n\u003ctr\u003e\u003ctd\u003eBindingParameters\u003c/td\u003e\u003ctd\u003eMode\u003c/td\u003e\u003ctd\u003eBinding\u003c/td\u003e\u003ctd\u003e\u003ca href = \"#android-binding-mode\"\u003eMode\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\r\n\u003ctr\u003e\u003ctd\u003e\u003c/td\u003e\u003ctd\u003ePropertyName\u003c/td\u003e\u003ctd\u003eBinding\u003c/td\u003e\u003ctd\u003e\u003ca href = \"#android-binding-propertyname\"\u003eproperty name\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\r\n\u003ctr\u003e\u003ctd\u003e\u003c/td\u003e\u003ctd\u003eCommandParameter\u003cbr /\u003eSelectedItemAdapterView\u003c/td\u003e\u003ctd\u003eCommandParameter\u003c/td\u003e\u003ctd\u003e\u003ca href = \"#android-commandparameter-listid\"\u003eListId\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\r\n\u003ctr\u003e\u003ctd\u003e\u003c/td\u003e\u003ctd\u003eListPropertyName\u003c/td\u003e\u003ctd\u003eList\u003c/td\u003e\u003ctd\u003e\u003ca href = \"#android-list-itemssource\"\u003eItemsSource\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\r\n\u003ctr\u003e\u003ctd\u003eDataBindableListAdapter\u003c/td\u003e\u003ctd\u003eitemTemplateResourceId\u003c/td\u003e\u003ctd\u003eList\u003c/td\u003e\u003ctd\u003e\u003ca href = \"#android-list-itemtemplate\"\u003eItemTemplate\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\r\n\u003ctr\u003e\u003ctd\u003e\u003c/td\u003e\u003ctd\u003eitemValueResourceId\u003c/td\u003e\u003ctd\u003eList\u003c/td\u003e\u003ctd\u003e\u003ca href = \"#android-list-itemvalueid\"\u003eItemValueId\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\r\n\u003c/table\u003e\r\n\r\n#### Customizing or Extending Android Data Binding ####\r\nQuickCross allows you to simply modify or extend it with overrides in the view base classes, and in the ViewDataBindings class. You can also add more view base classes if you need to derive your views from other classes besides Activity and Fragment.\r\n\r\n##### Customizing Data Binding in Android Views #####\r\nBy overriding the `OnPropertyChanged()` method in your view class, you can handle changes for specific properties yourself instead of with the standard data binding. E.g:\r\n\r\n```csharp\r\n// Example of how to handle specific viewmodel property changes in code instead of with (or in addition to) data binding:\r\nprotected override void OnPropertyChanged(string propertyName)\r\n{\r\n    switch (propertyName)\r\n    {\r\n        case OrderViewModel.PROPERTYNAME_DeliveryLocationListHasItems:\r\n            var hasItems = ViewModel.GetPropertyValue\u003cbool\u003e(\r\n\t\t\t\t\t\t\t  OrderViewModel.PROPERTYNAME_DeliveryLocationListHasItems);\r\n            var spinner = FindViewById\u003cAndroid.Widget.Spinner\u003e(\r\n\t\t\t\t\t\t\t  Resource.Id.OrderView_DeliveryLocation);\r\n            spinner.Visibility = hasItems ? ViewStates.Visible : ViewStates.Invisible;\r\n            break;\r\n        default:\r\n            base.OnPropertyChanged(propertyName); break;\r\n    }\r\n}\r\n```\r\n\r\nYou can also override the `UpdateView()` method to change how the data binding mechanism sets a property value to a specific view (or modify multiple views based on the value etc.). E.g., an alternative to the `OnPropertyChanged()` code above is to add a containing `FrameLayout` around the spinner, data-bind the FrameLayout to the `DeliveryLocationListHasItems` property, and then override `UpdateView()` like this:\r\n\r\n```xml\r\n\u003cFrameLayout\r\n    android:id=\"@+id/OrderView_DeliveryLocationListHasItems\"\r\n    android:layout_width=\"fill_parent\"\r\n    android:layout_height=\"wrap_content\"\u003e\r\n    \u003cSpinner\r\n        android:layout_width=\"fill_parent\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:id=\"@+id/OrderView_DeliveryLocation\"\r\n        android:tag=\"{Binding Mode=TwoWay} {List ItemIsValue=true, ItemTemplate=TextListItem}\" /\u003e\r\n\u003c/FrameLayout\u003e\r\n```\r\n\r\n```csharp\r\npublic override void UpdateView(Android.Views.View view, object value)\r\n{\r\n    switch (view.Id)\r\n    {\r\n        case Resource.Id.OrderView_DeliveryLocationListHasItems:\r\n            view.Visibility = (bool)value ? ViewStates.Visible : ViewStates.Invisible; break;\r\n        default:\r\n            base.UpdateView(view, value); break;\r\n    }\r\n}\r\n```\r\n\r\n\u003e Note that `UpdateView()` is also called for **data bindings in all list items** for all data-bound lists in your view. This makes it possible to customize data binding within list items with code in a normal view, instead of writing a custom data bindable adapter to put that customization code in.\r\n\r\n###### Binding multiple Android views to a viewmodel property ######\r\nAnother scenario for overriding `UpdateView()` is when you want to update more than one view (within the same root view) from the same viewmodel property:\r\n\r\n```csharp\r\npublic override void UpdateView(Android.Views.View view, object value)\r\n{\r\n    switch (view.Id)\r\n    {\r\n        case Resource.Id.OrderView_ProductName:\r\n            base.UpdateView(view, value); // Set the single data-bound view\r\n\t\t\tstring text = value == null ? \"\" : value.ToString();\r\n            if (ProductName2TextView.Text != text) ProductName2TextView.Text = text;\r\n\t\t\tbreak;\r\n        default:\r\n            base.UpdateView(view, value); break;\r\n    }\r\n}\r\n```\r\n\r\nFinally, you can react to changes in lists that implement INotifyCollectionChanged (e.g. ObservableCollections) by overriding `OnCollectionChanged()` in your view:\r\n\r\n```csharp\r\npublic override void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)\r\n{\r\n    ...\r\n}\r\n```\r\nThe sender parameter is the collection. You could use this e.g. if you want to do some animation when items are added or removed in a list.\r\n\r\n##### Adding New Data-Bindable Android View Types #####\r\nOut of the box QuickCross has default data binding support for these view types:\r\n\r\nOne-Way binding:\r\n\r\n- `Android.Widget.ProgressBar`\r\n- `Android.Webkit.WebView`\r\n- `TextView` and derived types\r\n- `AbsListView` and derived types\r\n- `AdapterView` and derived types\r\n\r\nTwo-way binding:\r\n\r\n- `AbsSpinner` and derived types\r\n- `AbsListView` and derived types\r\n- `EditText` and derived types\r\n\r\nCommand binding:\r\n\r\n- `AbsSpinner` and derived types\r\n- `AdapterView` and derived types\r\n- `View` and derived types\r\n\r\nTo make more control types data bindable, you can simply add a case to the appropriate switch statements in the `QuickCross\\ViewDataBindings.UI.cs` file in your application project, as indicated by the `// TODO: ` comments. E.g.:\r\n\r\n```csharp\r\npublic static void UpdateView(View view, object value)\r\n{\r\n    if (view != null)\r\n    {\r\n        string viewTypeName = view.GetType().FullName;\r\n        switch (viewTypeName)\r\n        {\r\n            // TODO: Add cases here for specialized view types, as needed\r\n            case \"Macaw.UIComponents.MultiImageView\":\r\n                {\r\n                    if (value is Uri) value = ((Uri)value).AbsoluteUri;\r\n                    var multiImageView = (Macaw.UIComponents.MultiImageView)view;\r\n                    multiImageView.LoadImageList(value == null ? null : new[] { (string)value });\r\n                }\r\n                break;\r\n\t\t\t...\r\n\t\t}\r\n\t}\r\n}\r\n```\r\nTo prevent memory leaks, be sure that if you register an event handler on a view in `AddCommandHandler()` or `AddTwoWayHandler()`, you also unregister that handler in `RemoveCommandHandler()` resp. `RemoveTwoWayHandler()`.\r\n\r\n##### Adding New Android View Base Classes #####\r\nIf you need to derive your views from other classes besides Activity and Fragment, you can simply copy the existing `QuickCross\\ActivityViewBase.cs` or `QuickCross\\FragmentViewBase.cs` class and change the class that it derives from to the one that you need. \r\n\r\nE.g. to support data bindable classes derived from ListActivity, you would copy ActivityViewBase.cs to ListActivityViewBase.cs and just change \"Activity\" to \"ListActivity\" in these lines:\r\n\r\n```csharp\r\npublic abstract class ListActivityViewBase : ListActivity\r\n{\r\n\t...\r\n}\r\n\r\npublic class ListActivityViewBase\u003cViewModelType\u003e :\r\n\t\t\t     ListActivityViewBase, \r\n                 ViewDataBindings.ViewExtensionPoints\r\n                 where ViewModelType : ViewModelBase\r\n{\r\n\t...\r\n}\r\n```\r\nNow you can use the new base class in your view:\r\n\r\n```csharp\r\n[Activity(Label = \"Order\")]\r\npublic class OrderView : ListActivityViewBase\u003cOrderViewModel\u003e\r\n{\r\n\t...\r\n}\r\n```\r\nIt should take no more than a minute. To complete this, you could also [add a custom view template](#customizing-and-extending-command-templates) for this new view type.\r\n\r\n### Android View Lifecycle Support ###\r\nAs described by Xamarin, under \"**3.1. Removing Event Handlers in Activities**\" [here](http://docs.xamarin.com/guides/cross-platform/application_fundamentals/memory_perf_best_practices), you need to remove and re-add any external event handlers that you register in your view code to prevent memory leaks (external meaning not tied to the view itself or to an object contained within that view). The QuickCross view base classes do this removing and re-adding automatically at the appropriate [lifecycle events](http://docs.xamarin.com/guides/android/application_fundamentals/activity_lifecycle). To have your own event handlers added, removed and re-added at the appropriate times, you only need to override the `AddHandlers()` and `RemoveHandlers()` methods and add/remove your handlers there. E.g.:\r\n\r\n```csharp\r\nprotected override void AddHandlers()\r\n{\r\n    base.AddHandlers();\r\n    foreach (var tab in tabs) tab.TabSelected += Tab_TabSelected;\r\n}\r\n\r\nprotected override void RemoveHandlers()\r\n{\r\n    foreach (var tab in tabs) tab.TabSelected -= Tab_TabSelected;\r\n    base.RemoveHandlers();\r\n}\r\n```\r\nNote: Be sure to always call the base class method as well!\r\n\r\nYou should not call `AddHandlers()` yourself - that would mess up the base class tracking of added handlers. `AddHandlers()` is initially called by the base class in the `Initialize()` method, which you call in your view code in the `OnCreate()` or `OnCreateView()` method.\r\n\r\n### Android Helpers ###\r\nIn the `QuickCross\\AndroidHelpers.cs` file in your application project, you will find a few simple helpers that are of general use in Android development. Noteable helpers are:\r\n\r\n- `CurrentActivity` sometimes you need to code against the current activity from code that is not part of that activity. This static property is kept up to date by the Activity view base class, in such a way that no memory leaks can occur.\r\n- `Wrapper\u003cT\u003e` sometimes you need to provide a `Java.Lang.Object` to a Xamarin.Android method or property, but what you actually have is a `System.Object`. This wrapper allows you to cast between any .NET Object and Java Object, e.g.:\r\n\r\n\t```csharp\r\n\trootView.Tag = (Wrapper\u003cListDictionary\u003e)viewHolder;\r\n\t...\r\n\tvar viewHolder = (ListDictionary)rootView.Tag;\r\n\t```\r\n\tNote that the Tag property of an Android View in Xamarin is a `Java.Lang.Object`. \r\n\r\n## How to upgrade to a later version of QuickCross ##\r\nTo upgrade QuickCross to a later version, follow these steps:\r\n\r\n1. For all your QuickCross solutions: open your solution, make sure that you have no editor windows open, and then enter these commands in the package manager console:\r\n\r\n\t```posh\r\n\tRemove-Module QuickCross\r\n\tUninstall-Package QuickCross\r\n\t```\r\n\r\n3. Delete the QuickCross folders from your application project and your library project.\r\n\r\n\t\u003e Note: if you made any customizations to the QuickCross files, save those first and re-apply them to the new QuickCross files after you have upgraded.\r\n\r\n4. Install the latest QuickCross version by following **steps 2 through 4** in [Getting Started](#getting-started)\r\n\r\n\tThis will add the latest version of the QuickCross folders to your projects, but it will not overwrite any of your exiting code (Application, Navigator).\r\n\r\nNow your app is upgraded. NJoy QuickCross!\r\n\r\n## How to upgrade from MvvmQuickCross to QuickCross ##\r\nTo upgrade from MvvmQuickCross 1.6 to QuickCross 2.0, follow these steps:\r\n\r\n1. For all your MvvmQuickCross solutions: open your solution, make sure that you have no editor windows open, and then enter these commands in the package manager console:\r\n\r\n\t```posh\r\n\tRemove-Module MvvmQuickCross\r\n\tUninstall-Package MvvmQuickCross\r\n\t```\r\n\r\n2. Uninstall the MvvmQuickCross Visual Studio code snippets:\r\n\t1. In Visual Studio Code Snippets Manager, select the folder where the MvvmQuickCross snippets are listed.\r\n\t2. Copy the folder path from Location and open it in Windows Explorer\r\n\t3. Delete the MvvmQuickCross file there\r\n\t4. Close the Code snippets manager; the MvvmQuickCross snippets should be gone now\r\n\r\n3. Delete the MvvmQuickCross folders from your application project and your library project, and then rename MvvmQuickCross to QuickCross in **all files** in your solution.\r\n\r\n\t\u003e Note: if you made any customizations to the MvvmQuickCross files, save those first and re-apply them to the QuickCross files after you have upgraded.\r\n\r\n4. Rename your existing *MyApp*Navigator.cs, *IMyApp*Navigator.cs and *MyApp*Application.cs source files to end on **.old.cs** and set their **Build Action** property to **None**.\r\n\r\n5. Install QuickCross by following **steps 2 through 4** in [Getting Started](#getting-started)\r\n\r\n\tThis will add the QuickCross folders to your projects and generate a new *MyApp*Navigator, *IMyApp*Navigator and *MyApp*Application, but it will not overwrite any of your existing code.\r\n\r\n6. Copy your `NavigateTo...()` method signatures from *IMyApp*Navigator.old.cs to *IMyApp*Navigator.cs, and remove the `navigationContext` parameter.\r\n\r\n7. Copy your `NavigateTo...()` method implementations from *MyApp*Navigator.old.cs to *MyApp*Navigator.cs, and remove the `navigationContext` parameter there as well.\r\n\r\n8. Copy your `...ViewModel` properties, your `ContinueTo...()` methods and any code you added manually from *MyApp*Application.old.cs to *MyApp*Application.cs. Remove the `skipNavigation` parameter from the `ContinueTo...()` methods; it is now safe to always call the `NavigateTo...()` methods because the Navigator now checks if navigation should be skipped. Finally, remove the `navigationContext` parameter from the `NavigateTo...()` method invocations.\r\n\r\n9. Build your solution; you will get errors from the code that creates your application and navigator instances. This is because the `navigationContext` parameter was moved from the `Application` to the `Navigator` for more flexibility when using multiple navigation contexts (e.g. in iOS Universal apps). The navigator now is a singleton, accessible through it's static `Instance` property. The navigator now also has a public `NavigationContext` property that you need to set to the navigation context. To fix this:\r\n\r\n\tWhere the old code reads: `new MyAppNavigator()`, update it to:\r\n\r\n    \tMyAppNavigator.Instance\r\n    \r\n\tWhere the old code reads: `new MyAppApplication(..., navigationContext)`, update it to:\r\n\r\n    \tMyAppNavigator.Instance.NavigationContext = navigationContext;\r\n    \tnew MyAppApplication(...)\r\n \r\n10. In your Android Activity views, in `OnCreate()` you need to add the following code before the call to one of the `MyAppApplication.Instance.ContinueTo...()` methods:\r\n\r\n\t    MyAppNavigator.Instance.NavigationContext = this;\r\n\r\n11. Once your app compiles and runs, remove the *MyApp*Navigator.old.cs, *IMyApp*Navigator.old.cs and *MyApp*Application.old.cs \r\n\r\n\r\nNow your app is upgraded. NJoy QuickCross!\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvincenth-net%2Fquickcross","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvincenth-net%2Fquickcross","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvincenth-net%2Fquickcross/lists"}