.NETpad 2025: First Steps in Rebuilding .NETpad in WASDK/WinUI 3 (Premium)

.NETpad 2025: Rebuilding .NETpad in WASDK/WinUI 3

I’ve made significant progress on WinUIpad, the Windows App SDK (WASDK)/WinUI 3 version of .NETpad. Here’s a quick look at some of the challenges of this port, what I’ve done so far, and what’s left.

Nothing is ever perfect

I’ve been working on a WASDK/WinUI 3 version of .NETpad for the past month or so. In .NETpad 2025: WinUI 3 is the Way Forward (Premium), I explained why, with a few examples of the many ways in which WASDK/WinUI 3 is superior to the Windows Presentation Foundation (WPF) for creating a truly modern Windows app. But that’s only part of the story. There are other advantages beyond those I mentioned in that article. And there are negatives.

So many negatives.

And, no I’m not talking about the fact that Microsoft has pretty much ignored the Windows App SDK and the developers that use it for the past year or so, though that’s certainly a discussion worth having. Granted, it’s still better than the situation with WPF.

No, I’m speaking more of a “death by 1000 cuts” type problem with WASDK/WinUI 3.

To be fair to Microsoft, it has done a pretty good job over decades of giving developers who invested their time, energy, and codebases in .NET a way forward, at least at a high level. Even in the dark years of the Windows Runtime (WinRT) and Windows 8, when Microsoft abandoned .NET, the new framework was at least familiar, and you could still use C#. So that’s nice. But the boots-on-the-ground reality is more nuanced. And the differences, big and small, between older and newer frameworks can be confusing, with many unexpected blockers. Everything is similar … but also different. There are so many things to catch you up.

And I suspect this is a more pronounced issue for me than it might be for most. As I always try to stress, I’m not a professional developer. And I don’t spend all day every day on this work. So it sometimes takes me a bit to get up to speed.

Anyway. Here’s what I’ve been working on.

The basics

From a user interface perspective, .NETpad is not a complex app. There is a single main app window with four main areas from top to bottom: Tabs, menu, text box, and status bar. Then there are secondary interfaces in the form of dialog boxes and a settings interface.

I’ve mostly implemented these areas, which are controls, in XAML in the existing WPF version of .NETpad, though as I’ve pushed to figure out multiple documents and tabs, I’ve also experimented at great length with other ways of creating these UIs. Primarily in the form of dynamic C# code and via something called UserControl that segregates blocks of XAML code and its associated code-behind C# into separate objects (and files). Ultimately, I decided this was too much trouble, but I will continue forward with using dynamic C# code to create the contents of each tab.

And of course, I’m starting over with WinASDK/WinUI 3. At a high level, the basics are the same. I could use XAML to build out the user interface, as always. Or I could use more sophisticated but complex methods like those noted above to create at least some of these UIs dynamically so that I can one day accommodate multiple documents and tabs. It’s tempting to go the XAML route to start, because it’s simpler.

There’s just one problem. All of those things are implemented differently in WinASDK/WinUI 3. All of them.

The way you customize the title bar of the app window is different. The way you implement a menu system is different. The text box is perhaps the least different, but it is different. And there’s no status bar in WinASDK/WinUI 3, so I had to cobble together my own set of controls–basically a grid with text blocks–to make that UI. (I will get to settings later.)

The first hurdle, then, was to figure out these differences just so I could present the basic app user interface.

Basic app XAML

Fortunately, that wasn’t much of a hurdle. I just needed to map whatever WPF control syntax to the equivalent WASDK/WinUI 3 control syntax. For example, where WPF has a TabControl control that contains one or more TabItem controls, WASDK/WinUI 3 has a TabView control that contains one or more TabViewItem controls … and a few things WPF does not offer, like configurable TabStripHeader and TabStripFooter containers, and more, a key reason for the switch.

In XAML, then, the code would at least look similar and familiar. There would be a TabView control in the first row of the underlying Grid. A Grid in the second row for the MenuBar control and a Settings button on the far right. A TextBox control in the third row. And then a Grid in the fourth row representing the status bar that contains various TextBlock controls.

Simple. But this app is getting less simple. And so the ultimate form of this main app UI will be more complex and sophisticated. Most of it will be generated dynamically in C# because of the issues I’ve had with UserControls. And that means that the XAML for the main app window will be incredibly simple. Stripped of the extraneous, it looks like this:

<Window>
    <Grid>
        <TabView Name=”MyTabs” Grid.Row=”0″ />
            <TabView.TabStripHeader />
            <TabView.TabStripFooter />
        </TabView>
    </Grid>
</Window>

That’s it. The rest of the code is dynamically generated at runtime.

Why?

Document state management, my old nemesis—that’s why.

Each TabViewItem (tab) will be added dynamically at runtime in C#, including the first and only tab that the initial version of this app will support. Each TabViewItem has header and content areas, as with the WPF TabView control, and while the header is simple, and basically just a TextBlock that displays the document name, the content is complex. This area will include:

  • A full app menu system with top-level File, Edit, and View menus and a Settings gear button.
  • A Textbox control that contains the associated document
  • A full status bar with multiple Textblock controls for status information

I’m doing this dynamically and per-TabViewItem (tab) because it will make document state management easier. Reusing the same TextBox across multiple documents was unreliable. At least I couldn’t figure it out.

