Windows Phone For Newbies – Geofencing in Windows Phone 8.1 WinRT

Geofencing was one of the newest features Windows Phone 8.1 provided and for the developers it indeed was cool. Previously people did it their way but it’s always better to have an api in our hand. So, before digging into that i strongly suggest you guys to read my previous 2 articles if you haven’t done it already.

1. The Complete Reference of Map Control in Windows Phone 8.1 RT

2. Tracking Location in Windows Phone 8.1

These two would get you started pretty fast and you’d probably want that. If you already read my aforementioned 2 articles, I expect you know how to use a map control in Windows Phone 8.1. We’re going to need that later.

Geofencing:

Geofencing is a mechanism where you put a virtual boundary around a specific point of interest and you want to interact with the user when you arrive or leave that specific boundary. You seriously can do pretty amazing stuff with it actually.

Initial Work:

Now, let’s take a more practical approach to this, every time I go into my room, Im supposed to check my mails. But I usually forget that. How cool it would be if my phone reminds me every time I get into my room and tells me to check my mail?  😉

So, let’s go ahead and create a new Windows Phone app and name it GeoFencingTest. Now, lets see how to do that actually.

So, first of all go over your Package.appxmanifest file and go to the Capabilities Tab and select the Location capability.

Geofencing 1

Now, when you are done with that, let’s move on and start cracking. Before going deep lets get a basic UI running. And it looks like following:

GeoFencing - 2

And on the XAML part it looks like the following:

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="4*"></RowDefinition>
            <RowDefinition Height="8*"></RowDefinition>
        </Grid.RowDefinitions>
        

        <Grid Grid.Row="0">
            <TextBlock Text="GeoFencing Sample" FontSize="25" Margin="10"/>
        </Grid>

        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>

            <StackPanel Margin="10">
                <TextBlock Text="Longitude" Margin="0,0,0,15"  FontSize="20"></TextBlock>
                <TextBlock Text="Latitude"  Margin="0,0,0,15" FontSize="20"></TextBlock>
                <TextBlock Text="Altitude"  Margin="0,0,0,15" FontSize="20"></TextBlock>
            </StackPanel>

            <StackPanel Grid.Column="1" Margin="10">
                <TextBlock Name="Longitude" Margin="0,0,0,15"  FontSize="20"></TextBlock>
                <TextBlock Name="Latitude"  Margin="0,0,0,15" FontSize="20"></TextBlock>
                <TextBlock Name="Altitude"  Margin="0,0,0,15" FontSize="20"></TextBlock>
            </StackPanel>

        </Grid>

        <Grid Grid.Row="2" Margin="10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="4*"></ColumnDefinition>
                <ColumnDefinition Width="7*"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>

            <CheckBox Content="Single Use"></CheckBox>
            <TextBlock Grid.Row="1" FontSize="20" Text="Dwell Time" Margin="0,8,0,0"/>
            <TextBox Grid.Column="1" Name="DwellTime"  Grid.Row="1"/>

            <Button x:Name="CreateGeoFencingButton" Grid.Row="2" Grid.ColumnSpan="2" Content="Create GeoFence" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"/>
            
        </Grid>

    </Grid>

Before going in deep on what is for what let’s get some basic stuff done. Let’s get our current location first.

