Windows Phone

How to implement a simple notification system in MVVM Windows 8.1 Universal apps

screenshot_07042015_152814

If your app performs actions, you most probably want to add also some confirmation if an action has finished. There are some ways to do this, like using local toast notifications or MessageDialogs. While I was working on Voices Admin v2, which is a universal app, I came along with a helper to simplify using local toast notifications. However, there came the point, where I got annoyed by the sound of these, and I looked into possible ways to replace them. My solution is a simple notification system, that uses the MVVM Light Messenger.

The first thing I did was adding a new property that broadcasts its PropertyChangedMessage to my ExtendedViewModelBase (which inherits from the MVVM Light ViewModelBase). This simplifies setting the notification text across multiple ViewModels as I don’t need to create a property in every ViewModel of my app:

public class ExtendedViewModelBase : ViewModelBase
    {
        public ExtendedViewModelBase()
        {
            
        }


        /// <summary>
        /// The <see cref="NotificationText" /> property's name.
        /// </summary>
        public const string NotificationTextPropertyName = "NotificationText";

        private string _notificationText = string.Empty;

        /// <summary>
        /// Sets and gets the NotificationText property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the MessengerInstance when it changes.
        /// </summary>
        public string NotificationText
        {
            get
            {
                return  _notificationText = string.Empty;
            }
            set
            {
                Set(() => NotificationText, ref _notificationText, value, true);
            }
        }
   }

The second step is to create the possibility to bind this into my view. I am using a custom PageBase class to simplify this. For those binding purposes it is common to add a DependencyProperty, and this is exactly what I did:

/// <summary>
        /// global property to bind the notification text against
        /// </summary>
        public static readonly DependencyProperty AppNotificationTextProperty = DependencyProperty.Register(
            "AppNotificationText", typeof (string), typeof (PageBase), new PropertyMetadata(string.Empty, (s, e) =>
            {
                var current = s as PageBase;

                if (current == null)
                {
                    return;
                }

                current.CheckifNotificationMessageIsNeeded(s);
            }));

        /// <summary>
        /// gets or sets the AppNotificationText
        /// </summary>
        public string AppNotificationText
        {
            get { return (string)GetValue(AppNotificationTextProperty); }
            set { SetValue(AppNotificationTextProperty, value); }}

You may have noticed that I hooked up into the PropertyChangedCallback of the DependecyProperty, which passes the execution to an separate method. Before we’ll have a look on that method, we need to add two private members to my PageBase: one for a StackPanel (mainly to set the Background color) and another one for Textblock. This is needed because this is the visible part of the notification. In the constructor of my PageBase class, I am filling them with live and connect them together:

            //instantiate and create StackPanel and TextBlock
            //you can put anything you want in the panel
            _panel = new StackPanel()
            {
                Background = new SolidColorBrush(Colors.Blue),
                Visibility = Visibility.Collapsed,
            };

            _textBlock = new TextBlock()
            {
                FontSize = 20,
                Margin = new Thickness(39, 10, 10, 10),
                TextAlignment = TextAlignment.Center
            };
            _panel.Children.Add(_textBlock);

The next thing we need to do is the FindChildren<T> helper method, which I took from the MSDN docs:

        /// <summary>
        /// Gets a list of DependencyObjects from the Visual Tree
        /// </summary>
        /// <typeparam name="T">the type of the desired object</typeparam>
        /// <param name="results">List of children</param>
        /// <param name="startNode">the DependencyObject to start the search with</param>
        public static void FindChildren<T>(List<T> results, DependencyObject startNode) where T : DependencyObject
        {
            int count = VisualTreeHelper.GetChildrenCount(startNode);
            for (int i = 0; i < count; i++)
            {
                var current = VisualTreeHelper.GetChild(startNode, i);
                if ((current.GetType()) == typeof(T) || (current.GetType().GetTypeInfo().IsSubclassOf(typeof(T))))
                {
                    T asType = (T)current;
                    results.Add(asType);
                }
                FindChildren<T>(results, current);
            }
         }

This helper enables us to find the top level grid, where we will add the StackPanel and control its visibilty and the TextBlock’s text. Which we are doing with the CheckifNotificationMessageIsNeeded() method:

        /// <summary>
        /// handles the visibility of the notification
        /// </summary>
        /// <param name="currentDependencyObject">the primary depenedency object to start with</param>
        private void CheckifNotificationMessageIsNeeded(DependencyObject currentDependencyObject)
        {
            if (currentDependencyObject == null) return;

            var children = new List<DependencyObject>();
            FindChildren(children, currentDependencyObject);
            if (children.Count == 0) return;

            var rootGrid = (Grid)children.FirstOrDefault(i => i.GetType() == typeof(Grid));

            if (rootGrid != null)

                if (!string.IsNullOrEmpty(AppNotificationText))
                {
                    if (!rootGrid.Children.Contains(_panel))
                    {
                        rootGrid.RowDefinitions.Add(new RowDefinition() {Height = new GridLength(_panel.ActualHeight, GridUnitType.Auto)});
                        _panel.SetValue(Grid.RowProperty, rootGrid.RowDefinitions.Count);

                        rootGrid.Children.Add(_panel);
                    }

                    _textBlock.Text = AppNotificationText;
                    _panel.Visibility = Visibility.Visible;
                }
                else if (string.IsNullOrEmpty(AppNotificationText))
                {
                    _textBlock.Text = string.Empty;
                    _panel.Visibility = Visibility.Collapsed;
                }
        }

