Monthly Archives: February 2017

Xamarin Forms: ListView with SQLite

Previously we stored our entry in a SQLite database. Now we want to be able to look at a list of the things we previously saved.

ListView

When you want to display a list of objects, your best option is most likely the aptly named ListView. The ListView binds to a dataset and then displays each item according to a template in a scrollable list.

This is exactly what we want to use to view our saved properties for the cashflow calculator.

Getting the Data

There are several ways to get the data out of the SQLite database and into the ListView. Two of the most common ways are returning the result to a List or creating a CursorAdapter.

I chose to use the List method as it is simple and worked well with how I have set up the database calls to be asynchronous.

A New Page

We need to create a SavedProperties Page and set up our ListView there.

In the XAML file, we need to create our ListView and our template for each item. For now I just want to display the property name and its value.


<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SimpleCashflowCalculator.SavedPropertiesPage">
    <ListView x:Name="saved_properties_list">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout Orientation="Horizontal" 
                        HorizontalOptions="FillAndExpand"
                        Margin="20, 10, 20, 0" >
                        <Label Text="{Binding Name}" HorizontalOptions="StartAndExpand" />
                        <Label Text="{Binding Value}" />
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage>

This creates a ListView called saved_properties_list and gives it an item template with 2 text labels. It is now expecting a Name field and a Value field for whatever objects are bound to this ListView.

Setting the ItemSource

The way to actually tell the ListView which dataset to use is by setting its ItemSource. We want to refresh this view every time we switch to it so that it always has the latest data. To do that we are going to set the ItemSource in the OnAppearing event.


        protected override async void OnAppearing()
        {
            base.OnAppearing();
            saved_properties_list.ItemsSource = await SimpleCashflowCalculatorPage.Database.GetPropertiesAsync();
        }

This is a parent class method so we override it and then call what is often called the super method or the parent method before adding our changes.

From the previous post we added this method to our Database class.


public Task> GetPropertiesAsync()
{
    return database.Table().ToListAsync();
}

We use this to set the ItemSource of the ListView to be all of our Properties in the database.

The next thing we want to add is a click event listener so that when a ListView Item is clicked, it will go to the edit page for that Property and pass its database ID to allow it to be edited.

Xamarin Forms Local Storage with SQLite

In the process of rewriting the rental property cashflow calculator app from Android and Java to Xamarin, I have gotten to the point where the calculator part is working pretty much how I want and already has some improvements over the Java version.

Today I added the ability to save the properties to a local SQLite database.

Add a NuGet Package

Since this is a Xamarin Forms application, I am trying to write as little platform specific code as possible. The SQLite-net PCL NuGet package helps significantly in this regard.

You will end up adding it to your main Forms project as well as to each of the platform specific projects that you want to build for.

FileHelper Interface and Implementation

The only thing you end up needing platform specific code for when using this package is for implementing the interface to find where the SQLite file is stored on the device.

In the Forms project, add a new interface called IFileHelper that looks like this:


    public interface IFileHelper
    {
        String GetLocalFilePath(string filename);
    }

Then in your YourAppName.Droid project, you would create a new class that implements this interface. It would look something like this:


using System;
using System.IO;
using Xamarin.Forms;
using YourAppName.Droid;

[assembly: Dependency(typeof(FileHelper))]
namespace YourAppName.Droid
{
    public class FileHelper : IFileHelper
    {
        public string GetLocalFilePath(string filename)
        {
            string path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
            return Path.Combine(path, filename);
        }
    }
}

Note the [assembly …] part of the code. This is a metadata attribute that registers this class as a FileHelper to the DependencyService. If you do not register your interface, the DependencyService will not be able to find it at run time and will throw an error.

Creating a Model

The easiest way of handling the data that goes in and out of your database is with a class that models all of the attributes of your SQLite table. In my case that is a property. Your model will be a basic class with a few fields. You will most likely want an ID field that auto increments. Here is the Property model I used for an example.


using SQLite;
namespace YourAppName
{
    public class Property
    {
        [PrimaryKey, AutoIncrement]
        public int ID { get; set; }
        public string Name { get; set; }
        public string Value { get; set; }
        public string Mortgage { get; set; }
        public string Rent { get; set; }
        public string Vacancy { get; set; }
        public string Repair { get; set; }
        public string Management { get; set; }
        public string Tax { get; set; }
    }
}

