The WPF Files: A Few Successes (Premium)

The other day, I complained about how WPF (and UWP) make it difficult to do things that were easy in Windows Forms. But it’s not all bad. In fact, there are several niceties in both of these more modern frameworks that I really appreciate. I just wish Microsoft hadn’t dropped so much of what was good about WinForms.

So today, I’ll focus on the positive. This includes some of the improvements in WPF as well as some of my own mini-successes in porting .NETpad to this confusing (to me) environment. I’m glad I started with WinForms, and with Visual Basic, too, since that collective environment was at least familiar to me, and that collectively helped me get up and running more quickly than would have been the case had I started off with C#, which is a more powerful but complex language, and with WPF or UWP, which have their advantages but are likewise confusing. Again, to me.

And that’s the thing. As I promised early on in my work with .NETpad, I can’t teach you programming because I’m learning as I go myself. I make mistakes, and I have to backtrack when I head off in the wrong direction.

Case in point: I’ve struggled on separate occasions for what seems like weeks to get WPF to interact with the FontDialog and Font objects/classes from Windows Forms that provide simple and easy access to the system Font dialog and thus to the available fonts on the PC. This is a bit hard to explain, but I was able to get it (sort of) working when I created a C#/WPF/.NET Framework version of the app. But when I switched to .NET Core, Windows Forms—and thus its FontDialog and Font objects/classes—were no longer available.

So I experimented. As I did earlier when I started trying to manually implement something like a Task Dialog in Windows Forms, I eventually decided to roll my own Font dialog, frustrated that WPF didn’t provide its own modern equivalent and that the WinForms FontDialog was no longer available when using .NET Core.

Then a reader, davidl, jumped in to help in the comments of the previous article, explaining how you could make this work: This isn’t documented by Microsoft to my knowledge, but with a simple workaround, you can access Windows Forms and its objects and classes in a .NET Core-based Visual Studio project. Nice. And thanks again to that reader for the help.

Yesterday, I set out to yank out my own Font dialog and replace it with my homemade version. And what I arrived at was the same place I had been previously when I was still using the .NET Framework. It only sort-of works. That is, yes, I can pull up the Font dialog and then apply the font changes back to the app’s textbox (and then later save those settings when the app closes so they’re available at the next run). But pulling the font information from the text box and auto-configuring the Font dialog to use the right font name, style, and size was problematic. Because, again, WPF uses different objects to represent fonts than does WinForms, and those conversions are difficult.

Amidst this frustration, I had the makings of an epiphany, at least on a small scale: I had already created a fully-working Font dialog. It looks great, in my opinion, and more importantly, it works. It works great.

In fact, my own Font dialog does something that I think is important for these projects: It embraces, in this case, what makes WPF, well, WPF. It embraces the WPF-ness of WPF. And I think that’s the right approach, in general. The original version of .NETpad was created in Windows Forms and is very much a Windows Forms app, which is to say it is a classic Win32 app, just like Notepad, its inspiration, is. So maybe in “upgrading” or evolving .NETpad to WPF, I can embrace what makes WPF different, not fight it.

Part of what makes WPF different from WinForms, of course, is its use of XAML, a declarative way to describe user interface using an XML-based markup language. If you’re familiar with HTML (or XML), XAML makes tons of sense, and is very readable. But XAML is much more powerful than HTML. And it enables developers and designers to create scalable, dynamic, and adaptive user interfaces in ways that, frankly, weren’t just hard in WinForms. They are impossible.

XAML is a big conversation, but for the purposes of the .NETpad user interface, the way to think of it is that the main application window is a grid that consists of three rows: The menu bar, the text box, and the status bar. Each occupies the entire width of the app, no matter how it’s sized, and each sits on top of each other from top to bottom, with the menu bar and status bar being relatively fixed in size (though auto-sizing as resolution and scaling change) and the text box filling up the rest of the space.

