Getting started with UWP

Barbie Martínez
10 min readAug 1, 2018

--

The idea of this article is to introduce you to UWP core concepts and try them out by building a Pomodoro timer. If you already know what UWP is, you can go straight to Creating our first app section.

Introducing UWP

Universal Windows Platform (UWP as of now) is a Microsoft API introduced in Windows 10 OS. This API provides a common platform that is available for any Windows-compatible device. This means you can create an app package and install it onto a wide range of devices.

UWP is compatible with several programming languages, including C, C++, C#, Visual Basic, and JS. It also provides many ways to keep interacting with the user, even when the app is inactive.

Besides, these applications need user authorization to perform any action, for this reason, the user will always be aware of the app required permissions. This feature, and the ability to install and uninstall the application without touching the root directory makes UWP apps even safer than any other.

One app for all devices

UWP is compatible with all Windows 10 devices. That’s because it has controls and inputs that respond to size and DPI from any screen. This feature makes them adjust to each screen size, beyond layout and/or scaling.

Also, UWP has many SDK extensions with exclusive features for some devices or a family of them. For more information about SDK extensions, please read the official documentation.

Keep users engaged

Nowadays, we don’t go to information, it comes to us, and it is very important to stay connected with everything. UWP provides tools to allow interaction with the OS. Thus, the user has, in real time, the necessary information for his day to day. The most used are tiles, notifications, background execution, bluetooth, speech interaction and Cortana integration.

Distributing your app

You can distribute your apps into a wide range of devices using Windows Store. The store provides a unified distribution medium and a one-place management using Windows Dev Center Dashboard. There are several ways to earn profits with apps, the most popular are Paid download, Free trials, Sales, In-app purchases and Ads.

What is Pomodoro ?

It is a time management technique created by Francesco Cirillo. It consists in carrying out a task in 25 minutes focusing only on it.

You can do this by setting a pomodoro timer for 25 minutes and focus on your task until it rings. When the time’s up, put a checkmark on a paper and take a five minutes rest. Do this for every task until you have reached the fourth pomodoro. After the fourth one, you can take a longer break

For more information about how you can do proper time management, please visit the official site blogpost.

Creating your first app

A very effective way to put theory into practice is to start coding a simple project. The following tutorial explains how you can create a Pomodoro timer. It’s a simple and complete project that involves important and useful UWP concepts like notification handling, app lifecycle, UI bindings and more.

Setting up the environment

To follow this tutorial, you have to get Visual Studio installed and enable your device for development.

For more information about how you can set up visual studio for UWP development, you can read the get set up tutorial and try to build your first app.

Adding the timer

In this section, we will show you how to stop, start, reset and set a rest time in case the task interval time has finished.

The DispatcherTimer is a .NET Core class from System.Windows.Threading.DispatcherTimer for time handling. It has a tick function which can be set up with a callback and it can be initialized with int or TimeSpan clases.

In our main class we are going to initialize the dispatcher timer and setup the tick method. We init the DispatcherTimer using initializeTimer method. Also, we defined the _restsTaken, _currentTime and _tickInterval variables. _restsTaken counts the rests taken number. _currentTime sets the current interval number in minutes. And the_tickInterval sets the value for each tick.

public MainPage()
{
this.InitializeComponent();
_takenTicks = 0;
_currentTime = 0;
_timeInterval = TimeSpan.FromSeconds(1);
this.initializeTimer(_timeInterval.Seconds);
this.initializeDisplayTimer(0);
}

We use an enum class called Interval to declare the number in minutes of each interval. We have an interval for the current task, one for the short rest and one for long rest.

private enum Interval
{
Task = 2,
ShortRest = 1,
LongRest = 6
};

InitializeTimer method

private void initializeTimer(int tickInterval)
{
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromSeconds(tickInterval);
_timer.Tick += interval_Tick;
}

We can set up the dispatcher timer interval using a one second TimeSpan, as we want the timer to tick every second. The tick function will be executed on every tick.

InitDisplayTimer method

