{"id":25921,"date":"2016-05-23T12:07:23","date_gmt":"2016-05-23T19:07:23","guid":{"rendered":"https:\/\/blog.xamarin.com\/?p=25921"},"modified":"2016-05-23T12:07:23","modified_gmt":"2016-05-23T19:07:23","slug":"cross-platform-development-with-xamarin-forms-and-realm","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/cross-platform-development-with-xamarin-forms-and-realm\/","title":{"rendered":"Cross-Platform Development with Xamarin.Forms and Realm"},"content":{"rendered":"<p>\t\t\t\t<em>This is a special guest post from the Realm team, written by Kristian Dupont and Yavor Georgiev.<\/em><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/Kristian-Dupont.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/Kristian-Dupont.png\" alt=\"Kristian Dupont\" width=\"75\" height=\"75\" class=\"alignright size-full wp-image-25942\" \/><\/a><\/p>\n<p><em>Kristian is a C# developer at Realm, working on Realm Xamarin. You can find him and links to his various profiles at <a href=\"http:\/\/kristiandupont.com\" target=\"_blank\">kristiandupont.com<\/a>.<\/em>\n&nbsp;\n&nbsp;<a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/Yavor-Georgiev.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/Yavor-Georgiev.png\" alt=\"Yavor Georgiev\" width=\"75\" height=\"75\" class=\"alignright size-full wp-image-25943\" \/><\/a>\n<em>Yavor Georgiev is a developer at Realm, working on Realm Xamarin. Yavor herded iPhones at Telerik AppBuilder and bent JavaScript in unnatural shapes for NativeScript, but is now back to his .NET roots. He can be found on <a href=\"https:\/\/github.com\/fealebenpae\" target=\"_blank\">GitHub<\/a>.<\/em><\/p>\n<h3>What is Realm?<\/h3>\n<p>Realm, a mobile database that runs directly inside phones, tablets, and wearables, and offers a safe and easy non-ORM replacement for SQLite, <a href=\"https:\/\/realm.io\/news\/introducing-realm-xamarin\/\">recently launched support for Xamarin<\/a>. <\/p>\n<p>Realm Xamarin is built specifically with Xamarin developers in mind and is designed from the ground up for reactive app development. Data binding allows you to connect your UI to your persisted data in a very smooth and seamless way. It&#8217;s not only easy to use, but also heavily optimized for performance, which allows you to make apps that are more responsive and consume less power and memory.<\/p>\n<p>In this blog post we&#8217;ll demonstrate how to create a basic Xamarin.Forms app backed by Realm using Xamarin Studio on OSX. The tutorial is exactly the same if you&#8217;re using Visual Studio, except you&#8217;ll need to be connected to a Mac OSX machine use iOS as a platform target.<\/p>\n<h3>Setting up a Xamarin.Forms Project<\/h3>\n<p>Start by creating a new Xamarin.Forms project. If you want, you can download our source from <a href=\"https:\/\/github.com\/realm\/realm-dotnet\/tree\/master\/examples\/QuickJournal\">GitHub<\/a>, but you&#8217;ll learn more by going through the steps yourself.<\/p>\n<p>Choose the Xamarin.Forms App Project type under Cross-platform\/App in the New Project dialog. <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/choose-template.png\" alt=\"Select a template for your new mobile application.\" width=\"347\" height=\"148\" class=\"aligncenter size-full wp-image-25925\" \/><\/p>\n<p>Name your app, select &#8220;Use Portable Class Library&#8221; for shared code, and target both Android and iOS. <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/configure-project-1.png\" alt=\"Configure your project with a name, platforms, and shared code type.\" width=\"422 \" height=\"308\" class=\"aligncenter size-full wp-image-25926\" \/><\/p>\n<p>You probably want your project and solution to use the same name as your app. Put it in your preferred folder for projects and click Create.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/configure-project-2.png\" alt=\"Completed Configure Project Dialog\" width=\"437\" height=\"311\" class=\"aligncenter size-full wp-image-25927\" \/><\/p>\n<p>You now have a basic Xamarin.Forms app. Click the play button to try it out.<\/p>\n<h3>Adding Realm<\/h3>\n<p>With the foundation in place, we need to add Realm to it. Our solution has three projects, the Android app, the iOS app, and the PCL library for shared code. We&#8217;ll add Realm to all three. Do this by expanding the projects in the solution view, right-clicking on the Packages node, and clicking &#8220;Add Packages&#8230;&#8221; Search for &#8220;Realm&#8221; in the search box, select it, and add it. Do this for the remaining two projects as well.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/nuget-dialog.png\" alt=\"How to add the Realm NuGet package to your Xamarin.Forms apps.\" width=\"407\" height=\"268\" class=\"aligncenter size-full wp-image-25928\" \/><\/p>\n<h3>Creating Your Model<\/h3>\n<p>Our demo app is a minimalistic journal app. The only model is <code>JournalEntry<\/code>, which contains a timestamp and body text.<\/p>\n<pre class=\"lang:csharp decode:true\">\npublic class JournalEntry : RealmObject\n{\n    public DateTimeOffset Date { get; set; }\n    public string BodyText { get; set; }\n}\n<\/pre>\n<h3>Setting up the User Interface<\/h3>\n<p>Now that we have our model in place, we&#8217;ll create its corresponding UI. We&#8217;ll have two pages: a list of journal entries and a details view for specific journal entries. We&#8217;ll use the <a href=\"https:\/\/developer.xamarin.com\/guides\/xamarin-forms\/user-interface\/xaml-basics\/data_bindings_to_mvvm\/\">Model-View-ViewModel (MVVM) pattern<\/a> as much as possible, so every page will comprise of a View and an accompanying ViewModel.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/new-page.png\" alt=\"Adding a new Xamarin.Forms ContentPage XAML in Xamarin Studio.\" width=\"358\" height=\"272\" class=\"aligncenter size-full wp-image-25929\" \/><\/p>\n<p>Let\u2019s start by creating a new <code>Page<\/code> in the portable project, where all of our code will go. Make sure to select Forms &gt; ContentPage with XAML in the New File dialog. Name it <code>JournalEntriesPage<\/code>. This will contain the <code>ListView<\/code> that displays the journal entries and will be the main screen of the app.<\/p>\n<p>\u0422he XAML for the page should contain a <code>ListView<\/code>:<\/p>\n<pre class=\"lang:csharp decode:true\">\n\n    \n        \n            \n                \n            \n        \n    \n\n<\/pre>\n<p>We&#8217;ll set this as the MainPage of the App class that Xamarin.Forms generated for you in QuickJournal.cs: <\/p>\n<pre class=\"lang:csharp decode:true\">\nMainPage = new NavigationPage(new JournalEntriesPage());\n<\/pre>\n<p>We\u2019ll also need a <code>ViewModel<\/code> for our <code>Page<\/code>, so let\u2019s create JournalEntriesViewModel.cs:<\/p>\n<pre class=\"lang:csharp decode:true\">\npublic class JournalEntriesViewModel\n{\n    public IEnumerable Entries { get; private set; }\n\n    public INavigation Navigation { get; set; }\n}\n<\/pre>\n<p>And wire it up in the page\u2019s code-behind JournalEntriesPage.xaml.cs:<\/p>\n<pre class=\"lang:csharp decode:true\">\npublic JournalEntriesPage()\n{\n    InitializeComponent();\n    BindingContext = new JournalEntriesViewModel { Navigation = Navigation };\n}\n<\/pre>\n<p>You can now run the app, but you\u2019ll end up with an empty list; let\u2019s do something about that!<\/p>\n<h3>Binding the UI to a Realm<\/h3>\n<p>A Realm is an object that encapsulates a database. We\u2019ll let our <code>ViewModel<\/code> manage the realm.<\/p>\n<pre class=\"lang:csharp decode:true\">\nprivate Realm _realm;\n\npublic JournalEntriesViewModel()\n{\n    _realm = Realm.GetInstance();\n\n    Entries = _realm.All();\n}\n<\/pre>\n<p>Note that we are exposing the available entries by making a simple query to the <code>Realm<\/code>.  <code>Realm.All()<\/code> will give us the entire set of a given type that exists in the <code>Realm<\/code>. As it\u2019s a &#8220;live&#8221; query, we can simply bind our list view to it and it will be continuously up to date.<\/p>\n<p>Now the list should still be empty, but that\u2019s because the database is empty. Let\u2019s create some journal entries for testing purposes in the <code>JournalEntriesViewModel<\/code> constructor:<\/p>\n<pre class=\"lang:csharp decode:true\">\n_realm.Write(() =&gt;\n{\n    for (var i = 0; i &lt; 3; i++)\n    {\n        var entry = new JournalEntry { Date = DateTimeOffset.Now };\n        _realm.Add(entry);\n    }\n});\n<\/pre>\n<p>Of course, this will add new entries every time we run the app, so we\u2019ll need some way to delete entries as well. To do so, let\u2019s add a <code>Delete<\/code> context action to the <code>ListView<\/code>, and later we&#8217;ll remove the <code>for<\/code> loop so we don&#8217;t create dummy entries when we run the app.<\/p>\n<pre class=\"lang:csharp decode:true\">\n\n    \n\n<\/pre>\n<p>We\u2019ll use the command pattern to wire up interactivity between our views and view models. To do so, let\u2019s add a new property to <code>JournalEntriesViewModel<\/code>:<\/p>\n<pre class=\"lang:csharp decode:true\">\npublic ICommand DeleteEntryCommand { get; private set; }\n<\/pre>\n<p>And initialize it in the constructor:<\/p>\n<pre class=\"lang:csharp decode:true\">\nDeleteEntryCommand = new Command(DeleteEntry);\n<\/pre>\n<p>Here, <code>DeleteEntry<\/code> is a simple method to do the actual deletion:<\/p>\n<pre class=\"lang:csharp decode:true\">\nprivate void DeleteEntry(JournalEntry entry)\n{\n    _realm.Write(() =&gt; _realm.Remove(entry));\n}\n<\/pre>\n<p>Now we have an app that displays three journal entries straight from a Realm database using concise XAML and data binding.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/running-app.png\" alt=\"What our Realm-backed journal app looks like.\" width=\"455\" height=\"739\" class=\"aligncenter size-full wp-image-25930\" \/><\/p>\n<h3>Adding an Edit screen with Save\/Cancel<\/h3>\n<p>Let\u2019s add a second page that will be used to edit the body of a journal entry: <code>JournalEntryDetailsPage<\/code>:<\/p>\n<pre class=\"lang:csharp decode:true\">\n\n    \n        \n    \n    \n        \n    \n\n<\/pre>\n<p>It needs to have a corresponding view model:<\/p>\n<pre class=\"lang:csharp decode:true\">\npublic class JournalEntryDetailsViewModel\n{\n    private Transaction _transaction;\n\n    public JournalEntry Entry { get; private set; }\n    internal INavigation Navigation { get; set; }\n    public ICommand SaveCommand { get; private set; }\n\n    public JournalEntryDetailsViewModel(JournalEntry entry, Transaction transaction)\n    {\n        Entry = entry;\n        _transaction = transaction;\n        SaveCommand = new Command(Save);\n    }\n\n    private void Save()\n    {\n        _transaction.Commit();\n        Navigation.PopAsync(true);\n    }\n\n    internal void OnDisappearing()\n    {\n        _transaction.Dispose();\n    }\n}\n<\/pre>\n<p>And the two need to be wired up in the <code>Page<\/code>\u2019s code-behind:<\/p>\n<pre class=\"lang:csharp decode:true\">\npublic partial class JournalEntryDetailsPage : ContentPage\n{\n    public JournalEntryDetailsPage(JournalEntryDetailsViewModel viewModel)\n    {\n        InitializeComponent();\n        BindingContext = viewModel;\n        viewModel.Navigation = Navigation;\n    }\n\n    protected override void OnDisappearing()\n    {\n        base.OnDisappearing();\n        (BindingContext as JournalEntryDetailsViewModel)?.OnDisappearing();\n    }\n}\n<\/pre>\n<p>There are some familiar concepts here such as <code>Command<\/code>, but we introduce an important Realm feature with the <code>Transaction<\/code>. Because the details page will use data binding to edit the body of a <code>JournalEntry<\/code> directly in the Realm database, it will need to hold on to a <code>Transaction<\/code>&mdash;more on that in a bit.<\/p>\n<p>Lastly, let\u2019s add a new toolbar button to the `ListView` page:<\/p>\n<pre class=\"lang:csharp decode:true\">\n\n    \n \n<\/pre>\n<p>and a corresponding <code>Command<\/code> in the <code>JournalEntriesViewModel<\/code>:<\/p>\n<pre class=\"lang:csharp decode:true\">\npublic ICommand AddEntryCommand { get; private set; }\n<\/pre>\n<p>Be sure to remove the <code>for<\/code> loop in <code>JournalEntriesViewModel<\/code> that adds three dummy entries each time the app is launched.<\/p>\n<p>We\u2019ll need an <code>AddEntry<\/code> method to back the <code>AddEntryCommand<\/code> in <code>JournalEntriesViewModel<\/code>. It\u2019ll be responsible for creating an entry and navigating to the details page where it can be edited:<\/p>\n<pre class=\"lang:csharp decode:true\">\nprivate void AddEntry()\n{\n    var transaction = _realm.BeginWrite();\n    var entry = _realm.CreateObject();\n    entry.Date = DateTimeOffset.Now;\n\n    var page = new JournalEntryDetailsPage(\n          new JournalEntryDetailsViewModel(entry, transaction));\n\n    Navigation.PushAsync(page);\n}\n<\/pre>\n<p>There are three things of note here:<\/p>\n<p>1. We open a write transaction.\n2. We create a new <code>JournalEntry<\/code> object and set its Date.\n3. We create a new instance of <code>JournayEntryDetailsPage<\/code> and its view model, passing the entry and transaction we created.<\/p>\n<p>That\u2019s how you add entries. Editing existing entries is something you can work out on your own, or you can cheat and <a href=\"https:\/\/github.com\/realm\/realm-dotnet\/tree\/master\/examples\/QuickJournal\">look at the complete project on GitHub<\/a>.<\/p>\n<h3>The Realm Transaction Explained<\/h3>\n<p>There are three mutating actions in our app: adding, editing, and deleting a journal entry. One of the essential things to remember when working with Realm is that any time you want to mutate data, you must do so in a transaction. <\/p>\n<p>Deleting is, as we saw, quite simple. Create a transaction, remove the requested <code>JournalEntry<\/code> from the <code>Realm<\/code>, and commit the transaction. We achieve this with the <code>Realm.Write()<\/code> method. This makes sure a transaction is created and subsequently committed and disposed of (unless the statement throws an exception). <\/p>\n<p>To add and edit, our situation is a bit different. We want to keep a transaction alive while the user edits the body text of their journal entry so we can bind the <code>Editor<\/code> directly to our <code>BodyText<\/code> property. In other words, we practically get UI-to-disk binding with no extra plumbing. We do this by tying the transaction to the details page; when the details page is visible, a corresponding transaction will be active. <\/p>\n<p>We can easily cancel the edit by not committing the transaction before disposing of it. To achieve this, we let our <code>JournalEntryDetailsViewModel<\/code> own the transaction. In the Save command, we commit the transaction so the changes are persisted and then we pop the edit page from the Xamarin.Forms navigation stack. This will trigger <code>JournalEntryDetailsViewModel.OnDisappearing()<\/code> which disposes of the transaction. If the user taps \u201cBack\u201d instead of &#8220;Save&#8221;, only the <code>JournalEntryDetailsViewModel.OnDisappearing()<\/code> method is called, so the transaction is disposed of without being committed first. This will cause any edits that took place inside the transaction, including creating the new entry, to be rolled back.<\/p>\n<h3>TL; DR<\/h3>\n<p>We can make an app that presents and persists data very quickly and with very little plumbing code with the power of Xamarin.Forms data binding and the Realm zero-copy architecture. <\/p>\n<p>Once you&#8217;re comfortable with writing your models so they are compatible with Realm and know how to bind them to the UI, you can create end-to-end functionality as easily as you would a mockup. <\/p>\n<p>We rely on a transaction that lives together with the details page. In our demo journal app, this makes an add or an edit of a journal entry atomic, so it can easily be saved or undone. We could have chosen a different design with more fine-grained transactions if, for example, we wanted to save a draft while it was being edited, but this goes beyond the scope of this post.<\/p>\n<p>Although we\u2019ve only shown you how to get the basics running, we hope this will help you get started. There&#8217;s obviously much more depth to both Xamarin.Forms and Realm and we&#8217;ll be following up with posts on more advanced topics. You can learn more about <a href=\"https:\/\/www.xamarin.com\/forms\">Xamarin.Forms here<\/a> and about Realm Xamarin  <a href=\"https:\/\/realm.io\/docs\/xamarin\/latest\/\">here<\/a>.\t\t<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a special guest post from the Realm team, written by Kristian Dupont and Yavor Georgiev. Kristian is a C# developer at Realm, working on Realm Xamarin. You can find him and links to his various profiles at kristiandupont.com. &nbsp; &nbsp; Yavor Georgiev is a developer at Realm, working on Realm Xamarin. Yavor herded [&hellip;]<\/p>\n","protected":false},"author":1953,"featured_media":25928,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[4],"class_list":["post-25921","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","tag-xamarin-platform"],"acf":[],"blog_post_summary":"<p>This is a special guest post from the Realm team, written by Kristian Dupont and Yavor Georgiev. Kristian is a C# developer at Realm, working on Realm Xamarin. You can find him and links to his various profiles at kristiandupont.com. &nbsp; &nbsp; Yavor Georgiev is a developer at Realm, working on Realm Xamarin. Yavor herded [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/25921","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/1953"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=25921"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/25921\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=25921"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=25921"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=25921"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}