For now, of course, WinUIpad, as I think of this version of the app, only supports a single document. But I wanted to get ahead of the dynamic UI code now so that adding support for multiple documents and tabs will be easier. And so I came up with what I think is a good idea. And this one involves AI.

I knew going into this that I could cut a few corners by using AI. And I have to say, this is a fairly terrific way to use AI, specifically for this type of coding.

What I did was create a basic empty app and construct the user interface for a single tab–a TabViewItem, in WinUI 3/WASDK–using XAML, which I know pretty well by this point. This includes all the bits noted above, the full menu bar and the Settings button, the main text box, and the status bar, which is now a grid of TextBlock controls. And each of the Click() event handlers for all those controls. I eventually landed on a simple app that looks like this.

Then, I used GitHub Copilot to convert that XAML code to C#. Simple. You know, assuming the code is correct.

To find out, I created a second basic empty app. And instead of creating the UI in XAML, I left it empty, made a CreateGrid() method in MainWindow.xaml.cs and called that from the constructor so it would run when the app started. Then, I pasted the AI-generated C# code into GreateGrid(). After a single edit–the AI had made a mistake with the line of code that makes the Settings button background transparent–I compiled and ran the app. And it looks identical to the XAML version. Which was exactly what I had hoped for.

Nice.

The next step was to apply this code to the WinUIpad app project. This would require some work, and I had to reimplement the dynamic data binding code that makes this more modern version of the app manage application state as automatically as possible. And I am happy to say that I figured that all out on my own. So I now have a basic version of WinUIpad, with the full front-facing user interface, that can open a file, save a file, and create a new file, all while checking to see whether you want to save some unsaved work first, the latter via a standard system Command dialog.

First app and user settings

Then I started looking at some next steps, like implementing app settings, which thankfully works as it does in WPF. So I created a Settings interface and started building out some related features, like a UserSettings class and some UIs like the menu-based status bar and word wrap features, ahead of figuring out the app settings interface.

The UserSettings class currently has separate methods for loading basic app window metrics like width, height, position on screen, and so on, and its use of the system theme, and there are starter methods for font attributes and some other features. And then methods for saving these things when needed. This was mostly straightforward, as I had been working on a similar class with WPF. But the code one uses to access these system features is, so far, completely different from WPF.

The window metrics code, for example, is much more low-level and similar to classic Windows SDK code. Maybe it’s just me, but this WPF code for the window metrics is easy to read:

But this WASDK/WinUI 3 code for the same is completely different, requiring research, and requiring me to pass in an AppWindow reference that has to run even more obtuse required code first (as seen below the red line).

Welcome to WASDK/WinUI 3, where nothing is ever easy or obvious.

First steps on the settings UI

I hand-coded a XAML-based settings page for the recent WPF versions of .NETpad, that was faithful to the version in Notepad, and I was curious whether any of the WinUI 3 controls would introduce any changes or improvement. I knew going in that WinUI 3 supports the ToggleSwitch that WPF does not. But the rest of it was an open question.

As usual, I’ve started with a new side project, this time to create a WASDK/WinUI 3 version of the app’s setting UI in XAML. In this case, I don’t see a need to convert this to dynamic C#, as it’s a single UI that only needs to be implemented once. So it’s mostly straightforward.

With the WPF version of .NETpad, I couldn’t use the Expander control to create non-expanding Expander-like UIs, I had to fudge those types of settings with a StackPanel surrounded by a Border control. In Notepad, for example, the Font setting “bar” you see below is an Expander that, well, expands. But the Font and Word wrap settings do not.

So I was hoping and almost expecting that the WinUI 3 version of Expander supported this capability. But it does not. And so I am, for now at least, just fudging it again. This time using a Grid because it supports a border natively. But same effect.

I’m still working on the settings basic UI as I write this. And I’m not sure yet if I will toggle the display of this UI on/off like I did in .NETpad. But I will experiment and try to make it as normal/native as possible. This is what it looks like right now.

It’s a bit rough, but it will get there.

Looking ahead

WinUIpad is obviously in an incomplete state but I’m making progress. I’ve had to punt on some of the more complex topics, like commanding and how freaking different it is from WPF. But a basic to-do for WinUIpad looks like so.

  • Menu system. The menu is fully drawn/created, but most of the commands don’t do anything yet. So far, File > New, Open, Save, and Save as work, as do View > Status bar and Word wrap. So I have to figure out WASDK/WinUI 3 commanding to properly implement the other commands under File and all the commands under Edit. I also have to create a UI for the Find/Replace dialog.
  • Settings. I need to finish the settings UI, wire up all the settings in there, and figure out to display it (and then close it).
  • Theme/UI. Right now, the Windows 11 theme switching is crashing the app, but I’m sure I’ll fix that. And the basic control theming–especially in the tabs area–needs work. That will require some research but I will figure that out too.

So just three things. It’s almost done!

Kidding. But it’s getting there. I have classes for Document (document state management), File Operations, and User Settings that are all in pretty good shape. My dynamic TabViewItem creation code with data binding is in pretty good shape. And the basic UI is mostly there.

There’s always more to do, and when this is “done,” it will just be the basic app. The point of this is to get to multiple documents/tabs, and to some of the other more advanced features in Notepad, some of which I’d previously implemented to some degree in WPF.

I will also get this version of the app into GitHub soon, probably this week.

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