private void initializeDisplayTimer(int intervalTime)
{
_intervalRemainingTime = TimeSpan.FromMinutes(intervalTime);
timerLabel.Text = _intervalRemainingTime.ToString();
}

In this method, we are displaying the timer into the canvas. The timerLabel only will show the initial state.

Interval_Tick method

private void interval_Tick(object sender, object e)
{
_intervalRemainingTime = _intervalRemainingTime.Subtract(_timeInterval);
timerLabel.Text = _intervalRemainingTime.ToString();
}

For each tick the function substracts a second and updates the UI with the new time.

Now the timer is on our app, but it still isn’t working.

A quick way to test it is to start the timer in the main method. We can do this timer.start() at the end of the initialization. When it finishes the countdown, stop the clock like this.

if(TimeSpan.Equals(DisplayTimer,TimeSpan.Zero))
{
timer.stop()
}

We cannot control the flow of time yet, the clock only will keep going until it stops. Now, we are going to show you how to add buttons to handle this.

Binding the timer to the UI

We’re going to add the start,stop,reset and rest buttons to handle the timer flow. They are simple functions by now but as we move forward, we’re going to add more complexity.

First we’re going to draw our UI in XAML.

<Grid HorizontalAlignment="Center" VerticalAlignment="Center" Width="auto" Height="146">
<TextBlock x:Name="timerLabel" HorizontalAlignment="Center" Text="00:00:00" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="60" FontWeight="Normal" TextAlignment="Center" Width="328" Margin="0,0,0,0"/>
<Button Name="startButton" Content="Start" HorizontalAlignment="Left" Click="Button_Click_Start" VerticalAlignment="Top" Margin="44,101,0,0"/>
<Button Name="stopButton" Content="Stop" HorizontalAlignment="Left" Click="Button_Click_Stop" VerticalAlignment="Top" Margin="104,101,0,0" RenderTransformOrigin="1.373,0.57"/>
<Button Name="resetButton" Content="Reset" HorizontalAlignment="Left" Click="Button_Click_Reset" VerticalAlignment="Top" Margin="164,101,0,0" RenderTransformOrigin="1.373,0.57"/>
<Button Name="restButton" Content="Rest" HorizontalAlignment="Left" Click="Button_Click_Rest" VerticalAlignment="Top" Margin="230,101,0,0" RenderTransformOrigin="1.373,0.57"/>
</Grid>

Now, it should look like this

Displaying the timer. In our interval_tick method, we're going to show our label with updated timer. We added the line timerLabel.Text = _intervalRemainingTime.ToString(); below the minute substraction. The method should be looking like this.

private void interval_Tick(object sender, object e)
{
TimeSpan previousTime = _intervalRemainingTime;
_intervalRemainingTime = _intervalRemainingTime.Subtract(_timeInterval);
timerLabel.Text = _intervalRemainingTime.ToString();
}

Also, we need a label that notifies us when the time’s up. So, we’re going to add a validation that stops the timer and adds a ‘Time’s up’ label when the time’s up. Like this.

if (TimeSpan.Equals(_intervalRemainingTime, TimeSpan.Zero))
{
_timer.Stop();
timerLabel.Text = "Time´s up";
UpdateTile("Time´s up");
}

So, the final method should be:

private void interval_Tick(object sender, object e)
{
TimeSpan previousTime = _intervalRemainingTime;
_intervalRemainingTime = _intervalRemainingTime.Subtract(_timeInterval);
timerLabel.Text = _intervalRemainingTime.ToString();
if (TimeSpan.Equals(_intervalRemainingTime, TimeSpan.Zero))
{
_timer.Stop();
timerLabel.Text = "Time´s up";
UpdateTile("Time´s up");

}
}

Start button

The start button makes the timer go on after stop button or rest. The timer begins at 00:00:00. When you hit the start button, it will start their countdown from the interval set before .

We’re going to focus in our event start. It will only trigger the timer.

private void Button_Click_Start(object sender, RoutedEventArgs e)
{
_timer.Start();
}