Once we have the rootGrid on our Page, we are adding a new Row, set the StackPanel’s Grid.Row property to that and finally add the StackPanel to the Grid’s Children – but only if it does not exist already. No everytime the AppNotificationText property changes, the visibility of the StackPanel changes accordingly. Same counts for the TextBlock’s text. That’s all we need to do in the PageBase class.

The final bits of code we have to add are in the MainViewModel. I am using the MainViewModel as a kind of root ViewModel, which controls values and actions that are needed across multiple ViewModels. If you do not use it in the same way, you might need to write that code in all of your ViewModels where you want to use the notifications. The biggest advantage of my way is that the notification system (and other things) also works across pages.

The first thing we need is of course a property for the notification Text, which we will use to bind against on all pages where we want to use the notification system:

        /// <summary>
        /// The <see cref="GlobalNotificationText" /> property's name.
        /// </summary>
        public const string GlobalNotificationTextPropertyName = "GlobalNotificationText";

        private string _globalNotificationText = string.Empty;

        /// <summary>
        /// Sets and gets the GlobalNotificationText property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string GlobalNotificationText
        {
            get
            {
                return _globalNotificationText;
            }
            set
            {
                Set(() => GlobalNotificationText, ref _globalNotificationText, value);
            }
        }

Now we have this, we are hooking into the MVVM Messenger to catch the broadcasted NotificationText’s PropertyChangedMessage:

            Messenger.Default.Register<PropertyChangedMessage<string>>(this, message =>
            {
                if (message.PropertyName == ExtendedViewModelBase.NotificationTextPropertyName)
                {
                }
             });

If we would stop here, you would need to find a good point to set the NotificationText (and/or the GlobalNotificationText) property back to an empty string. This can be like the search a needle in the hay, believe me. That’s why I am giving every notification 5 seconds to be displayed, and the I am resetting the GlobalNotificationText  property in my MainViewModel automatically. To achieve this goal, I am using a simple DispatcherTimer with an Interval of 1 second:

            _notificationTimer = new DispatcherTimer() { Interval = new TimeSpan(0, 0, 1) };

DispatcherTimer has a Tick event, which fires every time a Tick happened. In our case, it fires every second. Hooking up into this event is essential, so add this line of code and let Visual Studio create the handler for you:

//in constructor:       
_notificationTimer.Tick += _notificationTimer_Tick;

//generated handler:
        private void _notificationTimer_Tick(object sender, object e)
        {
        }

Inside the Tick event handler, I am counting the ticks (using a private member in my MainViewModel). Once the timer passed 5 seconds, I am stopping the DispatcherTimer, reset the counter and finally set the GlobalNotificationText  property back to empty, which causes the notification to disappear:

            _notificationTimerElapsedSeconds++;

            if (_notificationTimerElapsedSeconds > 5)
            {
                _notificationTimer.Stop();
                _notificationTimerElapsedSeconds = 0;
                GlobalNotificationText = string.Empty;
            }

Of course we also need to start the DispatcherTimer. The perfect time for this is within the handler of the received PropertyChangedMessage we added earlier:

            //register for the global NotificationText PropertyChangedMessage from all VMs that derive from ExtendenViewModelBase
            Messenger.Default.Register<PropertyChangedMessage<string>>(this, message =>
            {
                if (message.PropertyName == ExtendedViewModelBase.NotificationTextPropertyName)
                {
                    if (!_notificationTimer.IsEnabled)
                    {
                        _notificationTimer.Start();
                    }
                    else
                    {
                        _notificationTimerElapsedSeconds = 0;
                    }

                    GlobalNotificationText = message.NewValue;
                }
            });

I am just checking if the DispatcherTimer is not yet enabled (= running) and start the timer in this case. If it is already running, I am just resetting my counter property to make sure that the notification is visible for 5 seconds again.

That’s it. Your MVVM (Light) app has now a simple and not so annoying notification system. It also provides the same experience across both platforms. There are sure ways to improve this here and there, that’s why I put up a sample to play around and contribute to on my Github account.

As always, I hope this post is helpful for some of you.

Happy coding!

Posted by msicc in Dev Stories, win8dev, wpdev, 0 comments

Helper class to easily display local toast notifications (Windows Universal app)

Often , we need to display a confirmation that some action in our app has been finished (like some data has been updated etc.). There are several ways of doing this, like displaying a MessageBox or MessageDialog. This however breaks the user interaction, and a lot of users will start complaining on that if your app keeps doing so. There needs to be a better way.

With the Coding4fun Toolkit floating around, you can mimic a toast notification – sadly only on Windows Phone (at least for the moment, but Dave told me he will work on implementing it for Windows, too). Also, Toastinet library is floating around, which is also able to mimic the toast notification behavior (although for Windows Universal app, the implementation is not that intuitive as for Windows  Phone). Both are fantastic libraries that I used in the past, but I wanted a solution that is implemented easily and works with my Universal app. So I did some searching in the Web and the MSDN docs, and found out that is pretty easy to use the system toast notifications on both platforms locally.

There are 8 possible ways to format toast notifications (as you can see here in the toast template catalog). This gives us pretty much options on how a notification can be styled. However, most options just work on Windows 8.1, while Windows Phone 8.1 apps will only show the notification in the way “app logo”  “bold text”  “normal text”. However, the notification system takes care of that, so you can specify some other type on Windows 8.1, while knowing that it gets converted on Windows Phone automatically. This allows us to write a helper class that implements all possible options without any headache.

the code parts for the notification

