Xamarin.Native Tutorial: InvoiceJe: DataBinding: Setup

Alright, now let's go with DataBinding. We still won't make a database though.

We will pick up from where we left earlier.

We will use https://github.com/purrmiaw/InvoiceJeNoDatabase as our starting point (you should be here if you've followed the previous tutorial).

What we are going to do here is databinding. Basically, we will touch on how:

  • To display data from code behind to the screen
  • To bind enumerable data to enumerable views/controls such as ListView (Android, UWP) / TableView (iOS).
  • How to send parameters between activities (Android) / screens (iOS) / pages (UWP)

Okay, let's go!

Setup Dummy Repository

For now, we still won't go into database yet. However, we will setup a dummy repository that returns data to us.

So, in the Portable class, create a folder named Models. Inside it create a class named Invoice. Replace the code with this:

namespace InvoiceJe.Models
{
    public class Invoice
    {
        public int Id { get; set; }
        public string ReferenceNumber { get; set; }
        public string BillTo { get; set; }
        public decimal Amount { get; set; }
    }
}

Now let's create the repository class. Create a folder named Data. Inside it, create a class named Repository. Replace the code with this:

using InvoiceJe.Models;
using System;
using System.Collections.Generic;

namespace InvoiceJe.Data
{
    public class Repository
    {
       
        public IEnumerable<Invoice> GetInvoices()
        {
            var invoices = new List<Invoice>();
            invoices.Add(new Invoice { Id = 1, ReferenceNumber = "001", Amount = 20.12M, BillTo="ABC Sdn Bhd" });
            invoices.Add(new Invoice { Id = 2, ReferenceNumber = "002", Amount = 32.56M, BillTo = "Ahmad and Friends" });
            invoices.Add(new Invoice { Id = 3, ReferenceNumber = "003", Amount = 45.12M, BillTo = "Reddit pvt ltd" });
            invoices.Add(new Invoice { Id = 4, ReferenceNumber = "004", Amount = 27.00M, BillTo = "Google ltd" });
            invoices.Add(new Invoice { Id = 5, ReferenceNumber = "005", Amount = 16.00M, BillTo = "Microsoft ltd" });
            invoices.Add(new Invoice { Id = 6, ReferenceNumber = "006", Amount = 87.00M, BillTo = "Dave Games" });
            invoices.Add(new Invoice { Id = 7, ReferenceNumber = "007", Amount = 4.32M, BillTo = "Authentic Venture Sdn Bhd" });
            invoices.Add(new Invoice { Id = 8, ReferenceNumber = "008", Amount = 20.12M, BillTo = "Nancy" });
            invoices.Add(new Invoice { Id = 9, ReferenceNumber = "009", Amount = 17.00M, BillTo = "Archer" });
            invoices.Add(new Invoice { Id = 10, ReferenceNumber = "010", Amount = 46.85M, BillTo = "Hatsune Miku" });
            invoices.Add(new Invoice { Id = 11, ReferenceNumber = "011", Amount = 95.45M, BillTo = "Game of Thrones pvt ltd" });
            invoices.Add(new Invoice { Id = 12, ReferenceNumber = "012", Amount = 100.2M, BillTo = "Sunsuria Apts ltd" });
            invoices.Add(new Invoice { Id = 13, ReferenceNumber = "013", Amount = 520.7M, BillTo = "Miaw.xyz" });
            invoices.Add(new Invoice { Id = 14, ReferenceNumber = "014", Amount = 1.12M, BillTo = "Authentic Venture Sdn Bhd" });
            invoices.Add(new Invoice { Id = 15, ReferenceNumber = "015", Amount = 50.00M, BillTo = "Acer Sdn Bhd" });
            invoices.Add(new Invoice { Id = 16, ReferenceNumber = "016", Amount = 100.0M, BillTo = "Oppo Sdn Bhd" });
            invoices.Add(new Invoice { Id = 17, ReferenceNumber = "017", Amount = 145.1M, BillTo = "FL Studio" });
            invoices.Add(new Invoice { Id = 18, ReferenceNumber = "018", Amount = 205.8M, BillTo = "Unity3D" });
            invoices.Add(new Invoice { Id = 19, ReferenceNumber = "019", Amount = 785.6M, BillTo = "Goal" });
            invoices.Add(new Invoice { Id = 20, ReferenceNumber = "020", Amount = 15.03M, BillTo = "Google ltd" });

            return invoices;
        }
    }
}