Stop button

The stop button makes the timer stops while it is running. As start function, it will only stop the timer before it reaches 0.

private void Button_Click_Start(object sender, RoutedEventArgs e)
{
_timer.Start();
}

Reset button

The reset button resets the timer at the current interval beyond of their interval type. This function not only resets the timer at 0, it also stops the clock and decides which interval has to reset. We set the _currentInterval variables on the start and rest buttons. It's important to keep in mind that because the function only obeys to this variable.

private void Button_Click_Reset(object sender, RoutedEventArgs e)
{
_timer.Stop();
this.initializeDisplayTimer(_currentTime);
}

Rest button

The rest button sets the rest interval. But, this function doesn’t reset the timer at rest time. Also decides which rest will be taken. It can be a long or short one based on the number of rests taken. So far, this is the most complex event handler on this project.

private void Button_Click_Rest(object sender, RoutedEventArgs e)
{
_takenTicks++;
int longRestTime = 0;
if (_takenTicks == 3)
{
longRestTime = (int)Interval.LongRest;
_takenTicks = 0;
}
else
{
longRestTime = (int)Interval.ShortRest;
}
_isRestTime = true;
_currentTime = longRestTime;
_timer.Start();
}

Attaching the events to their respective buttons

Note that in XAML Tag there’s a Click property. Simply we're going to reference our event in this proprety.

Handling the app lifecycle

There’s still a problem with this timer implementation. When you minimize the app, the timer will stop until you resume it. To avoid this, we are going to show you how to handle the App_Resuming method.

The App_Resuming method handles the window resume event.

private void App_Resuming(Object sender, Object e)
{
if (_isRunning)
{
if (_intervalEnd <= DateTime.Now)
{
_timer.Stop();
timerLabel.Text = "Time`s up";
}
else
{
TimeSpan diff = (_intervalEnd - DateTime.Now);
_intervalRemainingTime = new TimeSpan(0, diff.Minutes, diff.Seconds);
timerLabel.Text = _intervalRemainingTime.ToString();
}
}
}

The variable _intervalEnd is the time when the countdown started plus time interval. When the timer's time is bigger or equal than this _intervalEnd, the app will substract to our interval time the DateTime.Now time. Thus, this will be the new time displayed on the UI. Also, notice that the isRunning flag is always checking if the timer is actually running before handling the event logic. This was done to make sure that the event logic doesn't activate while the timer is stopped and minimized.

It’s important to suscribe to this event on app initialization, otherwise, it won’t work.

Application.Current.Resuming += new EventHandler<Object>(App_Resuming);

Notification when the time’s up

So far, our app is getting into shape, but what if we keep our app window minimized until the time’s up?. We won’t know when it’s time to take a rest and we’ll keep going until we’re stressed out. To avoid this, we can trigger a notification when the time’s up.

For this tutorial, we’re going to implement the ScheduledToastNotificationnotification class, as we already know when the notification should appear. This class schedules a Windows 10 toast notification that will be triggered when the timer reaches the scheduled time.

Setting the notification time

To do this, we’ll set the _intervalEnd variable when we start the timer for any interval, be it task or rest. To calculate the exact time, we'll create a DateTime with the current time using DateTime.Now.Then, we'll add the remaining time obtained from _intervalRemainingTime.

In the Start button click event handler, we’ll assign the value to _intervalEnd using the logic we've explained, right after the code to reset the timer.

private void Button_Click_Start(object sender, RoutedEventArgs e)
{
if (TimeSpan.Equals(_intervalRemainingTime, TimeSpan.Zero))
{
_currentTime = (int)Interval.Task;
this.initializeDisplayTimer(_currentTime);
}

_intervalEnd = DateTime.Now.Add(_intervalRemainingTime);
}

In the Rest button click event handler, we’ll add the same logic after we determine which rest goes next (long or short).

