
In this update, a little code cleanup, a “Need to be Saved” indicator, and new minimum app window width and height settings.
Remember, the latest version of the code is available on GitHub.
Given all the refactoring work I’d done on the WPF version of this app (.NETpad), I was never super comfortable with the quick and dirty approach I was taking to WinUIpad. But this was born of necessity: The Windows App SDK isn’t just new to me, it’s terrible, all kinds of terrible, and lots of things that just work in WPF don’t work here. So this really is a rewrite in so many ways, and I’ve pushed forward in my unsophisticated way, hoping to brute force this thing into a basic app that actually works. But the goal has always been to clean up the code once it does work. And I’ve been trying to stamp down that annoying part of my brain that doesn’t want to wait on doing that.
But after I posted the previous update, timo47 provided me with some very useful feedback, some of which touches on my quick and dirty approach with the Windows App SDK. (And thanks again for that.) I would have gone through it regardless, but because this had been bothering me anyway, I was more eager to do so than I might have been otherwise.
To be clear, I haven’t cleaned up the entire program. But before I pushed the previous code update to GitHub, I had been experimenting with different types of state checks (it’s possible I’m obsessed with app state), and though I knew that an unnecessary App-level state property I had created and then used in several places was still in there, I had let it go, figuring I would simply remove all that on the next pass.
In making that change, I discovered that my use of this new property in the FileOpMenu_Click() event handler had caused an error that prevented the user from opening a document. So I pushed that change to GitHub as soon as I was sure I had reverted it correctly.
Among other things, timo47 asked me why I was calling the (Main) Window’s Close() event handler from the AppWindow’s OnClosing() event handler. I wish I could answer that accurately, but it came out of what is now a familiar experience when working with the Windows App SDK: Nothing ever works, and so I find myself adding more and more code to try to get around whatever issue. And then I forget why I went down that particular rabbit hole.
In this case, I was hoping to just create a single method that ran each time the user tried to close the app window, one that would check whether the document needed to be saved and, if so, then save (or save as) the document as needed or back out if the user cancelled. This proved impossible as I wrote in the previous post. And so I settled on two primary event handlers for app closing: OnClosing() in AppWindow and ExitMenu_Click().
I went through too many permutations of each to count or remember, but I did temporarily leave some commented out code in each that was from previous attempts. And since then, I’ve cleaned up both considerably in part by creating a separate BeforeClosing() helper method that both now call. That’s where the state checks occur now.
In any event, OnClosing() and ExitMenu_Click() both do the same thing now, though the former has that e.Cancel = true; code in there to defer the app window closing so I can clean up first. Here’s the version from OnClosing():

Super-simple and, as important, it just seems to work, and in both event handlers.
timo47 also told me that recent versions of the Windows App SDK now offer an AppWindow property of a Window class. I did not know that, but I was able to remove a lot of ugly code thanks to that tip.
For example, this block of code:

Is now this simple:

Very nice. And there were several examples of this throughout. ?
Back when I set out to figure out data binding, one of my first successes was a little colored icon that would appear or disappear based on the status of the TextHasChanged property that’s now part of the Document class. This mirrors how Notepad works. When there’s an unsaved change, the little Close (“x”) button on the current tab changes to a bullet. When that document is saved, or replaced, or whatever, it goes back to normal.

This behavior is a rare example of data binding just working, and that’s true because a Boolean/Visibility converter is built in for whatever reasons. The TextHasChanged property is a boolean (true/false) value and I just toggle the display of the little “Need to be indicator based on that value. If the text in the TextBox has changed, the indicator is visible. Otherwise, it is not.
In this simpler, single-document version of WinUIpad, the “Needs to be Saved” indicator appears to the right of the document name in the app’s title bar, as it did in the pre-tabs versions of Notepad. When I finally move back to working on tabs again, I will implement it as a replacement for each tab’s “Close tab” button per modern versions of Notepad.
Implementing this couldn’t have been easier, as I’d done this before and could simply refer to my earlier code. I just added a small 16 dip wide TextBlock next to the Document title TextBlock in XAML and added the following code to bind the control’s Visibility property to the TextHasChanged property of the Document object instance:
Visibility=”{x:Bind doc.TextHasChanged, Mode=OneWay}”
And that’s all there is to it. When TextHasChanged is true, the little bullet character appears next to the document name. When it’s false, it does not.

Here’s yet another example of something that’s easy to do in WPF but is as tedious as a root canal in the Windows App SDK. You have an app window, and while it can be resized, you also want to limit how small it gets. And so the WPF Window class has MinWidth and MinHeight properties. You can even set them right in the XAML for the MainWindow and never think about it again. Perfect.
The Windows App SDK does not support these properties on MainWindow, AppWindow, or any other kind of window because the Windows App SDK is terrible. And though Microsoft has known about this obvious omission for several years, it has never fixed it. And so the official advice is to write hundreds of lines of Win32 C interoperability code. Yeah, right.
At first, I refused, because that is ridiculous. And then I finally gave in, realizing I could simply tuck that code away in some black box class and never even try to learn why it works. But when I re-searched on this topic, I came up with a far more elegant and less wordy solution at the bottom of this StackOverflow page.

I was positive it wouldn’t work, but it does. So I am moving on.

As always, the latest code updates can be found in the GitHub repository.
More soon
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.