...Basically, we're just returning dummy data first.

Your folder structure should now look like this:

Alright, that's all we need to do in the Portable Class Library. Now let's move on to each platform.

 

How to use Acrylic Accent

You will need to target Creator Update for this.

    <RelativePanel Grid.Column="0" Grid.ColumnSpan="2" MinWidth="40" x:Name="MainGrid" SizeChanged="Page_SizeChanged">
        <RelativePanel Grid.Column="0" Width="{Binding ElementName=MainGrid,Path=Width}" Background="#28000000">
            <Grid>
                <!--Having content here, for example textblock and so on-->
            </Grid>
        </RelativePanel>
    </RelativePanel>

 

public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();

            applyAcrylicAccent(MainGrid);
        }

        Compositor _compositor;
        SpriteVisual _hostSprite;

        private void applyAcrylicAccent(Panel panel)
        {
            _compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
            _hostSprite = _compositor.CreateSpriteVisual();
            _hostSprite.Size = new Vector2((float)panel.ActualWidth, (float)panel.ActualHeight);

            ElementCompositionPreview.SetElementChildVisual(panel, _hostSprite);
            _hostSprite.Brush = _compositor.CreateHostBackdropBrush();
        }

        private void Page_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (_hostSprite != null)
                _hostSprite.Size = e.NewSize.ToVector2();
        }

    }

 

CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true bug

https://social.msdn.microsoft.com/Forums/en-US/21215c3a-cc0f-46c7-b9e0-3469559e900a/14393-extendviewintotitlebar-can-never-return-to-false-again-even-reinstall?forum=wpdevelop

CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar will not return to false again even after reinstall.

This is because the value is saved inside the registry. 

"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ApplicationFrame\TitleBar\{YourAppIdentifier}"

Setting it to true will save it inside the registry. Setting it to false, however, does not.

 

Xamarin.Native Tutorial: InvoiceJe: Universal Windows Platform

Alright, now let's mess with the Universal Windows Platform.

Developing for UWP is actually pretty fun and it looks friggin' awesome. Too bad not many people use Windows phone :( (Alright Microsoft, pay me that pandering money!)

We'll go with the basics first.

Just like in the Android and iOS platforms, the application will be a tabbed application.

Setup

We'll setup a little thing first.

Open App.xaml.

<Application
    x:Class="InvoiceJe.UWP.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:InvoiceJe.UWP">
    <!--RequestedTheme="Light"-->
    
</Application>

Now, by default UWP sets the RequestedTheme as "Light". We'll remove it and let the app use the default theme of the user's device.

MainPage.xaml

Now open MainPage.xaml. And copy paste this xml:

<Page
    x:Class="InvoiceJe.UWP.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:InvoiceJe.UWP"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Page.Transitions>
        <TransitionCollection>
            <EntranceThemeTransition />
        </TransitionCollection>
    </Page.Transitions>

    <Grid x:Name="ContentGrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>

        <Pivot>
            <PivotItem Header="Invoices" Margin="0">
                <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                    <ListView Margin="0,0,0,48">
                        <TextBlock Text="Invoice #1" />
                        <TextBlock Text="Invoice #2" />
                        <TextBlock Text="Invoice #3" />
                        <TextBlock Text="Invoice #4" />
                        <TextBlock Text="Invoice #5" />
                        <TextBlock Text="Invoice #6" />
                        <TextBlock Text="Invoice #7" />
                        <TextBlock Text="Invoice #8" />
                        <TextBlock Text="Invoice #9" />
                        <TextBlock Text="Invoice #10" />
                        <TextBlock Text="Invoice #11" />
                        <TextBlock Text="Invoice #12" />
                        <TextBlock Text="Invoice #13" />
                        <TextBlock Text="Invoice #14" />
                        <TextBlock Text="Invoice #15" />
                        <TextBlock Text="Invoice #16" />
                        <TextBlock Text="Invoice #17" />
                        <TextBlock Text="Invoice #18" />
                    </ListView>

                    <CommandBar HorizontalAlignment="Stretch" VerticalAlignment="Bottom">
                        <CommandBar.Content>
                            <Grid/>
                        </CommandBar.Content>
                        <AppBarButton Icon="Add" Label="Add Invoice" Click="AppBarButton_Click"/>
                    </CommandBar>
                </Grid>

            </PivotItem>
            <PivotItem Header="Configuration">
                <ScrollViewer>
                    <StackPanel>
                        <TextBlock TextWrapping="Wrap" FontSize="24" Margin="0 0 0 3" Text="General Settings"/>
                        <ToggleSwitch Header="Local Only" Margin="0 0 0 12" />
                        <TextBlock TextWrapping="Wrap" FontSize="24" Margin="0 0 0 3" Text="Purchase"/>
                        <TextBlock TextWrapping="Wrap" Text="Click here to purchase now" />
                    </StackPanel>
                </ScrollViewer>
            </PivotItem>
        </Pivot>

    </Grid>

