notification

How to create a RSS feed web tile with notifications for your Microsoft Band

This is a blog post not only for developers, but also for users (I will try to get not to technical in this post).  I managed to buy a Microsoft Band 2 for me here in Europe two weeks ago, and of course I am still exploring all the functionality that it has. A web tile is one of the cool features it supports – with a web tile, you can add your digital footprint to the Microsoft Band. And the best thing: you don’t need to be a developer to create your own! Microsoft provides a web kit that creates the tile for you!

Let’s have a look at the (not so hard to understand) steps it takes to create your own web tile:

The First step is to choose the layout, which also describes the type of the web tile:

Screenshot (82)

After selecting the feed tile template, you need to find the RSS url of your blog or other source site. Paste it in the desired field and hit the next button.

Screenshot (83)

Microsoft’s site now reads your RSS feed and provides you the single fields that come with your feed. When you hover with your mouse over the fields, they’’ll get highlighted. Just drag and drop them into the Microsoft Band preview image on the left hand side.

Screenshot (77)

Now that you have selected the data that should appear on the Microsoft Band, let’s set up the notification for the web tile. This is where it gets a bit tricky, but most feeds should be covered by the following image:

Screenshot (79)

No worries, I am telling you what is done here. The first and second line is the title and the description of the notification. You can put in there whatever you like. The most important part is the condition expression below the Band preview. Sadly the documentation provided by Microsoft is not as detailed for feed tiles as it should. Luckily, I found a post at StackOverflow that explains a little bit more. If you’re a developer, feel free to read the full text. If you are a user: just drag and drop the guid field of the “item” section into the first and also into the last field and set the condition to not equal. If your feed gets a new item, you will get a notification on your band with that. This condition looks if there is any new guid in the items list of your feed – and if so, sends out the notification and shows the badge.

In the last step, we just need to provide some details about the web tile we have created. If you want to have all features, you must provide both images:

Screenshot (80)

If you want to have control on how the image looks like, you should provide the images already flattened into a transparent and white image already. The result could look very creepy otherwise. After that, you have finally created your web tile – congratulations!

Screenshot (81)

Once you have downloaded the web tile, you just need to mail it to yourself or anyone who wants to use it. The other option is to put it on your OneDrive and just share a link to your web tile. To share the link you need to add the link of your online storage to this: “mshealth-webtile://?action=download-manifest&url=”. The web tile I created for my blog is in this case: mshealth-webtile://?action=download-manifest&url=http://1drv.ms/1TDRGSC . This link only works on phones (also Android and iOS). It opens the Microsoft Health app (that needs to be installed for the usage of web tiles, anyways) and asks you to install the web tile:

wp_ss_20160226_0001

Once you have done that, your web tile is ready to go. Once you have a new entry in your RSS feed, the notification should appear on your band. If you want to force the update, just force the Microsoft Health app to sync with your band. After that, you should see the notification and also the badge count. Here is a shot of the one I did for testing:

WP_20160226_17_48_20_Rich_LI

I only began to play around with web tiles, and already was able to create a pretty good result so far. As I will explore them more and more, I will continue to blog about it. In the meantime, I hope this blog post is helpful for some of you. Have fun, everybody!

Posted by msicc in Dev Stories, Microsoft Band, User Stories, Windows Phone, 1 comment

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