Live tiles and notifications in Universal Windows 10 App

Live tiles and notifications in Universal Windows 10 App

liveTiles1

Short introduction

Windows 10 is concentrated on user productivity and provides amazing features that help notify about the meeting or a flight in the nearest future. That’s why today I would like to show you great features:

Live tiles and Notifications for Universal Windows 10 App!

What do I need to start?

1) Windows 10 operating system – can be neither Education edition or Enterprise

2) Visual Studio 2015 Comminity (for free) or higher

 

Let’s start

 1) Launch Visual Studio 2015

liveTiles2

2) From “File” menu select “New” and then “Project”. Give it the name – “UniversalwindowsApp”:

liveTiles3

3) Open “MainPage.xaml” file and paste below code between <Grid> </Grid> tags:

<grid background="{ThemeResource ApplicationPageBackgroundThemeBrush}">  
        <grid.rowdefinitions>  
            <rowdefinition>  
            <rowdefinition>  
        </rowdefinition></rowdefinition></grid.rowdefinitions>  
        <stackpanel grid.row="0" margin="12">  
            <textblock text="Adaptive Tiles" fontsize="20" fontweight="Bold">  
            <button click="UpdateBadge" verticalalignment="Top" margin="12" background="#330070B0">Update Badge Count</button>  
            <button click="UpdatePrimaryTile" verticalalignment="Top" background="#330070B0" margin="12">Update Primary Tile</button>  
        </textblock></stackpanel>  
        <stackpanel grid.row="1" margin="12">  
            <textblock text="Interactive Toast" fontsize="20" fontweight="Bold">  
            <stackpanel orientation="Horizontal" margin="12">  
                <textblock x:name="Description" verticalalignment="Center" text="{x:Bind CurrentToDoTask.Description, Mode=OneWay}" fontweight="Bold">  
                <checkbox margin="12,0,0,0" ischecked="{x:Bind CurrentToDoTask.IsComplete, Mode=OneWay}" isenabled="False">  
            </checkbox></textblock></stackpanel>  
            <button click="Notify" background="#330070B0" margin="12">Notify</button>  
            <button background="#330070B0" click="{x:Bind Refresh}" margin="12">Refresh</button>  
        </textblock></stackpanel>  
    </grid>  

liveTiles4

4) Now let’s add some tile information. Create folder named “Data”: and add new class named “PrimaryTile”. It should look like below:

liveTiles5

public class PrimaryTile  
{  
 public string time { get; set; } = "8:15 AM, Saturday";  
 public string message { get; set; } = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed  do eiusmod tempor incididunt ut labore.";  
 public string message2 { get; set; } = "At vero eos et accusamus et iusto odio dignissimos ducimus  qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias  excepturi sint occaecati cupiditate non provident.";  
 public string branding { get; set; } = "name";  
 public string appName { get; set; } = "UWP";  
}  

 

 5) Let create two services: “tileservice” and “toastservice” in folder named “services”:

liveTiles6