</Page>

 ...and replace the MainPage.xaml.cs to this:

using InvoiceJe.UWP.Views;
using Windows.ApplicationModel.Core;
using Windows.UI.Core;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace InvoiceJe.UWP
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();

            // To disable ExtendViewIntoTitleBar and others when using Acryllic Accent
            CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = false;
            ApplicationViewTitleBar titleBar = ApplicationView.GetForCurrentView().TitleBar;
            titleBar.ButtonBackgroundColor = null; // by setting this to null, it gets the default value
            titleBar.ButtonInactiveBackgroundColor = null; // by setting this to null, it gets the default value
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            Frame rootFrame = Window.Current.Content as Frame;
            if (rootFrame.CanGoBack)
            {
                // Show UI in title bar if opted-in and in-app backstack is not empty.
                SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
                    AppViewBackButtonVisibility.Visible;
            }
            else
            {
                SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
    AppViewBackButtonVisibility.Collapsed;
            }


        }

        //private void AppBarButton_Click(object sender, RoutedEventArgs e)
        //{
        //    Frame.Navigate(typeof(InvoicesCreatePage));
        //}
    }
}

 

You will end up with these screens.

There, we're done!

Nah, just kidding. But let me explain first.

Let's take a look at the XAML structure first.

<Page
    x:Class="InvoiceJe.UWP.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:InvoiceJe.UWP"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">


    <Page.Transitions>
        <TransitionCollection>
            <EntranceThemeTransition />
        </TransitionCollection>
    </Page.Transitions>

    <Grid x:Name="ContentGrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>

        <Pivot>
            ....
        </Pivot>
    </Grid>

</Page>

The parent is the Page element. So this defines a screen.

There's the <Page.Transitions> element (or actually, one of the Page properties as well). This defines the transitions for the page. You can read all about it here.

Then, you have 1 Grid. This defines the whole page layout. Just like Android.

And inside the Grid, you have the Grid.ColumnDefinitions. This defines the number of columns/cells the grid have. Right now, we only have 1.

Now the other children is the Pivot. Pivot is equivalent to Tabs in Android. So you simply define a Pivot. And then, you define the PivotItem, which is the child tabs. Inside the PivotItems you just define the elements inside.

PivotItem "Invoice"

Now inside the PivotItem "Invoice", we defined another Grid to host our child elements inside.

See that in the attributes of PivotItem: 

<PivotItem Header="Invoices" Margin="0">

...We have set the Margin to "0".

Inside the Grid, we have 2 elements, the ListView and the CommandBar.

We have the ListView which houses a bunch of dummy TextBlocks.

The CommandBar is the bottom bar you see in UWP apps, and is usually used to show the actions available to the user for the current screen. To add buttons, simply define the AppBarButton inside it.

Since the CommandBar is inside the "Invoice" PivotItem, it will be hidden when the user swipes to the "Configuration" PivotItem.

 Now, swipe to the "Invoices" pivot and try stretching the CommandBar.

You'll see that the CommandBar will stretch as well.

This is because...

<CommandBar HorizontalAlignment="Stretch" VerticalAlignment="Bottom">

....we defined the property HorizontalAlignment="Stretch" inside our CommandBar. This means that the horizontal length of the element should be stretched according to the parent element. The VerticalAlignment="Bottom" property means the element will be placed at the bottom of the parent element (which is the Grid) and maintain its default height.

UWP's fluid layout will immediately understand that the CommandBar is meant to be at the bottom of the PivotItem and stretches as necessary. 