private void Button_Click_Rest(object sender, RoutedEventArgs e)
{
_takenTicks++;
int longRestTime = 0;
if (_takenTicks == 3)
{
longRestTime = (int)Interval.LongRest;
_takenTicks = 0;
}
else
{
longRestTime = (int)Interval.ShortRest;
}
_intervalEnd = DateTime.Now.Add(TimeSpan.FromMinutes(_currentTime));}

Creating the notification

The ScheduleNotification method allows us to configure the time in which the pop-up notification will be shown.

private void ScheduleNotification(string title, string description)
{
var notificationDictionary = new Dictionary<string, string>()
{
{ "{TITLE}", title },
{ "{DESCRIPTION}", description }
};
var notificationXML = LoadAndPopulateXMLFile("/Resources/Notification.xml", notificationDictionary);
var toastScheduled = new ScheduledToastNotification(notificationXML, _intervalEnd);
ToastNotificationManager.CreateToastNotifier().AddToSchedule(toastScheduled);
}

We have an XML template to set the notification style. In it, we’ll replace the strings {TITLE} and {DESCRIPTION} with the current information to display in our notification. Then, we'll schedule the notification to our interval end time and add it to the notification queue. This XML template is handled with the LoadAndPopulateXMLFile method.

private XmlDocument LoadAndPopulateXMLFile(string fileNameWithExtension, Dictionary<string, string> dictionary)
{
var xmlDocument = new XmlDocument();
var xmlFile = File.ReadAllText(Directory.GetCurrentDirectory() + fileNameWithExtension);
foreach (var item in dictionary)
{
xmlFile = xmlFile.Replace(item.Key, item.Value);
}
xmlDocument.LoadXml(xmlFile);
return xmlDocument;
}

This method allows the user to upload their own xml file and create the notification template setting their resource path and a dictionary with all the key strings that will be replaced.

Setting up the live tile

Another great feature of UWP is the integration with the OS. To showcase this feature, we’ll set up a live tile in the start menu. This will show a label with the number of minutes remaining before the time’s up. You’ll have to create the live tile in the start menu beforehand to test this feature.

Update the tile

The implementation of the live tile is the same as toast notification implementation. We set the text tile with the UpdateTile method. It uses an XML template to create the tile, and then we trigger it on the interval_tick method.

private void UpdateTile(string tileSign)
{
var tileDictionary = new Dictionary<string, string>()
{
{ "Please Start!", tileSign }
};
var tile = new TileNotification(LoadAndPopulateXMLFile("/Resources/Tile.xml", tileDictionary));
TileUpdateManager.CreateTileUpdaterForApplication().Clear();
TileUpdateManager.CreateTileUpdaterForApplication().Update(tile);
}

The LoadAndPopulateXMLFile populates the XML and creates the live tile notification. It's important to clear the live tile before updating it.

In the interval_Tick, we'll add an if statement to determine when a minute has passed. We call the updateTile method when that condition is met. The variable previousTimeInMinutes saves the state of the timer before a second has passed.

private void interval_Tick(object sender, object e)
{
timerLabel.Text = _intervalRemainingTime.ToString(); if (!TimeSpan.Equals(previousTimeInMinutes.Minutes, _intervalRemainingTime.Minutes))
{
string timeIndicator = _intervalRemainingTime.Minutes == 0 ? "1 >" : _intervalRemainingTime.Minutes.ToString();
UpdateTile(timeIndicator + " minute(s) left");
}
}

Wrapping up

In this blogpost, you saw a brief explanation about what UWP is, what we can do with it, and created a pomodoro timer app from scratch to show you some of the most used platform features in a practical way. However, some features, such as the live tile and the toast notification implementation, can be improved by using the utilities provided by the Windows Community Toolkit instead of using a plain XML template.

This was a very simple introduction to understand some of the core concepts of UWP. If you’d like to keep learning about UWP, stay tuned for the next blogpost in which we’ll improve this pomodoro timer using the Windows Community Toolkit.

See you!

References

Pomodoro Timer project

Pomodoro timer official page

UWP Official site

--

--

Barbie Martínez

Code artisan & Cat lover. Find me to learn something about coding, social skills and beautiful designs.