public class TileService  
    {  
        static public void SetBadgeCountOnTile(int count)  
        {  
            // Update the badge on the real tile  
            XmlDocument badgeXml = BadgeUpdateManager.GetTemplateContent(BadgeTemplateType.BadgeNumber);  
  
            XmlElement badgeElement = (XmlElement)badgeXml.SelectSingleNode("/badge");  
            badgeElement.SetAttribute("value", count.ToString());  
  
            BadgeNotification badge = new BadgeNotification(badgeXml);  
            BadgeUpdateManager.CreateBadgeUpdaterForApplication().Update(badge);  
        }  
  
        public static Windows.Data.Xml.Dom.XmlDocument CreateTiles(PrimaryTile primaryTile)  
        {  
            XDocument xDoc = new XDocument(  
                new XElement("tile", new XAttribute("version", 3),  
                    new XElement("visual",  
                        // Small Tile  
                        new XElement("binding", new XAttribute("branding", primaryTile.branding), new XAttribute("displayName", primaryTile.appName), new XAttribute("template", "TileSmall"),  
                            new XElement("group",  
                                new XElement("subgroup",  
                                    new XElement("text", primaryTile.time, new XAttribute("hint-style", "caption")),  
                                    new XElement("text", primaryTile.message, new XAttribute("hint-style", "captionsubtle"), new XAttribute("hint-wrap", true), new XAttribute("hint-maxLines", 3))  
                                )  
                            )  
                        ),  
  
                        // Medium Tile  
                        new XElement("binding", new XAttribute("branding", primaryTile.branding), new XAttribute("displayName", primaryTile.appName), new XAttribute("template", "TileMedium"),  
                            new XElement("group",  
                                new XElement("subgroup",  
                                    new XElement("text", primaryTile.time, new XAttribute("hint-style", "caption")),  
                                    new XElement("text", primaryTile.message, new XAttribute("hint-style", "captionsubtle"), new XAttribute("hint-wrap", true), new XAttribute("hint-maxLines", 3))  
                            )  
                            )  
                        ),  
  
                        // Wide Tile  
                        new XElement("binding", new XAttribute("branding", primaryTile.branding), new XAttribute("displayName", primaryTile.appName), new XAttribute("template", "TileWide"),  
                            new XElement("group",  
                                new XElement("subgroup",  
                                    new XElement("text", primaryTile.time, new XAttribute("hint-style", "caption")),  
                                    new XElement("text", primaryTile.message, new XAttribute("hint-style", "captionsubtle"), new XAttribute("hint-wrap", true), new XAttribute("hint-maxLines", 3)),  
                                    new XElement("text", primaryTile.message2, new XAttribute("hint-style", "captionsubtle"), new XAttribute("hint-wrap", true), new XAttribute("hint-maxLines", 3))  
                                    ),  
                                new XElement("subgroup", new XAttribute("hint-weight", 15),  
                                    new XElement("image", new XAttribute("placement", "inline"), new XAttribute("src", "Assets/StoreLogo.png"))  
                                )  
                            )  
                        ),  
  
                        //Large Tile  
                        new XElement("binding", new XAttribute("branding", primaryTile.branding), new XAttribute("displayName", primaryTile.appName), new XAttribute("template", "TileLarge"),  
                            new XElement("group",  
                                new XElement("subgroup",  
                                    new XElement("text", primaryTile.time, new XAttribute("hint-style", "caption")),  
                                    new XElement("text", primaryTile.message, new XAttribute("hint-style", "captionsubtle"), new XAttribute("hint-wrap", true), new XAttribute("hint-maxLines", 3)),  
                                    new XElement("text", primaryTile.message2, new XAttribute("hint-style", "captionsubtle"), new XAttribute("hint-wrap", true), new XAttribute("hint-maxLines", 3))  
                                    ),  
                                new XElement("subgroup", new XAttribute("hint-weight", 15),  
                                    new XElement("image", new XAttribute("placement", "inline"), new XAttribute("src", "Assets/StoreLogo.png"))  
                                )  
                            )  
                        )  
                    )  
                )  
            );  
  
            Windows.Data.Xml.Dom.XmlDocument xmlDoc = new Windows.Data.Xml.Dom.XmlDocument();  
            xmlDoc.LoadXml(xDoc.ToString());  
            //Debug.WriteLine(xDoc);  
            return xmlDoc;  
        }  
    }  
 
public static class ToastService  
    {  
        public static XmlDocument CreateToast()  
        {  
            var xDoc = new XDocument(  
                new XElement("toast",  
                    new XElement("visual",  
                        new XElement("binding", new XAttribute("template", "ToastGeneric"),  
                            new XElement("text", "To Do List"),  
                            new XElement("text", "Is the task complete?")  
                            ) // binding  
                        ), // visual  
                    new XElement("actions",  
                        new XElement("action", new XAttribute("activationType", "background"),  
                            new XAttribute("content", "Yes"), new XAttribute("arguments", "yes")),  
                        new XElement("action", new XAttribute("activationType", "background"),  
                            new XAttribute("content", "No"), new XAttribute("arguments", "no"))  
                        ) // actions  
                    )  
                );  
  
            var xmlDoc = new XmlDocument();  
            xmlDoc.LoadXml(xDoc.ToString());  
            return xmlDoc;  
        }  
    }    

 

 6) Now we must add json file with test task structure:

{"Description":"A test task","Id":"9d6c3585-d0c2-4885-8fe0-f02727f8e483","IsComplete":true}     

 7) We need to have access to created json file and its structure in the app:

liveTiles8

