My First Windows Phone App Location Based Notifications Part 1

C#,Windows-Phone

Posted by Alex Peta on February 25, 2013 Copyright© from Bing images : Playa Roja in Paracas National Reserve, Peru (© Istvan Kadar Photography/Getty Images)

I will be starting a series of posts regarding my recent interest in Windows Phone 8 development. Then end goal is to build a simple application all they way from File > New Application up to having it ready for end users via the Windows Phone Marketplace (at least I hope I will finish it)

The idea and disclaimer

 Well I don’t think it’s original, I’m pretty sure it has already been implemented on other platforms, I didn’t check if something already exists for Windows Phone 8 because I will do it anyway : location based notification using the built-in phone GPS to track user location and show reminders if the phone is near a desired location.

You can follow along my progress by reading this series as well as visiting the dedicated Github repo with the full code version.

Because the UI/UX and all the other delicious eye candy visuals will be the last thing that I will focus on I am starting the series from the “bottom” up , that is  in tech language translated to starting with the data layer.

Data Layer

The data layer that I have created has 2 parts  Model and Data Access.

Model : BaseModel class

namespace LocationBasedNotifications
{
    public abstract class BaseModel : INotifyPropertyChanged,INotifyPropertyChanging
    {
        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        public event PropertyChangingEventHandler PropertyChanging;

        protected void NotifyPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if(handler != null)
            {
                handler(this,new PropertyChangedEventArgs(propertyName));
            }
        }

        protected void NotifyPropertyChanging(string propertyName)
        {
            var handler = PropertyChanging;
            if (handler != null)
            {
                handler(this, new PropertyChangingEventArgs(propertyName));
            }
        }
        #endregion INotifyPropertyChanged

        protected virtual bool IsValid()
        {
            throw new NotImplementedException();
        }
    }
}

As you can notice my base class implements as expected INotifyPropertyChanged as well as INotifyPropertyChanging (it seems this is a good thing to do performance wise when it comes to WP8)

namespace LocationBasedNotifications
{
    [Table]
    public class Location : BaseModel
    {
        #region Properties
        private int _locationId;

        [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
        public int LocationId
        {
            get { return _locationId; }
            set { _locationId = value; }
        }
        
        private string _name;

        [Column]
        public string Name
        {
            get { return _name; }
            set 
            {
                if (_name == value)
                {
                    return;
                }

                NotifyPropertyChanging("Name");
                _name = value;
                NotifyPropertyChanged("Name");
            }
        }

        private double _latitude;

        [Column]
        public double Latitude
        {
            get { return _latitude; }
            set 
            {
                if (_latitude == value)
                {
                    return;
                }

                NotifyPropertyChanging("Latitude");
                _latitude = value;
                NotifyPropertyChanged("Latitude");
            }
        }

        private double _longitude;

        [Column]
        public double Longitude
        {
            get { return _longitude; }
            set 
            {
                if (_longitude == value)
                {
                    return;
                }

                NotifyPropertyChanging("Longitude");
                _longitude = value;
                NotifyPropertyChanged("Longitude");
            }
        }

        private string _description;

        [Column]
        public string Description
        {
            get { return _description; }
            set 
            {
                if (_description == value)
                {
                    return;
                }

                NotifyPropertyChanging("Description");
                _description = value;
                NotifyPropertyChanged("Description");
            }
        }

        // Version column aids update performance.
        [Column(IsVersion = true)]
        private Binary _version;
        #endregion Properties

        #region Constructors
        public Location() : this(string.Empty,0D,0D,string.Empty)
        {
        }
        public Location(string name, double latitude, double longitude, string description)
        {
            Name = name;
            Latitude = latitude;
            Longitude = longitude;
            Description = description;
        }
        #endregion Constructors

    }
}

This is the Location entity that inherits the above BaseModel. As you noticed all of the public properties are are decorated with attributes from the System.Data.Linq.Mapping namespace. The reason for this is that Windows  Phone 8 uses as persistent storage Linq to SQL via the DataContext on the isolated storage database.

Data Access

Now we need to implement the DataContext  and the repository interface contracts:

namespace LocationBasedNotifications.Contracts
{
    public interface IRepository
        where T : BaseModel
    {
        IEnumerable GetInMemoryLocations();
        bool AddItem(T itemToAdd);
        bool RemoveItem(T itemToRemove);
        void Save(IEnumerable list);
    }
}

The DataContext

namespace LocationBasedNotifications.Repository
{
    public class LocalStorageRepository : IRepository
    {
        #region Private Members
        private ReminderDataContext _db;
        #endregion Private Members

        #region Constructors
        public LocalStorageRepository()
        {
            _db = App.LocalDB;
        }
        #endregion Constructors

        #region IRepository
        public IEnumerable GetInMemoryLocations()
        {
            var results = from d in _db.Locations
                          select d;

            return results;
        }

        public bool AddItem(Location itemToAdd)
        {
            if (itemToAdd == null)
            {
                throw new ArgumentNullException("location cant be null");
            }

            try
            {
                _db.Locations.InsertOnSubmit(itemToAdd);
                _db.SubmitChanges();
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }

        public bool RemoveItem(Location itemToRemove)
        {
            if (itemToRemove == null)
            {
                throw new ArgumentNullException("location cant be null");
            }

            try
            {
                _db.Locations.DeleteOnSubmit(itemToRemove);
                _db.SubmitChanges();
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }

        public void Save(IEnumerable list)
        {
            throw new NotImplementedException();
        }
        #endregion IRepository
        
    }
}

And finally we need to initialize the storage. This is done in the App.xaml.cs constructor

    private void InitializeDatabase()
    {
        ReminderDataContext db = new ReminderDataContext(Constants.DBConnectionString);
        if (!db.DatabaseExists())
        {
            db.CreateDatabase();
        }
        _localDB = db;
    }

Afte the initialization im keeping a reference to the DataContext in the App object via the _localDB property that I will be using throughout the whole application.

A think to note here is the format of the connection string. Because I don’t like hardcoded strings, I have created a utility class that stores constants and this is where I have defined my connection string. It looks like this:

“Data Source=isostore:/LocationBasedReminders.sdf” where isostore si the root location of the path and it basically represents the local folder previously known as isolated storage.

Mode details about how connection strings are in Windows Phone 8 can be found here.

This is it for this first post in the series.I have shown today how to have a data layer up and running for Windows Phone 8. If you wish to see it in action check out the Github project page.