In this lesson, we'll use a timer. It's crucial for making programs do tasks at specific times or after delays.
Imagine if we forgot cake in the oven and it burned! Timers in programming are like oven timers β they prevent disasters. They say, "Hey program, do this at this time. Don't forget!"
But first, let's make our app UI more helpful.
UI (also called GUI) means (Graphical) User Interface. It's what people see and touch in the app. Like a restaurant menu, UI helps us navigate and choose on a screen. In WinUI 3.0, we use XAML to make UI look yummy.
Just as we wouldn't serve stew in a mug or cake on a saucer, our app's layout must match its purpose. Let's see the layout for our plant care reminder.
<StackPanel Orientation="Vertical">
<TextBlock Text="Set Reminder Time" Margin="10"/>
<TextBox x:Name="TimeInput" PlaceholderText="HH:mm" Margin="10"/>
<Button Content="Set Reminder" Click="SetReminder_Click" Margin="10"/>
</StackPanel>
A StackPanel is like a shelf with plates stacked vertically. It neatly stacks UI elements, like plates, one on top of the other in a tidy line.
Imagine a jar of jam in the kitchen. It has a label telling you what's inside. Similarly, a TextBlock explains what's happening in the app. Here, it tells the user about setting the Reminder Time.
A TextBox is where you input the reminder time. The PlaceholderText is like an empty plate saying "Food here." It guides you to write hours and minutes in "HH:mm" format.
We know about Buttons already. When the new one is clicked, it calls the SetReminder_Click method. So, we'd better create one!
public void SetReminder_Click(object sender, RoutedEventArgs e)
{
string time = TimeInput.Text;
SetReminder(time);
}
In programming, a "string" is like a box of words. It's a sequence of characters strung together. It can be a name, a sentence, or anything we write. Like a box holds things, a string holds and represents text in computer programs. In our program, we take the Text from our TimeInput TextBox and place it into the string variable called time.
When the "Set Reminder" button is clicked, it triggers a method. It takes the time entered in a text box and calls another method named "SetReminder" with that time as a parameter.
Having a separate SetReminder method lets us reuse the reminder functionality in different parts of our code. The SetReminder_Click method is for handling the button click event, while the SetReminder method can be called from other places, like a timer or a different button, to easily set reminders without repeating code.
In our last lesson, we talked about our recipe's ingredients: DateTime, DispatcherTimer, and some key methods like Tick, Start, and Stop. Now let's dive into our coding cauldron and start creating our delightful dish - our reminder timer!
First, let's understand our main ingredient: the DispatcherTimer. It's like a multi-timer in our kitchen. Here's how we set it up:
public DispatcherTimer timer;
We create a DispatcherTimer called "timer." It's a global variable, which means we initialize it outside the methods. There's a good reason for that.
If we made the DispatcherTimer inside a method, we could only use it in that method. But since it's global, we can use "timer" in all the methods! Also, notice that global variables need permission, so we make it public in this case.
public DispatcherTimer timer;
public void SetReminder(string time)
{
timer = new DispatcherTimer();
}
It's like we've just set up our multi-timer, ready to start cooking! Next, we add a touch of "Tick" to our timer:
In programming, events are a way for objects to communicate. When something happens, like a button being clicked or a timer finishing counting, it tells the computer to do a specific action called an event handler.
Let's take a peek at how we use this timer in our SetReminder method.
timer = new DispatcherTimer();
timer.Tick += Timer_Tick;
In our code, the event "timer.Tick" occurs when the timer finishes counting, and "Timer_Tick" is the name of the action that runs when the Tick event happens. These names may seem similar, but they have different roles.
The event name, "timer.Tick," is like a special event we pay attention to, while "Timer_Tick" is the name of the action that contains the code we want to run when the event occurs. People often combine the object's name ("timer") and the event's name ("Tick") to clarify which event we are handling.
Using events allows for more flexible programming. If we had to keep track of time ourselves and call methods when specific times arrived, it would be troublesome. Instead, we can "subscribe" to an event, like the Tick of a timer, and instruct it to notify us only when it reaches the desired time.
Alright, chefs, it's time to cook up the Timer_Tick method. This part of our code recipe handles what occurs when our DispatcherTimer ticks β that is, when the countdown is complete.
First off, we have:
public void Timer_Tick(object sender, object e)
{
timer.Stop();
}
Imagine taking a pot off the stove. That's what we do when we give the timer a break. We must be careful not to start counting down again until we're ready for the next reminder.
Next, we serve a notification:
ShowToastNotification("Plant care reminder", "It's time to take care of your plants.");
Think of it as serving a meal. "ShowToastNotification" is like a waiter bringing out the food (or reminder). We tell the user, "Your reminder is ready!" This helps them know when to water their plants.
After delivering the reminder, we prepare for the next one:
timer.Interval = TimeSpan.FromDays(1);
Here, we get a TimeSpan of one day using FromDays. We set the timer to go off again in a day by assigning the one-day TimeSpan to the timer's Interval. It's like preheating the oven for the next dish. We ensure the user gets a daily reminder.
Lastly, we start the timer ticking again:
timer.Start();
This is like putting the pot back on the stove, igniting the timer for the next countdown.
Without these steps, the timer would only notify the user once and stop. It's like baking one muffin when you need a dozen. By stopping, delivering the notification, resetting the interval, and starting again, we make sure the user receives regular, daily reminders. And that, chefs, is a recipe for a successful user experience!
Ready, set, simmer! Let's understand the SetReminder method, which is like the recipe card telling us how to prepare our timer stew.
public void SetReminder(string time)
{
string[] timeParts = time.Split(':');
int hour = int.Parse(timeParts[0]);
int minute = int.Parse(timeParts[1]);
// Rest of the code...
Here we're taking the user's input (the time they want to set the reminder for), and we're breaking it down into hours and minutes with Split method, like separating eggs. We then convert these into integers, as our recipe requires whole numbers.
Next, we fetch the current date and time with DateTime.Now property. It's like checking the clock to know when to start cooking.
DateTime now = DateTime.Now;
DateTime nextReminder = new DateTime(now.Year, now.Month, now.Day, hour, minute, 0);
The new DateTime is the time for the next reminder. The parameters set the year, month, day, hour, minute, and second. We're using today's date, but the hours and minutes the user inputted. It's like setting our oven timer to beep when our dish should be ready.
if (now > nextReminder)
{
nextReminder = nextReminder.AddDays(1);
}
This is our secret sauce: we check if the current time has passed the time for the reminder. If it has, we set the reminder for the same time, but tomorrow with AddDays method. It's like realizing our dish needs more time in the oven, so we adjust our timer accordingly.
TimeSpan timeUntilNextReminder = nextReminder - now;
Then, we calculate the time left until the next reminder. It's the equivalent of checking how much longer our dish needs to bake. Finally, we need to add a couple of lines at the end of our SetReminder method:
timer = new DispatcherTimer();
timer.Interval = timeUntilNextReminder;
timer.Tick += Timer_Tick;
timer.Start();
timer.Interval is the time duration set for a timer to wait between each tick. It's like telling the timer how long to wait before it makes the next tick sound. By setting the Interval as timeUntilNextReminder, the timer will now kick off the event at the time we set. All that's left is to call the Start method of the timer to get it ticking.
If you now run your app and set the timer to, say, one minute from your current time, you should see a toast notification pop up.
Remember: good chefs manage their time efficiently, but great chefs automate it with code.
Visual Studio project:
winui3basics4.zip (17 KB)
winui3basics4 in GitHub