public class ToDoTask  
    {  
        public Guid Id { get; set; }  
        public string Description { get; set; }  
        public bool? IsComplete { get; set; }  
  
        public string ToJson()  
        {  
            using (var stream = new MemoryStream())  
            {  
                var serializer = new DataContractJsonSerializer(typeof(ToDoTask));  
                serializer.WriteObject(stream, this);  
                stream.Position = 0;  
                var jsonBytes = stream.ToArray();  
                return Encoding.UTF8.GetString(jsonBytes, 0, jsonBytes.Length);  
            }  
        }  
  
        public static ToDoTask FromJson(string json)  
        {  
            // note: throws exception if the json is not valid  
            var jsonData = JsonObject.Parse(json);  
  
            // exceptions will be thrown if the values do not match the types  
            return new ToDoTask  
            {  
                Id = Guid.Parse(jsonData["Id"].GetString()),  
                Description = jsonData["Description"].GetString(),  
                IsComplete = jsonData["IsComplete"].GetBoolean()  
            };  
        }  
    }  
 
public static class ToDoTaskFileHelper  
   {  
       private static readonly string Filename = "task.json";  
  
       public static async Task ReadToDoTaskJsonAsync()  
       {  
           // declare an empty variable to be filled later  
           string json = null;  
           // define where the file resides  
           var localfolder = ApplicationData.Current.LocalFolder;  
           // see if the file exists  
           if (await localfolder.TryGetItemAsync(Filename) != null)  
           {  
               // open the file  
               var textfile = await localfolder.GetFileAsync(Filename);  
               // read the file  
               json = await FileIO.ReadTextAsync(textfile);  
           }  
           // if the file doesn't exist, we'll copy the app copy to local storage  
           else  
           {  
               var storageFile =  
                   await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/task.json"));  
               await storageFile.CopyAsync(ApplicationData.Current.LocalFolder);  
               json = await FileIO.ReadTextAsync(storageFile);  
           }  
  
           return json;  
       }  
  
       public static async Task SaveToDoTaskJson(string json)  
       {  
           var localfolder = ApplicationData.Current.LocalFolder;  
           var textfile = await localfolder.GetFileAsync(Filename);  
           await FileIO.WriteTextAsync(textfile, json);  
       }  
   }  

 

 8) One last thing – code for “MainPage” to implement showing notifications and updating tiles:

liveTiles9

public sealed partial class MainPage : Page, INotifyPropertyChanged  
   {  
       private int _count;  
       private ToDoTask _currentToDoTask;  
  
       public MainPage()  
       {  
           InitializeComponent();  
           Loaded += MainPage_Loaded;  
       }  
  
       public ToDoTask CurrentToDoTask  
       {  
           get { return _currentToDoTask; }  
           set  
           {  
               _currentToDoTask = value;  
               PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentToDoTask)));  
           }  
       }  
  
       public event PropertyChangedEventHandler PropertyChanged;  
  
       private void MainPage_Loaded(object sender, RoutedEventArgs e)  
       {  
           Refresh();  
       }  
  
       private async void Refresh()  
       {  
           var json = await ToDoTaskFileHelper.ReadToDoTaskJsonAsync();  
           CurrentToDoTask = ToDoTask.FromJson(json);  
       }  
  
       private void UpdateBadge(object sender, RoutedEventArgs e)  
       {  
           _count++;  
           TileService.SetBadgeCountOnTile(_count);  
       }  
  
       private void UpdatePrimaryTile(object sender, RoutedEventArgs e)  
       {  
           var xmlDoc = TileService.CreateTiles(new PrimaryTile());  
  
           var updater = TileUpdateManager.CreateTileUpdaterForApplication();  
           var notification = new TileNotification(xmlDoc);  
           updater.Update(notification);  
       }  
  
       private void Notify(object sender, RoutedEventArgs e)  
       {  
           var xmlDoc = ToastService.CreateToast();  
           var notifier = ToastNotificationManager.CreateToastNotifier();  
           var toast = new ToastNotification(xmlDoc);  
           notifier.Show(toast);  
       }  
   }  

 

9) You can check how does it work! Try to click on the buttons and see the effect:

liveTiles10

liveTiles11

Sum up

Thatt’s it! Now you can create Notifications and Tiles updates inside your Universal Windows 10 App! Enjoy 🙂

Advertisements