.NETpad 2025: Something Old, Something New (Premium)

I guess this shouldn't be surprising. But in the course of updating .NETpad for tabs, I've experienced challenges that I anticipated and several I did not. You can see this most clearly in the design of the DocumentTab class, which started off with certain assumptions about what I'd need and then evolved over time to address issues I didn't predict.

Most of those issues are related to what I think of as document state. Managing a single document in a single app window is relatively easy. Managing an unknowable number of documents in a single app window is more difficult, as is displaying each correctly in its own tab as the user navigates back and forth. It seems like there's always some new issue, waiting around the corner.

The most recent permutation of this type of problem is tied to the location of the text insertion cursor. That is, when you work in a text-based document, there's a little blinking I-beam ("|") cursor in the editor that indicates where text will go when you type. In the language of the Windows Presentation Foundation (WPF), that text insertion cursor is called the caret and you can use the TextBox control's CaretIndex property to get or set the position of the text insertion cursor (as I will continue to call it).

That sounds simple enough. But it is not.
CaretIndex vs. Line Number and Column
In the current version of .NETpad, the version I posted on GitHub late last year, I only use that CaretIndex property in two places. When the user invokes Go to line, the GoToCommand_Executed() event handler fires, and the first lines of code create a new instance of my GoToLineDialog custom dialog by passing it the line number where the text insertion cursor is, which is calculated using CaretIndex and the TextBox's GetLineIndexFromCharacterIndex() method.

That's all it takes to generate the line number shown in the dialog's text box.

CaretIndex is also used by the ChangePositionText() helper function in Backend.cs, which I call from the TextBox1_TextChanged() event handler. I've found in working on the new version of this app that this one place is not sufficient for this purpose, but the point for now is that as the user edits the text in the TextBox, three things happen:

The document name in the app's title bar will change to include a "▪️" character to indicate that it's unsaved.
The word/character count display in the status bar will be updated.
And ChangePositionText() will fire, calculating the Line and Column positions of that text insertion cursor so that those two values can also be displayed in the status bar (in the form of "Ln 0, Col 0" as per Notepad).

ChangePositionText() looks like so:

In my ape brain, I was thinking of the position of the text insertion cursor as being two values, a line number and a column, because that's how it's identified in the UI (which is based on that of Notepad). So in the original DocumentTab class, I included a LineNumber property because I...

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