(Actually, "Stretch" is the default value for both HorizontalAlignment and VerticalAlignment properties. So for all elements that did not define their Alignment values, they'll default to "Stretch").

Now take a look at the ListView tag again...

<ListView Margin="0,0,0,48">

...Since we did not define the HorizontalAlignment and VerticalAlignment properties, it will default to "Stretch". But this means that the ListView will overlap with the CommandBar! Hence we defined the Margin="0,0,0,48", which means we set the bottom margin to 48px, which is the default height of the CommandBar.

"Configuration" PivotItem

<PivotItem Header="Configuration">
                <ScrollViewer>
                    <StackPanel>
                        <TextBlock TextWrapping="Wrap" FontSize="24" Margin="0 0 0 3" Text="General Settings"/>
                        <ToggleSwitch Header="Local Only" Margin="0 0 0 12" />
                        <TextBlock TextWrapping="Wrap" FontSize="24" Margin="0 0 0 3" Text="Purchase"/>
                        <TextBlock TextWrapping="Wrap" Text="Click here to purchase now" />
                    </StackPanel>
                </ScrollViewer>
            </PivotItem>

Now let's take a look at the Configuration PivotItem.

We've used a ScrollViewer here. ScrollViewer is just like ScrollView in Android. If we're putting too many things on our page until it doesn't fit, by putting it inside a ScrollViewer it will allow the user to scroll the elements that is put inside the ScrollViewer (We actually don't need it for our current Configuration page because we only have 2 elements inside it, but we'll just put it there for the future when the configuration page is big).

But what about the ListView before? We didn't put it inside a ScrollViewer, but I could scroll! It's because ListView have a built-in ScrollViewer itself, so we don't need to wrap it with a ScrollViewer.

And inside the ScrollViewer, we used a StackPanel. It's similar to the LinearLayout of Android, which means the elements defined inside it will 'stack' on top of each other.

The insides are pretty much self-explanatory. We have TextBlock as the text and the ToggleSwitch as the switch. However, here we defined the elements explicitly so that it looks nice (well, according to Microsoft Design Guidelines).

...Unfortunately, UWP doesn't have a built-in BottomNavigationView, so we're going with Pivot in our UWP app.

Of course, some of you will think "How about using the CommandBar as our BottomNavigationView?" Yes, you can, though we're not going to touch that in our tutorial. But with the knowledge from this tutorial it should be easy enough for you to change it to however you want.

...And for the .cs file:

public MainPage()
        {
            this.InitializeComponent();

            // To disable ExtendViewIntoTitleBar and others when using Acryllic Accent
            CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = false;
            ApplicationViewTitleBar titleBar = ApplicationView.GetForCurrentView().TitleBar;
            titleBar.ButtonBackgroundColor = null; // by setting this to null, it gets the default value
            titleBar.ButtonInactiveBackgroundColor = null; // by setting this to null, it gets the default value
        }

...This one is probably not important to you, but basically we're explicitly setting the app so that it works just like the user's system default.

And this one:

protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            Frame rootFrame = Window.Current.Content as Frame;
            if (rootFrame.CanGoBack)
            {
                // Show UI in title bar if opted-in and in-app backstack is not empty.
                SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
                    AppViewBackButtonVisibility.Visible;
            }
            else
            {
                SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
    AppViewBackButtonVisibility.Collapsed;
            }

        }

...is to handle the Back button whether to show to the users or not. Don't worry we're take a look at this later.

InvoicesCreate

Alright, now let's make an InvoicesCreatePage page.

Inside Solution Explorer, at the root of the UWP project, Right Click -> Add Folder and name it Views. Select XAML > Blank Page. Name it InvoicesCreatePage.xaml and click Add.

Your folder structure should look like this:

Now, inside InvoicesCreatePage.xaml, replace with this XAML:

<Page
    x:Class="InvoiceJe.UWP.Views.InvoicesCreatePage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:InvoiceJe.UWP.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Page.Transitions>
        <TransitionCollection>
            <EntranceThemeTransition />
        </TransitionCollection>
    </Page.Transitions>
    
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel Margin="12 12 12 0">
            <TextBlock TextWrapping="Wrap" Text="Reference" Height="20" FontSize="15" />
            <TextBox TextWrapping="Wrap" Height="32" Margin="0 4 0 0" />
            <TextBlock TextWrapping="Wrap" Text="Date Issued" Height="20" FontSize="15" Margin="0 24 0 0" />
            <DatePicker Height="34" Margin="0,4,0,0" HorizontalAlignment="Stretch" />
            <TextBlock TextWrapping="Wrap" Text="Bill To" Height="20" FontSize="15" Margin="0 24 0 0" />
            <TextBox TextWrapping="Wrap" Height="32" Margin="0 0 0 0" />
            <TextBlock TextWrapping="Wrap" Text="Email To" Height="20" FontSize="15" Margin="0 24 0 0" />
            <TextBox TextWrapping="Wrap" Height="32" Margin="0 0 0 0" />
            <TextBlock TextWrapping="Wrap" Text="Total" Height="20" FontSize="15" Margin="0 24 0 0" />
            <TextBox TextWrapping="Wrap" Height="32" Margin="0 0 0 0" />
        </StackPanel>
    </Grid>

    <Page.BottomAppBar>
        <CommandBar HorizontalAlignment="Stretch">
            <CommandBar.PrimaryCommands>
                <AppBarButton Icon="Save" Label="Save" />
            </CommandBar.PrimaryCommands>
        </CommandBar>
    </Page.BottomAppBar>
