Notifying the User Interface

Suppose that you wanted to extend the application to show the user an alert whenever somebody mentions her on Twitter. The logic to check with Twitter for mentions would ideally remain in the shared layer so that it can be reused across all platforms. This means that the check needs to be platform-independent, but each platform still needs to be able to know when it occurs so that it can notify the user. This is a great example of a time when the observer pattern discussed in Chapter 3 can come in handy. TwitterClient can expose an event that it publishes when a mention is detected, and each application can subscribe to the event and alert the user.

Shared Layer

First, add a new class to the Chapter4 folder named MentionEventArgs, which will represent the data sent back to the application when the event is fired. It should include a Tweet object (the same type created in the first section) containing information about the mention (see Example 4-13).

Example 4-13. MentionEventArgs.cs

using System;

namespace SharedLibrary.Chapter4
{
    public class MentionEventArgs : EventArgs
    {
        public Tweet Tweet { get; private set; }

        public MentionEventArgs(Tweet tweet)
        {
            Tweet = tweet;
        }
    }
}

Now open up TwitterClient.cs and modify it to look like Example 4-14. The example only includes new code being added to the class, so append this to what is already in that class.

Example 4-14. TwitterClient.cs (updates only)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Xml.Linq;

namespace SharedLibrary.Chapter4
{
    public class TwitterClient
    {
        public event EventHandler<MentionEventArgs> MentionReceived; 1

        public TwitterClient()
        {
            new Timer(delegate 2
            {
                var mention = new Tweet 3
                {
                    Id = 42,
                    CreatedAt = DateTime.Now,
                    Text = "This is a fake mention"
                };

                if (MentionReceived != null) 4
                {
                    MentionReceived(this, new MentionEventArgs(mention));
                }
            }, null, 15 * 1000, Timeout.Infinite); 5
        }

        // ...code from last section...
    }
}
1

Define the MentionReceived event, supplying MentionEventArgs as its argument type.

2

In the constructor, start a timer to pretend a mention is received.

3

Create a fake mention, assigning values for its properties.

4

If there are any subscribers to the event, publish the event to them.

5

Set the timer to fire once after 15 seconds.

To keep things simple, this example uses a Timer to fake the event of receiving a mention instead of getting bogged down in Twitter specifics. Fifteen seconds after the instance of TwitterClient is created, the timer will elapse and any subscribers to the event will be notified that a mention was received. Each application is then free to notify the user in any way it wants, allowing for fully native behavior. Add links to both of these files in all three platform-shared library projects.

iOS

Open up TwitterViewController.cs and attach a handler to the client’s MentionReceived event in the ViewDidLoad() method. When the event is received, show a new UIAlertView containing the tweet’s text (see Example 4-15). Remember that the callback will happen on a background thread, so be sure to show the alert back on the UI thread. When you run the application and the timer elapses, it should look like Figure 4-5.

Example 4-15. TwitterViewController.cs (updates only)

using MonoTouch.UIKit;
using SharedLibrary.Chapter4;

namespace Chapter4.MonoTouchApp
{
    public class TwitterViewController : UITableViewController
    {
        public override void ViewDidLoad()
        {
            // ...code from last section...

            _client.MentionReceived += (object sender, MentionEventArgs args) =>
            {
                InvokeOnMainThread(() =>
                    new UIAlertView("Mention Received", args.Tweet.Text,
                                    null, "Ok", null).Show());
            };
        }
    }
}
Mention received on iOS

Figure 4-5. Mention received on iOS

Android

Back in the Android application, modify TwitterActivity and attach a handler to the client’s MentionReceived event in OnCreate(). When the event is fired, show an alert dialog with the tweet’s text (see Example 4-16), making sure to do it on the UI thread. Running the application should result in something similar to Figure 4-6.

Example 4-16. TwitterActivity.cs (updates only)

using Android.App;
using Android.OS;
using Android.Widget;
using SharedLibrary.Chapter4;

namespace Chapter4.MonoAndroidApp
{
    [Activity (Label = "\\@OReillyMedia", MainLauncher = true)]
    public class TwitterActivity : Activity
    {
        protected override void OnCreate(Bundle bundle)
        {
            // ...code from last section...

            client.MentionReceived += (object sender, MentionEventArgs args) =>
            {
                RunOnUiThread(() =>
                {
                    new AlertDialog.Builder(this)
                        .SetTitle ("Mention Received")
                        .SetMessage(args.Tweet.Text)
                        .SetPositiveButton("Ok", delegate { })
                        .Show();
                });
            };
        }
    }
}
Mention received on Android

Figure 4-6. Mention received on Android

Windows Phone

Lastly, in the Windows Phone application, open MainPage.xaml.cs. In the OnNavigatedTo() method, show a message box when a mention is received, again being careful to execute the code on the UI thread. Running the application in the emulator should look like Figure 4-7.

Example 4-17. MainPage.xaml.cs (updates only)

using System.Windows;
using System.Windows.Controls;
using Microsoft.Phone.Controls;
using SharedLibrary.Chapter4;

namespace Chapter4.WindowsPhoneApp
{
    public partial class MainPage : PhoneApplicationPage
    {
        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            // ...code from last section...

            client.MentionReceived += delegate(object sender, MentionEventArgs args)
            {
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    MessageBox.Show(args.Tweet.Text, "Mention Received",
                                    MessageBoxButton.OK);
                });
            };
        }
    }
}
Mention received on Windows Phone

Figure 4-7. Mention received on Windows Phone

Get Mobile Development with C# now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.