The UWP Notepad Project (Redux): Auto Save (Premium)

Today, we’ll implement .NETpad’s Auto Save functionality, which will work nearly identically to the way we did it previously in Windows Presentation Foundation (WPF).

To get started, we need to add a DispatchTimer to our project using code. (You may recall that in Windows Forms, we could drag a Timer object in from the toolbox, but with UWP and WPF, we need to do this manually.)  So open up MainPage.xaml.cs and scroll up to the top and locate the MainPage class definition. There, you will find a variety of what I call global variables, broken into groups like “For font settings,” “For other (non-font) settings” and so on. Below the last group (“For Find and Replace”) open up some space and add the following code:

// For Auto Save
readonly DispatcherTimer Timer1 = new DispatcherTimer();

Now, locate ReadSettings(). At the bottom of the main if clause (which fires when there are saved savings to use), you’ll find an “Auto Save” section that looks like so:

// Auto Save
if (myAutoSave == true)
    AutoSaveButton.Content = "Auto Save: On";
else 
    AutoSaveButton.Content = "Auto Save: Off";

We need to edit this code to specify the timer’s Interval property, which is the frequency at which its Tick() method will fire. And we need to specify a method that will handle that Tick event. Then, we need to start the timer if the myAutoSave variable (and thus the MyAutoSave setting) are true, or stop it if it is not.

The revised code will look like so:

// Auto Save
Timer1.Interval = TimeSpan.FromSeconds(3);
Timer1.Tick += Timer1_Tick;
if (myAutoSave == true)
{ 
    AutoSaveButton.Content = "Auto Save: On";
    Timer1.Start();
}
else 
{ 
    AutoSaveButton.Content = "Auto Save: Off";
    Timer1.Stop();
}

Two notes here.

First, we’re setting the timer interval to 3 seconds now for testing purposes: It would be tedious to wait 30 seconds to see whether our code works. When we’re sure that everything is working properly, we will change that to 30, for 30 seconds.

Second, the Timer1_Tick bit will have a red squiggly under it because that method doesn’t yet exist. So let’s add that next: Scroll down to the bottom of the MainPage class definition and add the following empty event handler below whatever is currently the last method there (it’s ZoomInButton_Click() on my PC).

private void Timer1_Tick(object sender, object e)
{
    // 
}

We’ll add some code in there later, but that is enough to clear up the error we were seeing.

Next, locate AutoSaveSwitch_Toggled(). This method fires when the user makes a change to the Auto Save setting in the Settings pane. Currently it looks like this:

private void AutoSaveSwitch_Toggled(object sender, RoutedEventArgs e)
{
    if (AutoSaveSwitch.IsOn == true)
        AutoSaveButton.Content = "Auto Save: On";
    else
        AutoSaveButton.Content = "Auto Save: Off";
    SaveOtherSettings();
}

As with ReadSettings() above, we need to start or stop the timer when the user makes a change here too. So edit the code so that it now looks like this:

private void AutoSaveSwitch_Toggled(object sender, RoutedEventArgs e)
{
    if (AutoSaveSwitch.IsOn == true)
    { 
        AutoSaveButton.Content = "Auto Save: On";
        Timer1.Start();
    }
    else
    { 
        AutoSaveButton.Content = "Auto Save: Off";
        Timer1.Stop();
    }
    SaveOtherSettings();
}

Now, locate that empty Timer1_Tick() event handler that we added earlier. Here, we need to determine whether the document needs to be saved whenever the Tick event fires (every 30 seconds normally, but every 3 seconds for now while we test it). This takes the familiar form of our two checks, for whether the text has changed and whether the document has already been saved, respectively. But there is one other wrinkle: Because the Save() and SaveAs() methods that this event handler calls are asynchronous, we need to stop the timer before calling them and then restart the timer when this event handler concludes. Otherwise, the Tick() event would fire repeatedly and you can get stuck in a situation where the user is dealing with a Save As dialog and then another Save As dialog appear. And then another. And another…

We don’t want that.

private async void Timer1_Tick(object sender, object e)
{
    Timer1.Stop();

    if (TextHasChanged)
    {
        if (DocumentName.Length == 0)
            await SaveAs();
        else
            await Save();
    }

    Timer1.Start();
}

Note that we had to add the async keyword because we’re using await inside the event handler.

OK, that should do it. When you test the app, enable the Auto Save feature, make any change to the empty document, and make sure a Save As dialog appears after three seconds. Also make sure that the Auto Save setting correctly retains the right value each time you start the app. I think it works correctly, but anything is possible.

And if you’re sure it’s working correctly, don’t forget to change the value of Timer1.Interval from 3 seconds to 30 seconds in ReadSettings().

Next up, I’ll fix the style problems so that .NETpad displays correctly—i.e. that the text box is always white—no matter whether the user is using Light or Dark mode. That fix should bring this app up to what I think of as the minimum level of functionality and usability. But I have a few more additions I’m considering, so it’s likely that I’ll evolve it past there as well.

More soon.

Gain unlimited access to Premium articles.

With technology shaping our everyday lives, how could we not dig deeper?

Thurrott Premium delivers an honest and thorough perspective about the technologies we use and rely on everyday. Discover deeper content as a Premium member.

Tagged with

Share post

Thurrott