Let’s have a look at the code parts for the notification. First, you need to add two Namespaces to the class:

using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;

After that, we can start writing our code. Toast notifications are formatted using Xml. Because of this, we need to get a reference to the underlying Xml template for the system toast notification:

ToastTemplateType xmlForToast= ToastTemplateType.ToastImageAndText01; 
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(xmlForToast);

System toast notifications can hold Text (and an Image on Windows 8.1). So we need to declare the elements of the toast notification. We are using the Xml methods of the DOM namespace to get the text elements of the chosen template first:

XmlNodeList toastTextElements = xmlForToast.GetElementsByTagName("text");
toastTextElements[0].AppendChild(xmlForToast.CreateTextNode("text1"));
//additional texts, depending on the template:
//toastTextElements[1].AppendChild(xmlForToast.CreateTextNode("text2"));
//toastTextElements[2].AppendChild(xmlForToast.CreateTextNode("text3"));

This is how the image element is implemented:

XmlNodeList toastImageElement = xmlForToast.GetElementsByTagName("image");
//setting the image source uri:
if (toastImageElement != null) ((XmlElement) toastImageElement[0]).SetAttribute("src", imageSourceUri);
//setting optional alternative text for the image
if (toastImageElement != null)  ((XmlElement) toastImageElement[0]).SetAttribute("alt", imageSourceAlternativeText);

You can attach local or remote images to the toast notification, but remember this works only on Windows, not on Windows Phone.

The next part we are able to set is the duration. The duration options are long (25 seconds) and short (7 seconds). The default is short, which should be ok for most scenarios. Microsoft recommends to use long only when a personal interaction of the user is needed (like in a chat). This is how we do it:

IXmlNode toastRoot = xmlForToast.SelectSingleNode("/toast");
((XmlElement) toastRoot).SetAttribute("duration", "short");

What we are doing here is to get the root element of the template’s Xml and add a new element for the duration. Now that we finally have set all options, we are able to create our toast notification and display it to the user:

ToastNotification notification = new ToastNotification(xmlForToast);
ToastNotificationManager.CreateToastNotifier().Show(notification);

the helper class

That’s all we need to do for our local notification. You might see that always rewriting the same code just makes a lot of work. Because the code for the toast notification can be called nearly everywhere in an app (it does not matter if you are calling it from a ViewModel or code behind), I wrote this helper class that makes it even more easy to use the system toast notification locally:

    public class LocalToastHelper
    {
        public void ShowLocalToast(ToastTemplateType templateType, string toastText01, string toastText02 = null, string toastText03 = null, string imageSourceUri = null, string imageSourceAlternativeText = null, ToastDuration duration = ToastDuration.Short)
        {
            XmlDocument xmlForToast = ToastNotificationManager.GetTemplateContent(templateType);
            XmlNodeList toastTextElements = xmlForToast.GetElementsByTagName("text");

            switch (templateType)
            {
                case ToastTemplateType.ToastText01:
                case ToastTemplateType.ToastImageAndText01:
                    toastTextElements[0].AppendChild(xmlForToast.CreateTextNode(toastText01));
                    break;
                case ToastTemplateType.ToastText02:
                case ToastTemplateType.ToastImageAndText02:
                    toastTextElements[0].AppendChild(xmlForToast.CreateTextNode(toastText01));
                    if (toastText02 != null)
                    {
                        toastTextElements[1].AppendChild(xmlForToast.CreateTextNode(toastText02));
                    }
                    else
                    {
                        throw new ArgumentNullException("toastText02 must not be null when using this template type");
                        
                    }
                    ;
                    break;
                case ToastTemplateType.ToastText03:
                case ToastTemplateType.ToastImageAndText03:
                    toastTextElements[0].AppendChild(xmlForToast.CreateTextNode(toastText01));
                    if (toastText02 != null)
                    {
                        toastTextElements[1].AppendChild(xmlForToast.CreateTextNode(toastText02));
                    }
                    else
                    {
                        throw new ArgumentNullException("toastText02 must not be null when using this template type");
                    }
                    ;
                    break;
                case ToastTemplateType.ToastText04:
                case ToastTemplateType.ToastImageAndText04:
                    toastTextElements[0].AppendChild(xmlForToast.CreateTextNode(toastText01));
                    if (toastText02 != null)
                    {
                        toastTextElements[1].AppendChild(xmlForToast.CreateTextNode(toastText02));
                    }
                    else
                    {
                        throw new ArgumentNullException("toastText02 must not be null when using this template type");
                    }
                    ;
                    if (toastText03 != null)
                    {
                        toastTextElements[2].AppendChild(xmlForToast.CreateTextNode(toastText03));
                    }
                    else
                    {
                        throw new ArgumentNullException("toastText03 must not be null when using this template type");
                    }
                    ;
                    break;
            }

            switch (templateType)
            {
                case ToastTemplateType.ToastImageAndText01:
                case ToastTemplateType.ToastImageAndText02:
                case ToastTemplateType.ToastImageAndText03:
                case ToastTemplateType.ToastImageAndText04:
                    if (!string.IsNullOrEmpty(imageSourceUri))
                    {
                        XmlNodeList toastImageElement = xmlForToast.GetElementsByTagName("image");
                        if (toastImageElement != null)
                            ((XmlElement) toastImageElement[0]).SetAttribute("src", imageSourceUri);
                    }
                    else
                    {
                        throw new ArgumentNullException(
                            "imageSourceUri must not be null when using this template type");
                    }
                    if (!string.IsNullOrEmpty(imageSourceUri) && !string.IsNullOrEmpty(imageSourceAlternativeText))
                    {
                        XmlNodeList toastImageElement = xmlForToast.GetElementsByTagName("image");
                        if (toastImageElement != null)
                            ((XmlElement) toastImageElement[0]).SetAttribute("alt", imageSourceAlternativeText);
                    }
                    break;
                default:
                    break;
            }

            IXmlNode toastRoot = xmlForToast.SelectSingleNode("/toast");
            ((XmlElement) toastRoot).SetAttribute("duration", duration.ToString().ToLowerInvariant());

            ToastNotification notification = new ToastNotification(xmlForToast);
            ToastNotificationManager.CreateToastNotifier().Show(notification);
        }

        public enum ToastDuration
        {
            Short,
            Long
        }
    }