Since you guys have seen in the last articles, it’s fairly easy to do so. All I’m doing here is get the current location using Geolocator and put the Latitude, Longitude and Altitude into the textblocks defined in the MainPage.xaml.

    public sealed partial class MainPage : Page
    {
        Geolocator geolocator = new Geolocator();
        CancellationTokenSource CancellationTokenSrc = new CancellationTokenSource();

        public MainPage()
        {
            this.InitializeComponent();

            this.NavigationCacheMode = NavigationCacheMode.Required;
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {

            InitializeLocation();

        }

        async private void InitializeLocation()
        {
            try
            {

                geolocator = new Geolocator();

                CancellationTokenSrc = new CancellationTokenSource();
                CancellationToken token = CancellationTokenSrc.Token;

                var position = await geolocator.GetGeopositionAsync(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(30)).AsTask(token);

                Longitude.Text = position.Coordinate.Point.Position.Longitude.ToString();
                Latitude.Text = position.Coordinate.Point.Position.Latitude.ToString();
                Altitude.Text = position.Coordinate.Point.Position.Altitude.ToString();
            }

            catch (Exception)
            {
                if (geolocator.LocationStatus == PositionStatus.Disabled)
                {
                    ShowMessage("Location Services are turned off");
                }

            }
            finally
            {
                CancellationTokenSrc = null;
            }

        }

        private async void ShowMessage(string message)
        {
            MessageDialog dialog = new MessageDialog(message);
            await dialog.ShowAsync();
        }
    }

The only thing that is interesting here is having a CancellationToken generated from a CancellationTokenSource. Usually these are used if you really want control over your task after it’s being fired, the rest of the procedure should look familiar as it’s a basic Geolocator usage to find current geolocation.

Setting up a GeoFence:

Now comes the setting up the actual GeoFence part and even this is fairly simple. The method looks like the following:

        Geofence geofence = null;
        int DefaultDwellTimeInSeconds = 0;
        private void SetupGeofence()
        {
            //Set up a unique key for the geofence
            string GeofenceKey = "My Home Geofence";
            BasicGeoposition GeoFenceRootPosition = GetMyHomeLocation();

            double Georadius = 500;

            // the geocircle is the circular region that defines the geofence
            Geocircle geocircle = new Geocircle(GeoFenceRootPosition, Georadius);

            bool singleUse = (bool)SingleUse.IsChecked;

            //Selecting a subset of the events we need to interact with the geofence
            MonitoredGeofenceStates GeoFenceStates = 0;

            GeoFenceStates |= MonitoredGeofenceStates.Entered;
            GeoFenceStates |= MonitoredGeofenceStates.Exited;

            // setting up how long you need to be in geofence for enter event to fire
            TimeSpan dwellTime;

            dwellTime = DwellTime.Text!=""? ParseTimeSpan(DwellTime.Text) : TimeSpan.FromSeconds(DefaultDwellTimeInSeconds);

            // setting up how long the geofence should be active
            TimeSpan GeoFenceDuration;
            GeoFenceDuration = TimeSpan.FromDays(10);

            // setting up the start time of the geofence
            DateTimeOffset GeoFenceStartTime = DateTimeOffset.Now;

            geofence = new Geofence(GeofenceKey, geocircle, GeoFenceStates, singleUse, dwellTime, GeoFenceStartTime, GeoFenceDuration);

            //Add the geofence to the GeofenceMonitor
            GeofenceMonitor.Current.Geofences.Add(geofence);

        }

        private TimeSpan ParseTimeSpan(string DwellTimeInSeconds)
        {
            return TimeSpan.FromSeconds(Double.Parse(DwellTimeInSeconds));

        }

        private static BasicGeoposition GetMyHomeLocation()
        {
            BasicGeoposition GeoFenceRootPosition;
            GeoFenceRootPosition.Latitude = 23.742766;
            GeoFenceRootPosition.Longitude = 90.417566;
            GeoFenceRootPosition.Altitude = 0.0;
            return GeoFenceRootPosition;
        }

Now, there’s quiet a lot to catch up.

The first one is definitely the GeofenceKey. Put a GeofenceKey in position just to identify a specific Geofence. I put s generic string to identify my home geofence.

Then I called up GetMyHomeLocation() method to set the geofence center to the location of my room. This will identify the center of our desired Geofence.

And the next thing to define is a radius that will define the radius of our circular geofence. We are using Geocircle object to define our geofence here, thus we are using a center and a radius in meters to defined our geofence. You can definitely see the next thing we did is define our geocircle. Actually the Geofence takes a Geoshape object to define it’s radius and currently only Geocircle is supported.

            string GeofenceKey = "My Home Geofence";
            BasicGeoposition GeoFenceRootPosition = GetMyHomeLocation();

            double Georadius = 500;

            // the geocircle is the circular region that defines the geofence
            Geocircle geocircle = new Geocircle(GeoFenceRootPosition, Georadius);

Now, we have put a checkbox in our XAML named SingleUse. This is supposed to define whether our geofence would be used for only one time or not. You can set up temporary one time used geofence using this.


bool singleUse = (bool)SingleUse.IsChecked;

Now, the next thing we did is we defined how our desired geofence would be treated. Which events are we considering with this geofence? Should this be fired only when we get into that geofence or should this will only be considered when we exit the geofence, or even we remove the geofence? We can actually select all or a subset of that group. So we used Logical OR operator to add up all the cases we want our geofence to react upon.


            MonitoredGeofenceStates GeoFenceStates = 0;

            GeoFenceStates |= MonitoredGeofenceStates.Entered;
            GeoFenceStates |= MonitoredGeofenceStates.Exited;

Let’s move on into the time domain now. Now we need to figure how long we need to stay in our favourite geofence to trigger up it’s desired events. I put a textbox in front to define that in seconds, if that is defined, we fire out events from our geofence in that number of seconds and if not we fire out events in our default dwell time defined by 0 seconds.

            // setting up how long you need to be in geofence for enter event to fire
            TimeSpan dwellTime;

            dwellTime = DwellTime.Text!=""? ParseTimeSpan(DwellTime.Text) : TimeSpan.FromSeconds(DefaultDwellTimeInSeconds);

You can even define how long a geofence should be up and running. Like I want my rooms geofence to be running for next 10 days.


            // setting up how long the geofence should be active
            TimeSpan GeoFenceDuration;
            GeoFenceDuration = TimeSpan.FromDays(10);

Even with that thing defined, one question remains, even though it will run for 10 days, when does the geofence gets activated so it can start counting to that defined 10 days. Answer is right below:


// setting up the start time of the geofence
            DateTimeOffset GeoFenceStartTime = DateTimeOffset.Now;

Well, the only thing left to do is create our desired geofence and add it to GeofenceMonitor.


            geofence = new Geofence(GeofenceKey, geocircle, GeoFenceStates, singleUse, dwellTime, GeoFenceStartTime, GeoFenceDuration);
            
            //Add the geofence to the GeofenceMonitor
            GeofenceMonitor.Current.Geofences.Add(geofence);

Now, that’s how you create your own geofence and add it to the GeofenceMonitor. Now you might wonder that whether you’d really have to define all that parameters to create a geofence. Not actually, the littlest you can do is define an Id and a Geocircle to start your geofence. 😉 The rest of the values would take the default assumption.

Handling GeoFence Notifications on Foreground:

We have all our background work to create a geofence but we wont be able to do a single thing unless we test our geofence. Now, we have already defined that our geofence would trigger events after the aforementioned dwellTime and will trigger events if I enter or leave it. So, I definitely have to attach a event handler at a certain place. Don’t I?

Before that, let’s create the method stub for the click event handler for CreateGeoFencingButton and start SetupGeofence() method inside it. If you don’t know how to do that, select the CreateGeoFencingButton in XAML, go to properties, select events tab and double click on the click textbox.


private void CreateGeoFencingButton_Click(object sender, RoutedEventArgs e)
{
SetupGeofence();
}

Then let’s add the handler in the end of SetupGeofence()


GeofenceMonitor.Current.GeofenceStateChanged += Current_GeofenceStateChanged;

Now, let’s say we want to show a message every time I enter and exit my room’s geofence. The handler might look like the following:

        private async void Current_GeofenceStateChanged(GeofenceMonitor sender, object args)
        {
            var Reports = sender.ReadReports();

            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                foreach (GeofenceStateChangeReport report in Reports)
                {
                    GeofenceState state = report.NewState;

                    Geofence geofence = report.Geofence;

                    if (state == GeofenceState.Entered)
                    {
                        ShowMessage("You are pretty close to your room");

                    }
                    else if (state == GeofenceState.Exited)
                    {

                        ShowMessage("You have left pretty far away from your room");
                    }
                }
            });
        }