Creating Your Database Class

Now that you have your model and file helpers, you will most likely want a class to handle common operations for your Model like fetching multiple records, adding a new record, fetching a single record, and deleting a single record.

Here is an example of a class that handles these actions.


    public class PropertyDatabase
    {
        readonly SQLiteAsyncConnection database;

        public PropertyDatabase(string db_path)
        {
            database = new SQLiteAsyncConnection(db_path);
            database.CreateTableAsync().Wait();
        }

        public Task> GetPropertiesAsync()
        {
            return database.Table().ToListAsync();
        }

        public Task GetPropertyAsync(int id)
        {
            return database.Table().Where(p => p.ID == id).FirstOrDefaultAsync();
        }

        public Task SavePropertyAsync(Property property)
        {
            if (property.ID != 0)
            {
                return database.UpdateAsync(property);
            }
            else {
                return database.InsertAsync(property);
            }
        }

        public Task DeletePropertyAsync(Property property)
        {
            return database.DeleteAsync(property);
        }
    }

You may want to add the ability to get a specific set of records, for example all properties that have a value above or below a certain amount.

Also notice that we create an asynchronous database connection that is only designed to be opened once and left open waiting for commands during the lifecycle of the app. This avoids the overhead of creating a new database connection for every operation.

Setting It All Up

Now that we have a class set up to allow us to easily access the database, we need to create an instance of it and start performing some operations.


        static PropertyDatabase database;

        public static PropertyDatabase Database
        {
            get
            {
                if (database == null)
                {
                    database = new PropertyDatabase(DependencyService.Get().GetLocalFilePath("YourAppNameSQLite.db3"));
                }
                return database;
            }
        }

Here we use the DependencyService to ask for the platform specific FileHelper that we created earlier so we can access the SQLite database file.

Now you are all ready to start using the database instance. For an example, I created a Save Property button that calls the following method on the ‘Clicked’ event:


        void SaveProperty(object sender, EventArgs e)
        {
            var property = new Property();
            property.ID = property_id;
            property.Value = property_value.Text;
            property.Mortgage = mortgage.Text;
            property.Rent = monthly_rent_cash.Text;
            property.Vacancy = vacancy_cash.Text;
            property.Repair = repair_cash.Text;
            property.Management = property_management_cash.Text;
            property.Tax = property_tax_cash.Text;

            Database.SavePropertyAsync(property);
        }

My next step is to create a page for the app that lists the currently saved properties. This should be pretty straightforward with the PropertyDatabase class I created and a ListView.

Xamarin Tutorials and Documentation

If you get stuck, the tutorials on Xamarin’s Developer Center were very helpful for learning this and the source code for their ToDo app ended up being invaluable as well.

Also you can reach out to me at travis at evolvingdeveloper.com

First Monkey-X Game: Images and Theme

Games in general can get by with just basic shapes like squares, circles and triangles if the gameplay is good enough.

But we don’t want to just get by, so we are going to add images to our game that have a theme.

If you recall from earlier in the series, our theme is being underwater in a submarine fighting various kinds of biological and mechanical enemies.

We Need Art

The first thing we need is art.

There are a variety of ways to acquire game art. You can make your own, hire someone to draw you custom art, buy some already created art assets, or use some free art from a site like opengameart.org

Personally I like to draw and make little art assets. There are a lot of free tools that you can use and the images you make don’t have to be great, especially not for your first game.

What Will We Draw?

Let’s start by making a list of the objects in our game that we want to have art for.

  1. The Player
  2. 3 or more Enemy types
  3. 1 or more Bosses
  4. 1 or more Projectiles
  5. 1 or more Power Ups

For now we are going to start with the Player, some Enemies, some Projectiles, and a Boss. We will save the power ups and other images for later.

What Style Will We Use

One of the important things about your art is that is has a consistent style. Most of the time you don’t want to be mixing some 8 bit pixel art with cartoonish drawing style art.

You also want a style that lends itself to the theme and setting of your game. For example, you probably don’t want a cartoony and silly style for a horror game.

If you want you can pick a different style but for this I chose a simple flat basic shape style.

Adding the Images to the Game

Pack it Up

One of the ways to make your images more efficient for your game is to pack it into something called a sprite sheet. There is a free tool that will help with this called Texture Packer that works with FantomEngine.