As you can see, you just need to provide the wanted parameters to the ShowLocalToast method, which will do the rest of the work for you.

One word to the second switch statement I am using. The image element needs to be set only when we are using the ToastImageAndTextXX templates. There are three ways to implement the integration: using an if with 4  “or” options, the switch statement I am using or a string comparison with String.Contains. The switch statement is the cleanest option for me, so I decided to go this way. Feel free to use any of the other ways in your implementation.

In my implementation, I added also some possible ArgumentNullExceptions to make it easy to find any usage errors.

For your convenience, I attached the source file. Just swap out the namespace with yours. Download

The usage of the class is pretty simple:

var _toastHelper = new LocalToastHelper();
_toastHelper.ShowLocalToast(ToastTemplateType.ToastText02, "This is text 1", "This is text 2");

audio options

The system toasts have another option that can be set: the toast audio. This way, you can customize the appearance of the toast a bit more. I did not implement it yet, because there are some more options and things to remind, and I haven’t checked them out all together. Once I did, I will add a second post to this one with the new information.

As always, I hope this is helpful for some of you.

Happy coding!

Posted by msicc in Dev Stories, win8dev, wpdev, 3 comments

Simple helper method to detect the last page of API data (C#)

When you are working with APIs from web services, you probably ran already into the same problem that I did recently: how to detect if we are on the last page of possible API results.

Some APIs (like WordPress) use tokens to be sent as parameter  with your request, and if the token is null or empty you know that you have reached the last page. However, not all APIs are working that way (for example UserVoice).

As I am rewriting Voices Admin to be a Universal app, I came up with a simple but effective helper method that allows me to easily detect if I am on the last page. Here is what I did:

	public static bool IsLastPage(int total, int countperpage, int current)
        {
            bool value = false;

            if (current < Convert.ToInt32(Math.Ceiling(Convert.ToDouble(total)/countperpage)))
            {
                value = false;
            }

            if (current == Convert.ToInt32(Math.Ceiling(Convert.ToDouble(total)/countperpage)))
                value = true;

            return value;
        }

As you can see, I need the number of total records that can be fetched (which is returned by the API) and the property for the number per page (which is one of the optional parameters of the API). On top, I need the current page number to calculate where I am (which is also an optional parameter of the API and returned by the API result).

Now I simply need to divide the total records by the result count per page to get how many pages are used. Using the Math.Ceiling() method, I always get the correct number of pages back. What does the Math.Ceiling() method do? It just jumps up to the next absolute number, also known as “rounding toward positive infinity”.

Example: if you have 51 total records and a per page count of 10, the division will return 5.1 (which means there is only one result on the 6th page). However, we need an absolute number. Rounding the result would return 5 pages, which is wrong in this case. The Math.Ceiling() method however returns the correct value of 6.

Setting the method up as a static Boolean makes it easy to change the CanExecute property of a button for example, which will be automatically disabled if we just have loaded the last page (page 6 in my case).

As always, I hope this is helpful for some of you.

Happy coding, everyone!

Posted by msicc in Dev Stories, win8dev, wpdev, 2 comments

Review of a geek’s 2014

We are close to the end of this year 2014, time for a little review.

At the beginning of the year, I was mostly busy with working on my UserVoice library that makes it easier for me and other developers to integrate UserVoice into Windows Phone apps. I also launched Voices Admin, the companion app for the library. I will start to rewrite this library in 2015 to make it a true Universal library for Windows, Windows Phone as well as Xamarin (and make it return objects instead of naked JSON strings).

I also had some troubles with my former hoster, which lead to a total domain chaos and finally ended in January, too. Thanks to Azure Websites, the transition should have been without problems.  At Telefónica, I was busy finishing the internal App “Friends & You” for Android and Windows Phone. I learned a lot using Xamarin for the Android version, and even more about corporate rules and requirements. In the beginning of December, I also finished the iOS variant of the app (using Xamarin.Forms) – which is sadly set to be not launched for the moment (mostly because of my departing of Telefónica).

During the year, we also received the Windows Phone 8.1 Developer Preview. It removed the ability to cross post on social networks on Windows Phone. As this was one of my most used features, I decided to solve this problem for myself and started to write my own cross posting solution. As some of my followers recognized this, I continued my efforts to a more public and polished version, the result is UniShare for Windows Phone.

ae4dc8ca-2d86-4e36-bf9b-d7c2985a68b1

Since the first WP8.1 Developer Preview, we also have Cortana. Cortana is an awesome piece of software – if you are willing to use your phone with English and US region settings. I tried the UK version as well as the Italian and German version, but was only satisfied with the US one. I truly hope that the other countries will be on par in 2015.

I also updated my very first app ever (Fishing Knots +) to a Windows Phone 8 only version, leaving the old version for WP7 users. Also my NFC Toolkit received some love (and will receive even more in 2015). On top, I started to work on a Universal library for WordPress, which I will also continue to work on in 2015 to make it even better.

One of my saddest geek moments was when the screen of my Intel developer Ultrabook broke shorty before Christmas. As I need to be able working while on the go, I needed a replacement. I found it in the ASUS TP300L Transformer Flipbook, which is an awesome piece of an Ultrabook. On top, Santa (aka my wife) gifted me an HP Stream 7 tablet, that perfectly fits my needs for a tablet use (reading, surfing, playing some games). And so this part also turned well.

The most significant thing happened in September, when I read about a job as a C# Junior developer in Switzerland. I am truly happy about the fact I got this job (read more on it here), and already learned some new things in WPF. Currently, I am also working on my first WPF application, that is a practicing project for my new job I am going to start next year. Which leads me to the end of this short review.

2014 was a year with ups and downs like every year. I had some trouble in “first world” that we were able to solve as family (and friends), but made some good success in my geek and dev world. I am looking forward to 2015, where I am starting a new chapter in my dev story (with becoming a full time developer). But there are also some nice side projects, like maybe porting some apps to Android as well as the Internet of Things, which I am looking forward to dive in deeper. And of course, like any other MS fan, I am looking forward to the next evolutions of Windows 10!

What are you all looking for? How was your 2014? Feel free to comment below.

158340786

Happy New Year, everyone!

Posted by msicc in Dev Stories, User Stories, 1 comment

Goodbye Telefónica (Germany), Hello ShareCommService (Switzerland)

Yes, you read that right. Today was my last work day at Telefónica, where I worked since June 2007. During that time, I learned a lot about how good customer service should be, and even more about mobile networks and mobile devices (phones, tablets and more). During that time, I also started my dev story in my spare time – all because there was not a single fishing knots application available for Windows Phone (read more here).

This lead to get recognized also within Telefónica as a developer, and so I was asked to concept and develop the application Friends & You (nope, you can’t download it as it is an internal app).  I learned a lot about how corporate apps aren’t that easy to concept and build during that time, as well as as how restrictive corporate rules can be. After all, I had a few challenges to complete. Thanks to Friends & You, I was also able to dive into the world of Xamarin, where I learned a lot about the application structures of Android and iOS (which will be helpful for eventually porting some of my Windows Phone apps to those two).

I want to say thanks to my colleagues, you´re awesome! Keep up the great work you´re doing in Customer Service.

Back in September then, I opened up my Twitter app and the first tweet I read was this one:

image

I opened the attached document and read the job description. As an self-thought developer, I first was about to close it and put it aside as “read and done”.

Due to the head count freeze at Telefónica after acquiring e-Plus from KPN, there are no chances to become a real full time developer within Telefónica for the next time. But that is what I want to do. After reopening the document and reading it again, I decided to get in contact with Roman Mueller (who I knew from Twitter already).

We talked about the job itself and the circumstances behind the announcement. After a few talks and a visit in Switzerland, the decision was made. I am starting the next chapter of my developer story in January, moving to Switzerland, where I will add deeper SQL knowledge, WPF and a lot more to my development knowledge.

At this point, I want to thank ShareCommService and especially Roman for all the help I received already to make this all happen and get started.

It is going to be an exciting journey for me (and my family), and we are ready to go.

Happy coding everyone!

Posted by msicc in Dev Stories, 1 comment

How to use WordPress to display remote notifications in your Windows Phone app

Sometimes, we need to display information to our users on demand. The easiest way is to do this in our app via a remote notification service.

If you have a WordPress blog, my solution may also be helpful for you.

I am using a page that is not linked anywhere in my blog to display the message. To add a new page, go to your WordPress Dashboard and hover over “Pages” and click on “Add New”.

image

Fill in the title and your notification and publish the page. Before closing your browser, save/remember the id of the page, we will need it later.

image

The next step is to download my WordPress Universal library, which can be downloaded right here from my Github. You can add the project directly to your solution or build it and then reference the library you will find in the bin folder of the WordPress Universal project folder. If you want to learn more about the library, visit http://bit.ly/WordPressUniversal.

Now that we have everything in place, let’s add the code that does the magic for us:

        public async void ShowNotification()
        {
            //initialize the client and load the list of pages from your blog
            wpClient = new WordPressClient();
            var pages = await wpClient.GetPostList("msicc.net", WordPressUniversal.Models.PostType.page, WordPressUniversal.Models.PostStatus.publish, 20, 0);

            //select the notification page
            var notificationContentPage = from p in pages.posts_list where p.id == 4248 select p;

            //check if has content
            if (!String.IsNullOrEmpty(notificationContentPage.FirstOrDefault().content))
            {
                //convert parapgraphs into NewLines
                //you might have more HTML content in there which needs to be converted
                string content = notificationContentPage.FirstOrDefault().content.Replace("

", string.Empty).Replace("

", "\n\n"); //App.SettingsStore = ApplicationData.Current.LocalSettings //change this to your appropriate storage like IsolatedStorage etc. //this displays the message only once to our users, but keeps the door open for an easy update mechanism if (App.SettingsStore.LastNotificationContent != content) { MessageBoxResult result = MessageBox.Show(content, notificationContentPage.FirstOrDefault().title, MessageBoxButton.OK); switch (result) { //the button click saves the actual message case MessageBoxResult.OK: App.SettingsStore.LastNotificationContent = content; break; //BackButtonPress does this as well case MessageBoxResult.None: App.SettingsStore.LastNotificationContent = content; break; } } } }

What does this code do? First, it fetches all pages from our WordPress blog. Then, we are selecting the page we created via its id. If your WordPress blog does not show you the id in the url of the page, set a BreakPoint at the “var notificationContentPage = …” line. you will then easily be able to get the id:

image

Naturally, the returned content is HTML formatted. To remove the paragraph tags and but respect their function, we are using a simple String.Replace pattern. You may have more HTML tags in your message that needs to be removed or converted.

To generate an easy way to display the message only once but keep it open for updates, we are saving the converted message locally. In this case, I used the LocalSettings of my Windows Phone 8.1 app. I am using the MessageBoxResult to make the method saving the message either at the point of the OK click as well as on BackButtonPress.

This is how the above generated WordPress Page looks as a Notification:

wp_ss_20141127_0001

As my WordPress Universal library works cross platform for C# apps, you should be able to adapt this for your Windows 8.1 or  Xamarin apps as well.

As always, I hope this is helpful for some of you.

Happy coding!

Posted by msicc in Dev Stories, wpdev, 1 comment

How to generate a round image button for your Windows Phone 8.1 app (to use everywhere)

Recently, I experimented a bit because I wanted a round button that contains an image that can be used everywhere where I can add a standard button (and not just in the AppBar). I managed to get a simple style out of these experiments (sample at the end of this post).

First, you should check if you have already installed Syncfusion’s free Metro Studio (we will need it later). It is a powerful helper if you need icons, so if you do not have it, go straight ahead and download it here: http://www.syncfusion.com/downloads/metrostudio

Still here/back? Great! Ok, let’s start. In our project, generate a new button:

<Button Width="72" Height="72"></Button>

If you want your round button to have a smaller size, feel free to adjust the 72 pixels mine has to your preferred value.

The next step is to generate a new Style. Right click on the Button, and select ‘Edit Template’, followed by ‘Edit a Copy’.

Screenshot (407)

 

Set the name of your style in the next window, and save define it as an app-wide Style or on your page:

Screenshot (408)

This should open your App.xaml file and display the button as well as the newly generated style.

We are starting with our custom style modifications right at the top:

image

Set both Doubles to 0 and the Thickness to 0,0.

Next, scroll down to find the Border Element of the Button Template (closing ‘VisualStateManager.VisualStateGroups’ helps a lot).

Click on the Border element and add/adjust the ‘CornerRadius’ property. At a size of 72, the minimum value is 38 for the radius. This should be fine for most cases, but it may be higher/smaller if you are using another size. Don’t worry if your button looks like this at them moment:

image

We are going to fix it right now by setting the Height and Width properties of our Border element:

Height="{Binding Path=Height, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Width="{Binding Path=Width, RelativeSource={RelativeSource Mode=TemplatedParent}}"

This binds the Width and Height properties of our Button to the Style. Now we just need to define the Height and the Width of our Button to make it actually look really round. Setting both to 72 will result in a nice round button.

Like you can imagine, displaying text does not make a lot of sense in this case. Round Buttons should contain an image. You could add one through adding a background, but this will result in a strange looking button when it gets pressed. Also, it does not reflect changes like a color change. To solve this, we are going to add code that is able to draw a shape for us. This is achieved with the Path Class  in XAML. The Path class draws lines into a FrameworkElement like a Canvas or a Border.

To enable our Style to work with Path Data, we need to add some code before the ‘Template’ property Setter in our Style:

<Setter Property="ContentTemplate">
    <Setter.Value>
        <DataTemplate>
            <Path Stretch="Uniform"
                  RenderTransformOrigin="0.5,0.5"
                  Margin="2,6,2,2"
                  Fill="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=TemplatedParent}}"
                  Data="{Binding Path=Content, RelativeSource={RelativeSource Mode=TemplatedParent}}"></Path>
        </DataTemplate>
    </Setter.Value>
</Setter>

What does this code do? The ContentTemplate allows us to add rich content to our UIElement, the Button. To make it resuable, we are setting it up in our custom button style. The RenderTransforOrigin property value of 0.5,0.5 centers our Path drawn shape within the border. However, I found out that some shapes do not look good with that alone. That’s why I adjusted the Margin property together with it. This should fit most icon shapes, but you might adjust this for your own needs.

The most important aspects are the Fill property as well as the Data property. Binding the Fill Brush to the Foreground Brush property is necessary to reflect changes like theme changes as well as changes in the VisualState. Only this way it behaves like a native Button. Binding the Data property allows us to enter the Path string into the Content property of a button that uses our Style without any conversion. This makes it very simple to generate a button with our desired icon.

And this is where Syncfusion’s MetroStudio comes in handy. It allows you not only to generate icons as png, but also as shape in XAML. To get the relevant Data, open MetroStudio, search for your icon. Below the icon, there is an Edit Button. Tap it to open the icon settings page. On that settings page, you set up your button. Play around a little bit to get used to it (it’s pretty easy).

Once you have your desired icon on the screen, click on the </>XAML Button. Copy the highlighted part of the XAML code:

image

Back in Visual Studio, add this copied code to the Content property of our Button:

Content="F1M181.003,-1898.78L207.077,-1902.33 207.089,-1877.18 181.027,-1877.03 181.003,-1898.78z M207.065,-1874.28L207.085,-1849.1 181.023,-1852.69 181.022,-1874.45 207.065,-1874.28z M210.226,-1902.79L244.798,-1907.84 244.798,-1877.5 210.226,-1877.22 210.226,-1902.79z M244.807,-1874.04L244.798,-1843.84 210.226,-1848.72 210.177,-1874.1 244.807,-1874.04z" 
Height="72" 
Width="72"
Style="{StaticResource RoundButtonStyle}" 
VerticalAlignment="Center" 
HorizontalAlignment="Center"/>

Which will result in this nice looking round button with a Windows logo on it:

image

If you run the sample project, you can see that the Button behaves like a native Button with text. Download the sample project here.

I am pretty sure this can be improved. I will continue to play around with this, and if I have found enough optimizations, I will write another post about them. Until then, this should help you to get started with your own round button – and the best thing: you can use it like any standard button wherever you want in your Windows (Phone) 8.1 app!

Happy coding, everyone!

Posted by msicc in Dev Stories, win8dev, wpdev, 1 comment

Helper class to handle In-App-Products (IAP) licenses on Windows Phone (SL)

Like a lot of other apps, also UniShare got hit by an outage in the licensing system of the Windows Phone Store recently.

There was a workaround to get the licenses back from the store, but even with that, users have left negative votes (even after I posted the workaround and also wpcentral wrote about it a few days later).

The problem with those negative reviews: they tend to remain, even after responding to them (if possible) or having conversation with the users via mail. I totally understand users that are annoyed by such facts – I got hit by it as well with other apps I am using regularly. So I was thinking about a better solution as the recommended way by Microsoft, which says you should check it on every app start.

Rob Irving posted about his solution at the same day wpcentral wrote about it, which is one possible solution. His motive was the same as my solution – improving the user experience with the IAP’s.

However, I am preferring to check the licenses against the Store from time to time to make sure that the licenses are still correct.

Here is my solution (for durable IAP):

First, let’s we need to declare an object for the ListingInformation, which will hold the information that the store returns for our IAP:

ListingInformation IAPListing;

Then, we  need to create these two classes:

        public class IAP
        {
            public string Key { get; set; }

            public string Name { get; set; }

            public string Price { get; set; }

            public ProductType Type { get; set; }

            public string Description { get; set; }

            public string Image { get; set; }

            public bool IsLicenseActive { get; set; }
        }

        public class IAPToSave
        {
            public List<IAP> IAPListToSave { get; set; }

            public DateTime date { get; set; }
        }

The class IAP is the class/model that holds a single IAP item information. The second class is needed for saving the fetched IAP information (we’ll see later how I did it).

Now we have prepared these, we can finally go to the store and fetch the IAP list. I created an async Task that returns a List<IAP> for it:

        public async Task<List<IAP>> GetAllIAP()
        {
            var list = new List<IAP>();

            IAPListing = await CurrentApp.LoadListingInformationAsync();

            foreach (var product in IAPListing.ProductListings)
            {
                list.Add(new IAP()
                {
                    Key = product.Key,
                    Name = product.Value.Name,
                    Description = product.Value.Description,
                    Price = product.Value.FormattedPrice,
                    Type = product.Value.ProductType,
                    Image = product.Value.ImageUri.ToString(),
                    IsLicenseActive = isPackageUnlocked(product.Key)
                });
            }
            return list;
        }

To immediately check if our user has already purchased the item, we are getting a Boolean for it. While we are getting the data from the store, we are using this to fill our IAP class with the desired value (see IsLicenseActive property in the IAP item above).

        public bool isPackageUnlocked(string productKey)
        {
            var licenseInformation = CurrentApp.LicenseInformation;

            if (licenseInformation.ProductLicenses[productKey].IsActive)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

Now we have already all data that we need to display all IAP in our app. The usage is fairly simple:

var iapHelper = new IAPHelper();
var iapList = await iapHelper.GetAllIAP();

You can now bind the iapList to a ListBox (or your proper control/view). Next thing we are creating is our helper that performs the purchase action and returns a result string to display in a message to the user in our IAPHelper class:

        public async Task<string> unlockPackage(string productKey, string productName)
        {
            var licenseInformation = CurrentApp.LicenseInformation;

            string response = string.Empty;

            if (!licenseInformation.ProductLicenses[productKey].IsActive)
            {
                try
                {
                    //opening the store to display the purchase page
                    await CurrentApp.RequestProductPurchaseAsync(productKey);

                    //getting the result after returning into app
                    var isUnlocked = isPackageUnlocked(productKey);

                    if (isUnlocked == true)
                    {
                        response = string.Format("You succesfully unlocked {0}.", productName);  
                    }
                    else
                    {
                        response = string.Format("There was an error while trying to unlock {0}. Please try again.", productName);
                    }
                }
                catch (Exception)
                {
                    response = string.Format("There was an error while trying to unlock {0}. Please try again.", productName);
                }
            }
            else
            {
                response = string.Format( "You already unlocked {0}", productName);
            }

            return response;
        }

You may of course vary the messages that are displayed to the user to your favor.

The usage of this Task is also pretty straight forward:

var iapHelper = new IAPHelper();
string message = await iapHelper.unlockPackage(((IAPHelper.IAP)IAPListBox.SelectedItem).Key, ((IAPHelper.IAP)IAPListBox.SelectedItem).Name);

After that, we need to refresh the LicenseInformation by using GetAllIAP() again to refresh the iapList and of course our ListBox.

My goal was to save the LicenseInformation of my IAP for a limited time so the user is protected for future outages (or situations where no network connection is available). That’s why we need to add another Task to our IAPHelper class:

        public async Task<string> SerializedCurrentIAPList(List<IAP> iaplist, DateTime lastchecked)
        {
            string json = string.Empty;

            IAPToSave listToSave = new IAPToSave() { IAPListToSave = iaplist, date = lastchecked };

            if (iaplist.Count != 0)
            {
                json = await Task.Factory.StartNew(() => JsonConvert.SerializeObject(listToSave));
            }
            return json;
        }

As you can see, now is the point where we need the second class I mentioned in the beginning. It has one property for the List<IAP> and a DateTime property that we are saving. I am serializing the whole class to a JSON string. This way, we are able to save it as a string in our application’s storage.

The usage of this Task is as simple as the former ones:

var savedIAPList = await iapHelper.SerializedCurrentIAPList(iapList, DateTime.Now);

The last thing we need to create is an object that helps us indicating if a refresh of the list is needed or not. Like I said, I want to do this action time based, so here is my way to get this value:

        public bool isReloadNeeded(DateTime lastchecked, TimeSpan desiredtimespan)
        {
            bool reloadNeeded = false;

            var now = DateTime.Now;

            TimeSpan ts_lastchecked = now - lastchecked;

            if (ts_lastchecked > desiredtimespan)
            {
                reloadNeeded = true;
            }

            return reloadNeeded;
        }

This method just checks if the desired TimeSpan has passed already and returns the matching Boolean value. The usage of this is likewise pretty simple:

var savedlist = await Task.Factory.StartNew(() => JsonConvert.DeserializeObject<IAPHelper.IAPToSave>(App.SettingsStore.savedIAPList));

if (iapHelper.isReloadNeeded(savedlist.date, new TimeSpan(96, 0, 0)))
{
   //reload the list and perform your actions
}
else
{
   //use savedlist.IAPListToSave and perform your actions 
}

This way, we are able to make sure that all IAPs are available for a minimum of time and protect our users against store outages.

For your convenience, you can download the whole class right here. Just replace NAMESPACE with yours and you are good to go.

Note: I know that this approach does not follow the recommended way of Microsoft. It is up to us to deal with bad reviews if something on the store part is not working. This is my approach to avoid negative reviews because of store outages (at least for a limited time). However, like always, I hope this post is helpful for some of you.

Happy coding!

Posted by msicc in Dev Stories, wpdev, 0 comments

WordPressUniversal – a PCL library for WordPress based C# mobile apps

WP_CSharp_Lib

As I have already developed a news reader app for my blog, I got asked quite a few times if I want to share my code to help others creating their apps. As I need to redesign my blog reader to match the latest OS features of Windows and Windows Phone, I decided to create my WordPressUniversal library.

Automattic, the company behind WordPress, integrated a powerful JSON API into their JetPack plugin. My library is based on this API. Please make sure the JSON API is active on the blog you are developing your app for.

The library currently provides the following features:

  • getting a list posts or pages
  • getting a list of all categories
  • getting a list of comments for the site and single posts
  • supports Windows Phone 8 & 8.1 Silverlight, Windows Phone 8.1 RT, Windows 8, Xamarin.iOS and Xamarin.Android

The library deserializes all data into C# objects you can immediately work with.

It is still a work in progress, but as it provides already a bunch of options to get you started, I am making this public already.

I am constantly working on the library, so be sure to follow the project along.

Note: JetPack’s JSON API does not support guest commenting at the moment. I already reached out to Automattic to (hopefully) find a solution for this. If you cannot wait, Disqus has a portable solution for Windows Phone apps.

Please make sure to see the documentation on my GitHub page.

If you have any questions, idea, wishes for me, just post a comment here or ping on Twitter.

Happy coding everyone!

Posted by msicc in Dev Stories, win8dev, wpdev, Xamarin, 17 comments

Book review: Learning Windows Azure Mobile Services for Windows 8 and Windows Phone 8 (Geoff Webber-Cross)

During the last months, I used the few times of my spare time when I wasn’t in the mood for programming to read Geoff’s latest book for diving deeper into Azure Mobile Services. Geoff is well known in the community for his Azure experience, and I absolutely recommend to follow him! I am really glad he asked me to review his book and need to apologize that it took so long to get this review up.

The book itself is very well structured with a true working XAML based game that utilizes both Windows 8 and Windows Phone 8 and connects them to one single Mobile Service.

Even if you are completely new to Azure, you will quickly get things done as the whole book is full of step-by-step instructions. Let’s have a quick look on what you will learn while reading this book:

  1. Prepare your Azure account and set up your first Mobile Service
  2. Bring your Mobile Service to life and connect Visual Studio
  3. Securing user’s data
  4. Create your own API endpoints
  5. use Git via the console for remote development
  6. manage Push Notifications for both Windows and Windows Phone apps
  7. use the advantages of the Notification hub
  8. Best practices for app development – some very useful general guilty tips!

I already use a Mobile Service with my Windows Phone App TweeCoMinder. I have already started a Windows 8 version of that app, which basically only needs to be connected to my existing Azure Mobile Service to finish it.

Screenshot (359)

While reading Geoff’s book, I learned how I effectively can achieve this and also improve my code for handling the push notifications on both systems. The book is an absolutely worthy investment if you look into Azure and Mobile Services and has a lot of sample code that can be reused in your own application.

As this is my first book review ever, feel free to leave your feedback in the comments.

You can buy the book right here.

Happy coding, everyone!

Posted by msicc in Azure, Dev Stories, win8dev, wpdev, 0 comments