There you go! That’s how you set up your geofence in an app running in the foreground.

Setting up GeoFence on the background:

Now, this is where things get a little bit tricky. There’s a number of steps involved in this.

  1. Create a Windows Runtime Component Project and add it to your solution.
  2. Change Package.appxmanifest to declare the BackgroundTask that has been created.
  3. Register the BackgroundTask
  4. Handle Geofence Notifications from Background Task

Create a Windows Runtime Component Project:

Usually, background tasks are windows runtime component so you have to add one to your solution. Please go over to your solution and add a Windows Runtime Project.

GeoFencing - 3

GeoFencing - 4

After the new project is created go over class1.cs and rename it to your liking . I renamed it to BackgroundTask and added IBackgroundTask interface to the class and implemented it. I didn’t write anything afterwards. Let’s just keep it like that for a while and move to our GeofenceTest Project. Go over references and   add the newly created GeofenceTask.BackgroundGeofenceTask project to it. So our Wp8.1 project now has reference to the GeofenceTask.BackgroundGeofenceTask project.

Change Package.appxmanifest to declare the BackgroundTask:

Now let’s scoot over to our Package.appxmanifest file and go over Declarations tab. From Available Declarations combobox select BackgroundTask and select loction under the Properties list.

GeoFencing - 5

Now on the Entry point field please put the full qualified assembly name of your newly created background task. Don’t get confused. It’s fairly easy. Let’s have a look at BackgroundGeofenceTask class first.

namespace GeofenceTask
{
    public sealed class BackgroundGeofenceTask : IBackgroundTask
    {
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            throw new NotImplementedException();
        }
    }
}

Now put the name as (namespace.classname) format so that leaves us with GeofenceTask.BackgroundGeofenceTask

GeoFencing - 6

Register the BackgroundTask:

Now comes the part where you register the BackgroundTask. We need to register the background task to the app so it knows it to invoke it on time.  The registering method looks like following:

private async Task RegisterBackgroundTask()
        {
            BackgroundAccessStatus backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync();

            var geofenceTaskBuilder = new BackgroundTaskBuilder
            {
                Name = "My Home Geofence",
                TaskEntryPoint = "GeofenceTask.BackgroundGeofenceTask"
            };

            var trigger = new LocationTrigger(LocationTriggerType.Geofence);
            geofenceTaskBuilder.SetTrigger(trigger);

            var geofenceTask = geofenceTaskBuilder.Register();
            geofenceTask.Completed += GeofenceTask_Completed;

            switch (backgroundAccessStatus)
            {
                case BackgroundAccessStatus.Unspecified:
                case BackgroundAccessStatus.Denied:
                    ShowMessage("This application is denied of the background task ");
                    break;
            }

        }

Let’s see what we have in here now. The very first one is get the BackgroundAccessStatus. That helps us to know whether our application is capable of accessing BackgroundTasks. Now, let’s move up and use BackgroundTaskBuilder to create the background task we intend to create. Now, if you look at the TaskEntryPoint we provided there, you’d now realize why we created our Background Task project before and added it to the manifest. Because we are using the same entry point name here. I put a name to identify the background task. This is needed as if there is another background task with the same name you would be thrown an exception. If you want to know whether there is another BackgroundTask with the same name you can iterate through BackgroundTaskRegistration.AllTasks and then make sure whether there is one with the same name or not. You can use a method like the following to do so:

        public static bool IsTaskRegistered(string TaskName)
        {
            var Registered = false;
            var entry = BackgroundTaskRegistration.AllTasks.FirstOrDefault(keyval => keyval.Value.Name == TaskName);

            if (entry.Value != null)
                Registered = true;

            return Registered;
        }