You simply bring in the set of images that you want to turn into a sprite sheet and it puts them all together and allows you to export them into a single image. It then lets you save a file that describes that image so your game knows how to grab each one.

Fantom Engine only knows how to read the LibGDX and Sparrow data file formats for sprite sheets so make sure you pick one of those in the Texture Packer output file settings.

The Player

Let’s just start with the player and a single image and animation.

I created a simple set of 3 images to represent the player’s submarine. The only difference being the propeller so when we animate it, it will look like the propeller is spinning.

We are going to put it into our games ‘.data’ folder so we can load it later.

Loading the Images and Animation

Now that we have created an image, we need to load it into the game and associate it with the player.

What we are doing here is loading the image into memory, then creating an Animation object to replace our regular box that we had before. The Animation needs an image, it needs to know where in the image the animation starts, how big each frame is, and how many frames there are.

Everything else about the Fantom object remains the same so collision, movement, and everything else still works but now we have an animated little submarine instead of a box.

Using a Sprite Sheet

Now that we have a single image and animation working, we will see how to use a full sprite sheet.

I created an image for 3 different enemies, 2 different projectiles, the player, and a boss.

We then put all of the images into Texture Packer and publish the sprite sheet and the atlas mapping file. Remember to use the LibGDX or Sparrow formats for the atlas mapping file. Then we are going to put both into our games ‘.data’ folder.

Let’s start adding our new sprite atlas to the game and by getting our player’s animation from the new combined sprite sheet.

As you can see, this is not all that different from using an individual image for the animation, but it saves our game time and resources.

Fewer Enemy Types

Previously, we had all sorts of randomly sized enemies flying around the screen. Now since we have images or animations for 3 enemies, we will limit our enemy characters to being 1 of the 3 that we have images for. This is going to be a major overhaul of our enemy generator function.

First we need to pick our next enemy type at random. Then we will build the animation or regular image from our sprite sheet based on which enemy type it is.

Projectiles

The final 2 things that need to use our sprite atlas currently our the projectiles and the Boss.
Let’s start with projectiles.

And the Boss

Last but not least the Boss.

Now just by adding some images our game has a little underwater theme going on.

Xamarin TextChanged Event on Two Fields That Change Each Other

In the new version of the Cashflow Calculator I am making with Xamarin, I wanted to create the ability to input most of the expenses as both exact money values if you knew them or percentages of the monthly rent. This is a very common method of estimating repairs, vacancies, and property management fees.

I Change You, You Change Me

The idea was to have the percentage get set whenever the cash value was changed and the cash value get set whenever the percentage was changed.

But if you just create a normal TextChanged event on both of them, as soon as you make a change to one, it fires its TextChanged event which changes the other field and fires the other field’s TextChanged event which sets the one you are working on.

This does not work.

Stop Listening For a Sec

The solution to this is to disconnect the field you are about to change from its TextChanged listener and reconnect it when you are done changing it. We will use the event for calculating our rent percentage from the price of the property as an example.


async void CalculateRentCash(object sender, TextChangedEventArgs e)
{
    monthly_rent_cash.TextChanged -= CalculateRentPercent;
    await Task.Yield();
    var percent_val = GetFloat(monthly_rent_percent.Text);
    var new_rent_cash = GetFloat(property_value.Text) * (percent_val/100.0);
    monthly_rent_cash.Text = new_rent_cash.ToString();
    monthly_rent_cash.TextChanged += CalculateRentPercent;
}

The important parts of this function are the async in the function definition and the await Task.Yield() after removing CalculateRentPercent from the monthly_rent_cash.TextChanged listener.

Without the await Task.Yield() the function would tell the app that it needs to remove the listener but it would not do it right away. The task would be queued up but put on hold until the current task finished. It would then proceed through the function and the monthly_rent_cash field would still fire CalculateRentPercent.

With the await Task.Yield() line, the app pauses its execution of the current function and lets the Task we just created to remove the TextChanged listener finish before it continues.

If you are new to C# or Xamarin, remember that anytime you have a line that uses await in your function definition, you need async as part of the function description.

There may be other solutions to this problem, but this is the easiest one I came across so far. If you know a better solution, email me at travis at evolvingdeveloper.com and let me know.

Found the solution on the Xamarin forums.