The basic XAML for creating this user interface is very easy to understand. It looks like so.

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <Menu Grid.Row="0"></Menu>
    <TextBox Grid.Row="1" />
    <StatusBar Grid.Row="2"></StatusBar>
</Grid>

That’s it. Yes, there’s a lot more code in the actual XAML file, I’ve stripped out a bunch of properties, event handlers, and other code. But that’s the basic structure.

The Font dialog is more complex because it’s made up of multiple columns—for the font name, style, and size list boxes, mostly—-and rows. But XAML still makes it easy to create even a relatively complex UI, especially if it’s essentially made up of rectangles, like the Font dialog. As I noted in the comments to the previous article, I’ve updated this Font dialog since posting that article, and I really like where it’s landed. It now looks like so, and it auto-centers over the main application window.

Point being, unlike with WinForms, rolling your own dialog box or other window isn’t necessarily problematic with WPF. In fact, if you do it right, I feel that this will give your application a bit of character. A certain WPF-ness, if you will. Or maybe XAML-ness. (And for whatever it’s worth, I love how the UWP version of .NETpad looks, and that is very much about that app having a certain UWP-ness to it. That UI just works for me, where the WPF version is still very much a desktop app.)

That said, I did end up using the WinForms version of the Color dialog to implement .NETpad’s theming support. Recreating a Color dialog just seemed like too much work. So it still looks and works like it did in the WinForms versions of the app. And mapping old-school Color objects/properties to the WPF equivalents (Brush and SolidColorBrush, for the most part) was actually reasonably easy, unlike my font experiences.

Beyond those two stumbling blocks, I’m pretty happy with how much of .NETpad I’ve duplicated in WPF. And while I’m not quite done with it yet, printing is a huge improvement over WinForms: In fact, I was able to get basic printing support up and working in just four lines of code. I assume it was obvious how broken that was in WinForms, because it was clearly fixed in WPF.

File Open and Save/Save as works similarly to WinForms and was easy to implement. Cut, Copy, and Paste were automatic, and WPF even provides an automated way to gray out and enable those menu items as needed, which is nice. Text zoom works as it did in the WinForms version: TextBox doesn’t support a zoom mode, so I rolled my own the same way as before. User/app settings work mostly as they did before, and that all works perfectly now regardless.

The major remaining work, aside from a lot of code clean-up—I’ve written this quick and dirty—is my old nemesis: Find, Find Next/Find Previous, and Replace. But I have some ideas about a WPF-y way to implement those UIs using panels instead of floating dialogs. If I can get that to work, it will make this version of .NETpad even more WPF-like. I think I can do it.

Stepping back a bit, I think the biggest workflow change to creating this version of the app is that there is more coding—in both C# and XAML—because you can’t really work visually in the designer like you do in Windows Forms. It’s not just a performance thing, though the WPF (and UWP) designer is very slow. You just can’t do it. Instead, you construct the UI using code—declarative XAML code—and as you change properties and add event handlers, that code is added to the XAML too, so you get a feel for just writing it yourself. I’ve slipped into this mode of application creation somewhat seamlessly and I really like it.

Which is interesting, because one of my initial thoughts around writing about coding projects was demonstrating how little code you’d need to write in a traditional Windows Forms/VB app: It’s amazing how much functionality you get with drag-and-drop and filling out property values in the Properties box.

That’s valuable for beginners, for sure, and it was the appeal of the classic versions of Visual Basic as well. But there is something equally exciting about XAML and its more advanced capabilities. Making that leap requires work, and it’s more complicated than dragging controls onto a form surface, as before. But it’s also more sophisticated and is very satisfying in its own way.

Long story short, I sort of stumbled into it, but I feel like I did these things in the right order, for the most part. I’m glad I started with VB and Windows Forms. But I’m as glad to move past them and into the more sophisticated world of C#, WPF, and .NET Core.

Anyway, it’s nice to have a few successes, even small ones.

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