I haven’t used that in this solution but feel free to definitely use this. You can even unregister to make sure that your Background Task is unregistered to open up places for others

        public static void Unregister(string TaskName)
        {
            var entry = BackgroundTaskRegistration.AllTasks.FirstOrDefault(keyval => keyval.Value.Name == TaskName);

            if (entry.Value != null)
                entry.Value.Unregister(true);
        }

The next thing that comes off is defining the LocationTrigger for the BackgroundTaskBuilder object. So, we defined a new LocationTrigger of type LocationTriggerType.Geofence and used SetTrigger method to set it up. Then we used BackgroundTaskBuilder object to register the task and we instantiated a GeofenceTask_Completed event handler for that too.

At the bottom you’d see a switch with backgroundAccessStatus and putting a MessageDialog when it’s denied or unspecified.

Handle Geofence Notifications from Background Task:

So, lets move to our Windows Runtime Component which actually is the Background Task project and implement the IBackgroundTask interface. A method named

public void Run(IBackgroundTaskInstance taskInstance)

would pop up, we’d put our regular geofence event handling in there like there in the Foreground example. Now it looks like following when we are handling it from background

    public sealed class BackgroundGeofenceTask : IBackgroundTask
    {
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            var Reports = GeofenceMonitor.Current.ReadReports();
            var SelectedReport =
                Reports.FirstOrDefault(report => (report.Geofence.Id == "My Home Geofence") && (report.NewState == GeofenceState.Entered || report.NewState == GeofenceState.Exited));

            if (SelectedReport==null)
            {
                return;
            }

            //We are creating a toast this time as this is running in Background
            var ToastContent = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);

            var TextNodes = ToastContent.GetElementsByTagName("text");

            if (SelectedReport.NewState == GeofenceState.Entered)
            {
                TextNodes[0].AppendChild(ToastContent.CreateTextNode("You are pretty close to your room"));
                TextNodes[1].AppendChild(ToastContent.CreateTextNode(SelectedReport.Geofence.Id));
            }
            else if(SelectedReport.NewState == GeofenceState.Exited)
            {
                TextNodes[0].AppendChild(ToastContent.CreateTextNode("You are pretty close to your room"));
                TextNodes[1].AppendChild(ToastContent.CreateTextNode(SelectedReport.Geofence.Id));
            }

            var settings = ApplicationData.Current.LocalSettings;

            if (settings.Values.ContainsKey("Status"))
            {
                settings.Values["Status"] = SelectedReport.NewState;
            }
            else
            {
                settings.Values.Add(new KeyValuePair<string, object>("Status", SelectedReport.NewState.ToString()));
            }

            var Toast = new ToastNotification(ToastContent);
            var ToastNotifier = ToastNotificationManager.CreateToastNotifier();
            ToastNotifier.Show(Toast);

        }
    }

Now, this looks a wee bit different from the first example. The first change that is noticable is that we are now selecting the reports based on our geofence id and the report’s new state. As we are in background now, we are using our geofence id to get the proper geofence from the whole list. And as now we are in background we are using a Toast Notification instead of a MessageDialog to show our notification.

Handling it from the App Side:

Now you guys might get confused what to do with the foreground code we made earlier. Do we need Current_GeofenceStateChanged event handler anymore. Now here we might have to be a bit careful. Now if we want our app to react different when it is on foreground and make some UI changes it needed then we have to use GeofenceTask_Completed event rather than Current_GeofenceStateChanged. And there’s another thing to be added. We get our GeofenceMonitor Reports using  GeofenceMonitor.Current.ReadReports() and this step can only be done once for every change. So if your background reads it first then, your foreground app would not be able to read it. So, we have to save it somewhere when the background reads it so our foreground app can read it from there.

So we are using ApplicationData.Current.LocalSettings to save our state in the Background Task. If you look closely you’d find the following snippet:


            var settings = ApplicationData.Current.LocalSettings;

            if (settings.Values.ContainsKey("Status"))
            {
                settings.Values["Status"] = SelectedReport.NewState;
            }
            else
            {
                settings.Values.Add(new KeyValuePair<string, object>("Status", SelectedReport.NewState.ToString()));
            }

So, in our app side GeofenceTask_Completed event handler we’d read the status and fill up a new textblock.

Thus we added a new set of textblocks in the MainPage.xaml


<TextBlock Grid.Row="2" Text="Status" FontSize="25"/>
<TextBlock Grid.Row="2" Grid.Column="1" Name="Status"  FontSize="25"/>

Now, our GeofenceTask_Completed event handler looks like the following:

        private async void GeofenceTask_Completed(BackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs args)
        {
            if (sender != null)
            {
                // Update the UI with progress reported by the background task
                await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                {
                    try
                    {
                        // If the background task threw an exception, display the exception
                        args.CheckResult();

                        var settings = ApplicationData.Current.LocalSettings;

                        // get status
                        if (settings.Values.ContainsKey("Status"))
                        {
                            Status.Text = settings.Values["Status"].ToString();
                        }

                    }
                    catch (Exception ex)
                    {
                        ShowMessage(ex.Message);
                    }
                });
            }

        }

Now, if you look closely you will see all we did here is get the “Status” object from our ApplicationData.Current.LocalSettings and posted it on the TextBlock named Status. 🙂