</Page>

...and the code-behind:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238

namespace InvoiceJe.UWP.Views
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class InvoicesCreatePage : Page
    {
        public InvoicesCreatePage()
        {
            this.InitializeComponent();

            Windows.UI.Core.SystemNavigationManager.GetForCurrentView().BackRequested +=
                App_BackRequested;

        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            Frame rootFrame = Window.Current.Content as Frame;
            if (rootFrame.CanGoBack)
            {
                // Show UI in title bar if opted-in and in-app backstack is not empty.
                SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
                    AppViewBackButtonVisibility.Visible;
            }
        }

        private void App_BackRequested(object sender, Windows.UI.Core.BackRequestedEventArgs e)
        {
            Frame rootFrame = Window.Current.Content as Frame;
            if (rootFrame == null)
                return;

            // Navigate back if possible, and if the event has not 
            // already been handled .
            if (rootFrame.CanGoBack && e.Handled == false)
            {
                e.Handled = true;
                rootFrame.GoBack();
            }
        }
    }
}

Alright, now we've made a basic layout to issue an invoice.

The XAML file is self-explanatory, however you'll realize that we have put the CommandBar inside the Property Page.BottomAppBar.

<Page.BottomAppBar>
        <CommandBar HorizontalAlignment="Stretch">
            <CommandBar.PrimaryCommands>
                <AppBarButton Icon="Save" Label="Save" />
            </CommandBar.PrimaryCommands>
        </CommandBar>
    </Page.BottomAppBar>

...So basically we have assigned this CommandBar as the BottomAppBar.

The reason we do this is because when the on-screen keyboard opens, usually the keyboard will hover on top of the CommandBar, hiding it from the user. By putting it inside <Page.BottomAppBar>, the CommandBar will be visible to the user, at the bottom of the page, even if the user opens the keyboard. 

Now for the .cs file.

The OnNavigatedTo is the same as the one in the MainPage. However, this time, it will modify the app title bar to show the Back button.

The App_BackRequested() is the one that handles the Back Button clicked event. Basically, once clicked, if CanGoBack, GoBack().

Linking to InvoicesCreate From MainPage

Let's navigate from MainPage to InvoicesCreate.

Now, what we want to do is that when the User clicks/presses on the '+' button in the AppBar inside the Invoices PivotItem, we want the User to navigate to the InvoicesCreatePage.

So, let's do that.

Open MainPage.xaml. 

Now simply double-click on the '+' button inside the AppBar.

This will automatically generate the code-behind function named AppBarButton_Click that handles the AppBarButton_Click event.

(If you realized, I've already put the commented out function inside the .cs file, so feel free to use it too)

We can navigate to a different page inside our App using Frame.Navigate, like so:

 private void AppBarButton_Click(object sender, RoutedEventArgs e)
        {
            Frame.Navigate(typeof(InvoicesCreatePage));
        }

Yay, we're done!

Explanation: Open MainPage.xaml again, click on the '+' button and look at the properties. But instead, click on the Events button to show the Events available for the button (the button is on the top right of the Properties pane).

You'll see that for the Click event, it's wired to AppBarButton_Click.

Now try taking a look at the XAML and find the AppBarButton. You'll see the Designer have added a new property:

<AppBarButton Icon="Add" Label="Add Invoice" Click="AppBarButton_Click"/>

That's how events are wired inside UWP. So basically, you can define the function inside the code-behind (in this case, MainPage.xaml.cs) and then simply wire it to the element inside the view by referring to it inside the XAML. Easy-peasy.

Okay, now Deploy and Play.

Congrats!

Example is available on Github:

https://github.com/purrmiaw/InvoiceJeNoDatabase

Now we're going to make the database connection.