Now, all we have left to do is do a little change in UI and add an extra button to set up the Geofence background task. Now it looks like the following:

GeoFencing - 8

I created the method stub for the new buttons click event too and it looks like the following:

        private async void CreateBackgroundServiceButton_Click(object sender, RoutedEventArgs e)
        {
            if (IsTaskRegistered("My Home Geofence"))
            {
                Unregister("My Home Geofence");
            }
            await RegisterBackgroundTask();
        }

Testing the App on the Emulator:

You can definitely test the app on the emulator. Like always click the debug button with a emulator selected as the device and when it opens go to additional tools button and open up the location tab. Select a close location to your geofence, I did select a close one to my room and the status changed itself to “Entered”. It was that easy! You can even try the foreground example in the same way!

GeoFencing - 7

The source code is here.

Stay frosty! Hope this would help.

Advertisements

বাংলায় উইন্ডোজ ফোন – DelegateCommand, The Reusable ICommand

অনেকদিন পর ফেরত আসলাম। আজকের টিউটোরিয়াল ICommand এর একটি সহজ ও Reusable Implementation যার নাম DelegateCommand, তার উপরে। DelegateCommand implement হয় ICommand interface দিয়েই এবং এটি ICommand এর ব্যবহারকে অনেকটাই সহজ করে দেয়। আশা করি সবার ভালো লাগবে।

পুনশ্চ: যদি আপনি Introduction to ICommand দেখে না থাকেন তাহলে অনুগ্রহ করে দেখে আসুন।

 

প্রজেক্ট সোর্স পাওয়া যাবে এই লিংকে – http://sdrv.ms/1dYX3pT

বাংলায় উইন্ডোজ ফোন – Introduction to ICommand

ফিরে আসলাম আবার। আজকের টিউটোরিয়াল ICommand এর উপরে। নিঃসন্দেহে  অত্যন্ত গুরুত্বপূর্ন একটি interface যেটা MVVM approach এ বড় ভূমিকা পালন করে। আশা করি সবার ভালো লাগবে। 🙂

স্যাম্পল প্রজেক্ট ডাউনলোড করে নিন নিচের লিঙ্ক থেকে :
http://sdrv.ms/1eouqSL

Data Binding – The last words

Well, as the title says this would be my last points on Data Binding. That doesn’t actually mean this is all there is in data binding. Kindly consider I only could share two or three lines from the preface of the book named “Data Binding”. But as we need to move forward I’m only sharing what’s essential to know.

So, back with the same example we had in our last post. If we remember things correctly we left the work at this stage:

wp_ss_20130929_0001

If we remember correctly we used the button Update Data to update the data from C# code behind. What if we want to write something in the textboxes and want to update the data by clicking the button Update Data. Only this time the new Data would be what I write in the textboxes.

So, lets see what we did before first approach that might come to your head is to write something like this:

 private void Button_Click(object sender, RoutedEventArgs e)
        {
            _personModel.Name =Name.Text;
            _personModel.Age = Age.Text;
            _personModel.Height = Height.Text;
        }

Well, I don’t blame you. It’s fair to do so. But if we don’t want the button, we just want to type and it will update automatically? Well, I know, who wants that ? :\

But what if it’s a data field and we have next button to go to another field like we do have in installation wizards, we don’t need a update button in that case. So, lets rename the Update button to Read Data so we can check that the data is updated truly.  So, lets change the button name and change the “Button_Click” event as following:

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Name.Text = _personModel.Name;
            Age.Text = _personModel.Age;
            Height.Text = _personModel.Height;
        }

So, now it would read the data instead of writing it. Then who is going to write it! :\
Well, lets change the data binding mode to TwoWay and we’re done for the updating!


<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
   <TextBox Height="70" HorizontalAlignment="Left" Margin="0,130,0,0" Name="Name" Text="{Binding Name, Mode=TwoWay}" VerticalAlignment="Top" Width="450" />
   <TextBox Height="72" HorizontalAlignment="Left" Margin="0,206,0,0" Name="Age" Text="{Binding Age, Mode=TwoWay}" VerticalAlignment="Top" Width="450" />
   <TextBox Height="72" HorizontalAlignment="Left" Margin="0,284,0,0" Name="Height" Text="{Binding Height, Mode=TwoWay}" VerticalAlignment="Top" Width="450" />
   <Button Content="Read Data" Click="Button_Click" Margin="0,361,0,159" ></Button>
</Grid>

You see what I did here is, I changed the Text Property of the Name TextBox control to Text=”{Binding Name, Mode=TwoWay}” and I changed all the TextBoxes accordingly allowing it to update the underlying data automatically when it’s changed. 🙂 No need for an update button.

DON’T USE IT IF YOU DON’T WANT TO CHANGE THE UNDERLYING DATA WITHOUT ANY CONFIRMATION.

So, you see the amazing thing here is all I changed is the binding mode. If I didn’t have to read this using the button we wouldn’t have needed any code practically.

Now Let’s get to see Element Binding a bit

Well, to demonstrate element binding what are we going to do is, we’re gonna put a slider control in our ContentPanel. Whenever we change the value of the slider we want to see that in a TextBlock. So we will get rid of all the textboxes and we will  insert a slider in our Windows Phone project.

Slider and Textblock

So, you see, we added a TextBlock and a slider below and removed the button and textboxes that were here before.

So, our ContentPanel looks like this now.

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <TextBlock Height="70"
                     HorizontalAlignment="Left"
                     Margin="10,130,0,0"
                     Name="ValueBox"
                     Text="TextBlock"
                     FontSize="36"
                     VerticalAlignment="Top"
                     TextAlignment="Center"
                     Width="436" />
            <Slider x:Name="HSlider" Orientation="Horizontal"
                    HorizontalAlignment="Left"
                    Height="172"
                    Margin="10,200,0,0"
                    VerticalAlignment="Top"
                    Width="436"
                    LargeChange="10"
                    SmallChange="1"
                    Minimum="0"
                    Maximum="100"
                    Value="50"

                    />
        </Grid>

Lets look at the xaml for a minute. You will see the slider named HSlider has a horizontal orientation and Minimum and Maximum value set from 0 to 100. What we want is we want to see the slider value on the textblock above, it should change as we change the slider. What’s the first approach comes to your mind. We can set a ValuChanged event in the slider and show the value in the textblock like this.

Adding a ValueChanged event in the XAML:

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <TextBlock Height="70"
                     HorizontalAlignment="Left"
                     Margin="10,130,0,0"
                     Name="ValueBox"
                     Text="TextBlock"
                     FontSize="36"
                     VerticalAlignment="Top"
                     TextAlignment="Center"
                     Width="436" />
            <Slider x:Name="HSlider" Orientation="Horizontal"
                    HorizontalAlignment="Left"
                    Height="172"
                    Margin="10,200,0,0"
                    VerticalAlignment="Top"
                    Width="436"
                    LargeChange="10"
                    SmallChange="1"
                    Minimum="0"
                    Maximum="100"
                    Value="50"
                    ValueChanged="HSlider_ValueChanged_1"
                    />
        </Grid>

and write the event handler behind in MainPage.xaml.cs like this:

private void HSlider_ValueChanged_1(object sender, RoutedPropertyChangedEventArgs e)
        {
            if(HSlider!=null)
                this.ValueBox.Text = HSlider.Value.ToString();
        }

And if you build this and run it on the emulator or device, whenever you change the slider you will see it’s value in the textblock. But is that we wanted here? NOOOO!!

Let’s make things a bit simple. If we can bind the slider to textblock item we can instantly show the slider value on the textblock. No code needed whatsoever! And why we bind the slider to the textblock. Because here the textblock shows the data so the slider works here as the model and the textblock as view! So, the model is binded to the view!

Let’s chill and see the easiest trick here. Now our ContentPanel looks like this and we have got rid of the event handler named HSlider_ValueChanged_1 from MainPage.xaml.cs

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <TextBlock Height="70"
                     HorizontalAlignment="Left"
                     Margin="10,130,0,0"
                     Name="ValueBox"
                     Text="{Binding Value, ElementName=HSlider}"
                     FontSize="36"
                     VerticalAlignment="Top"
                     TextAlignment="Center"
                     Width="436" />
            <Slider x:Name="HSlider" Orientation="Horizontal"
                    HorizontalAlignment="Left"
                    Height="172"
                    Margin="10,200,0,0"
                    VerticalAlignment="Top"
                    Width="436"
                    LargeChange="10"
                    SmallChange="1"
                    Minimum="0"
                    Maximum="100"
                    Value="50"

                    />
        </Grid>

See, the change we made here is that we changed the text property of the textblock into Text=”{Binding Value, ElementName=HSlider}” . Here, we binded the Value property of the Element HSlider.

😀 See? It’s really easy and see how much clean it looks now, all our job is done by only one line. That’s the magic of data binding.
wp_ss_20131004_0002

So, this is it for now, Next we’re gonna talk a little about DataConverters. Till then ciao!

I Notify When Property Changes – Data Binding Reloaded

On my last post, what I said was pretty basic stuffs on data binding. Now I need to Nerd Up a bit. I mean today we’re gonna take a bit deeper dive into data bindings.  So, if you in case missed the last one on data binding, kindly read my last post on data binding.

So, as this is only a continuation, lets not reinvent the wheel. We’re gonna use the same PersonModel class we used last day because that’s really simple.

Before we get started, let’s get to know someone and his name is INotifyPropertyChanged. Before you get scared, lemme tell you something. This guy holds a very important key of MVVM pattern and practically he does a huge deal of heavy work. Now you might ask what the hell does he do that makes him so important? :S
Now if you believe you dont want to waste your time listening to me saying baby stuff, you can go here and get it by yourself, no baby stuff, rock solid geek material.

Now for the ones who prefer it from me, let me clarify stuff for you in the easiest way possible. The easiest way would be he’s a notifier, practically a mailman who rings your doorbell every time you get a mail, or your fire alarm, who sees a little fire and fies you. If you carefully see, all of these characters do one and one thing in common. They notify you when something important (a very property around you) changes. So, if you are an object of a certain class and you want to know when someone changes one of your property, who you should call? Yes, you should call INotifyPropertyChanged. Clear?

Now, wait wait? how? Call? Is he a method? Look at the name, the name starts with an capital “I”, that means he is an interface, you have to implement him on the class you want to.   So, lets see! Shall we? We’re using our PersonModel class from previous tutorial.

class PersonModel: INotifyPropertyChanged
    {

        private string _name;
        private string _age;
        private string _height;

        public string Name
        {
            get { return _name; }
            set
            {
                if (_name != value)
                {
                    _name = value;
                    NotifyPropertyChanged("Name");
                }
            }
        }

        public string Age
        {
            get { return _age; }
            set
            {
                if (_age != value)
                {
                    _age = value;
                    NotifyPropertyChanged("Age");
                }
            }
        }
        public string Height
        {
            get { return _height; }
            set
            {
                if (_height != value)
                {
                    _height = value;
                    NotifyPropertyChanged("Height");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

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

Looks like a lot of change has taken place ha? Well, truth to be told, yes , it kinda did. DONT GET SCARED. Lets see what we did here. Actually if you see closely we didn’t do much, we implemented the INotifyPropertyChanged and included a event named public event PropertyChangedEventHandler PropertyChanged; And you have to write this event every time you implement INotifyPropertyChanged. You might say what if I forget? Fear not! When you have written INotifyPropertyChanged right beside your class name, press ctrl +  . (dot) and you’ll see Visual Studio asking you to implement all its needed to implement! Easy ha?

Capture

So, you see, you practically dont have to remember this one. But what’s an event? :S An event is a certain situation when you want to invoke or do something. Like the change in the property. But you dont know what to do now, you want to decide when it happens. So what do you do? You write an event and when the certain situation comes you write it then.

So, with that out of the way, why did we write a private object of every property we wrote before? Because, we want to see which property changes. So, there’s a private object like _name for the public property “Name”. Now, if you see closely, the public property have get and set methods. In the get method we are returning the private object and in the set method we are checking whether the new value is same as the previous or not, if it is we set it and raise the event, otherwise we do nothing!

W-wait! raise an event? Well, we did write a method named NotifyPropertyChanged. Why? All it does that it checks whether a user has assigned anything to the event we declared before and if its not null, it fires or invokes it. If its null, it does nothing. Simply put if we want to watch any property, all we have to do is assign something to the event PropertyChanged. The NotifyPropertyChanged takes the name of the property and detects who has raised the event. Neat!

Okay, we need action, right? We need to change some property when the application is running, other wise we wont understand. But before we do that, let me ask you something again. Why are we even doing this? Because when the data inside an object changes , I mean the property changes, the view needs to know that it has changed and if it doesn’t know how it would update itself? We can’t bind them every time it changes. Can we? thats where INotifyPropertyChange comes real handy. Because it notifies the view that the data has changed and you sould update yourself too! 😉

Now lets add a button to the view just so we can update the data behind when we want.

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <TextBox Height="70" HorizontalAlignment="Left" Margin="0,130,0,0" Name="Name" Text="{Binding Name}" VerticalAlignment="Top" Width="450" />
            <TextBox Height="72" HorizontalAlignment="Left" Margin="0,206,0,0" Name="Age" Text="{Binding Age}" VerticalAlignment="Top" Width="450" />
            <TextBox Height="72" HorizontalAlignment="Left" Margin="0,284,0,0" Name="Height" Text="{Binding Height}" VerticalAlignment="Top" Width="450" />
            <Button Content="Update Data" Click="Button_Click" Margin="0,361,0,159" ></Button>
        </Grid>

The UI looks like this right now.
UI Changed after update

Now, we added a click event on the button (we will not do this much in MVVM, will tell you later why). Let’s change that so we can update the data of the PersonModel object.

 private void Button_Click(object sender, RoutedEventArgs e)
        {
            _personModel.Name = "Rishad";
            _personModel.Age = "24";
            _personModel.Height = "5.10";
        }

So, lets see whether it works or not, if I click Update Data, will the data in the textblocks change?

wp_ss_20130929_0001

Amazing! It does change! So, you see, that’s where INotifyPropertyChange comes handy. Hey! we didn’t use the event here by ourselves. Well, when it comes to the changes of views you don’t have to worry about that. When you want some changes based on a property you can call that event.

So, until next time, ciao. Next we’ll dig a bit more on binding modes and element binding. I might go for a video next time. I feel I can deliver better there.

Data binding – loaded

Back to code talks, yay! The last two posts were all about my daily adventures and experience (boring! 😡 ). FINALLY, we’re back to talk about code again. Okay, lemme see what I did wrong on the last post. As it seems because of MVVM’s steep learning curve a lot of people complained me they are not getting stuff properly in their head. So, let’s make it going. Shall we? Let’s break down stuffs a bit.

Let’s get into Data Binding a bit more. What’s data binding. If we remember our very own View-Model-ViewModel then data binding is what shows a Model’s properties on view. What am I meaning actually? Lets think of a data source that provides a list of persons to an app’s view. So, the model would contain a person’s basic properties, like name, age, height etc. A very important point to ponder here is model is not always the data source itself, it is the template of data in most of the times. So, its properties gets shown in the view i.e. in this case a person’s name, age, height would be shown. And thats in the simplest sense binding. It allows the view to form a bond with the model. 🙂 Trust me, that’s the simplest way I can describe data binding.

So, for all the people who are reading this, let me utter the words of  Jesse Liberty,

  • Data binding is not hard to understand
  • Neither hard to implement

SO, DONT RUN AWAY MAN! YOU ARE BETTER THAN THIS!

So, lets get into it. As this is one of the posts of my current series of MVVM I would definitely keep it on track of it. Lets start with a very basic view.

 <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="Data Bidning Loaded" Style="{StaticResource PhoneTextNormalStyle}" />
            <TextBlock x:Name="PageTitle" Text="DataBinding" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <TextBox Height="70" HorizontalAlignment="Left" Margin="0,130,0,0" Name="Name" Text="Name" VerticalAlignment="Top" Width="450" />
            <TextBox Height="72" HorizontalAlignment="Left" Margin="0,206,0,0" Name="Age" Text="Age" VerticalAlignment="Top" Width="450" />
            <TextBox Height="72" HorizontalAlignment="Left" Margin="0,284,0,0" Name="Height" Text="Height" VerticalAlignment="Top" Width="450" />
        </Grid>
    </Grid>

Before we get into what we wrote let’s have a peel how it looks

DataBindingSimple1

Pretty basic ha? We need basic for this stage. So, if you look into the view you will see we practically did nothing. We imported three textbox controls and named them Name, Age and Height and filled them up with the same text. Even simple might get blushed seeing this. Cause this is simpler than the word simple. 😛

View is done, next we need a model. It’s gonna be a simple one too. Lets look our simplest Person model.

namespace DataBindingSimple
{
    class PersonModel
    {
        public string Name { get; set; }
        public string Age { get; set; }
        public string Height { get; set; }
    }
}

For the sake of the simplicity we’re gonna use the .cs file attached with the view i.e. the MainPage.xaml.cs here. We’re not gonna create  a seperate viewmodel for now as our purpose is to understand data binding properly first.

Lets see that first

namespace DataBindingSimple
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor

        PersonModel _personModel;

        public MainPage()
        {
            InitializeComponent();
            Loaded += MainPage_Loaded;

        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            _personModel = new PersonModel()
            {
                Name="Prateek",
                Age="23",
                Height="5.5"
            };

            SetDataContext();

        }

        private void SetDataContext()
        {
            ContentPanel.DataContext = _personModel;
        }

    }
}

Well, if we look into what we have just wrote, we’ll see there’s nothing new here. We added a PersonModel object as the DataContext of ContentPanel in the MainPage Loaded event. Wait, wait, wait, DataContext? What on god’s name is that?

To understand the concept of DataContext is to understand where the data comes from to the view. Obviously the data source and what it looks like or what is the template of the data. Of course its our model. Applying  a DataContext to something is to explicitly declare that the data that would be shown in the control comes from that DataContext. If you understand what Im saying then in the simplest sense DataContext is the source of the data. It can be a list, database object, a simple object like we used here. As long as it has data in the template we want , I mean in the model we described, we don’t have to worry about the view. 🙂
So, what we did here, we created a simple PersonModel object and declared it as DataContext of ContentPanel. Why? Because ContentPanel holds the three textboxes we want to show our data. So, the data should go there and as the ContentPanel is the container of those three textboxes it’s awarded the DataContext. Seems a bit clear now?

Is it supposed to work now? Shall we see my name, age and height in the three textboxes in the view now? The answer is obviously NO! We won’t. Why?
BECAUSE WE DIDN’T BIND THE DATA, DUH!

So, lets bind the data, shall we? Lets see how we bind the three properties of PersonModel in the three textboxes in the view. As we will only change the ContentPanel, lets see it below

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <TextBox Height="70" HorizontalAlignment="Left" Margin="0,130,0,0" Name="Name" Text="{Binding Name}" VerticalAlignment="Top" Width="450" />
            <TextBox Height="72" HorizontalAlignment="Left" Margin="0,206,0,0" Name="Age" Text="{Binding Age}" VerticalAlignment="Top" Width="450" />
            <TextBox Height="72" HorizontalAlignment="Left" Margin="0,284,0,0" Name="Height" Text="{Binding Height}" VerticalAlignment="Top" Width="450" />
        </Grid>

The only thing that has changed is the text property of all the three textboxes. As we wanted to show the name property of the model in the first textbox we wrote:

<TextBox Height="70" HorizontalAlignment="Left" Margin="0,130,0,0" Name="Name" Text="{Binding Name}" VerticalAlignment="Top" Width="450" />

Look into the snippet Text={Binding Name}. Here Binding Name means we are binding the name property of the DataContext to the textbox. And what was the DataContext? Yes! The PersonModel object we assigned as DataContext a while ago.

Let’s see whether it works or not.

DataBindingSimple2

Yay! it does! So, you see Data Binding is practically very very easy. All you need to know is where is to bind something and what to bind. 🙂

I really wanted to talk a bit more but as I see long tutorials kind of takes people’s interest away from it now – a – days. So, thats it for today.

Next, we’re gonna talk about

  • Data Binding with INotifyPropertyChanged
  • Data Binding Modes
  • Element Binding
  • Data Converters

Don’t worry, I wont write these in a single one of course, learned my lesson from the last one. I would try to break these up into short ones.

So, until the next one, ciao!