Wednesday, August 02, 2023

4 times I got "sherlocked" by Visual Studio

"Sherlocked" - But, not in relation to the detective or associated fandoms.

Benedict Cumberbatch as Sherlock Holmes with a line across the image

It's the name used when functionality that was provided by an app or extension is incorporated into the OS or program running the extension. (ref1, ref2)


Here are 4 times that tools and extensions I've built to make it easier to work with Visual Studio have been "sherlocked".


1. UWP Design Time Data

Back in the day (prior to version 16.7 of Visual Studio), there was no way to see data-bound values in the designer of UWP apps. So I made a NuGet package that made it so you could. 
My approach was only ever intended as an interim solution as this functionality had been promised. I just got fed up of waiting.
Sadly, neither WinUI3 nor MAUI has Visual Designers, and so the relevance of all this is now moot.


2. Collapse usings on file open - part of Collapse Comments

Collapse Comments started out as an extension that only operated on comments. Over time, and thanks to feedback, some functionality was added that related to working with using directives too. This included the ability to collapse them when a file was opened.

Options for Collapse Comments extension

Then, in April 2022, this capability was also added to Roslyn.

Options Windows showing the Advanced Option to 'Collapse usings on file open'

I started working on the extension in 2018; an official request was made (by someone else) to have the functionality in Visual Studio in 202 (apparently JetBrains Rider already did this), then in 2022, VS did it too.
Someone on the Roslyn team reached out to let me know they were making the change. Which was nice.
The extension still exists as all the other functionality is unique and not built into VS--yet.

This is an encouragement that I am making valuable things with much broader potential reach. Note to self: work on marketing more.


3. Solution File Diff

Wanting to compare two files is a common task but something that was built-into Visual Studio prior to version 17.7 preview 2. My solution was often buggy so that this now exists is much better :)

If you're not yet using that version of Visual Studio (or above), you could also try FileDiffer.


4. Always Include

This was an experimental tool I created before C# has global and implicit usings. Whenever you opened a C# file, it would ensure that the using directives at the top of the file included a set of namespaces that you could configure.

Global and implicit usings make this almost entirely redundant now. However, I'm thinking of applying something similar to XAML files to apply a consistent set of XML namespace aliases to all files. - Let me know if this interest you too.


In addition to the above, I still have lots of extensions in the marketplace that provide other functionality that Visual Studio doesn't. Yet.....?




Saturday, July 29, 2023

Why does writing XAML have to be so slow?

This article is a part of the .NET MAUI UI July calendar—a month-long list of content around .NET MAUI from the developer community, curated by Matt Goldman.


There are many potential criticisms of XAML. Some people want to abandon it entirely and just use C# to create their UIs. I think that introduces other issues (that I'll expand on in a future blog post), but it also doesn't do anything for the people who like working with XAML and/or already have a lot of it, and for whom completely rewriting that code isn't an option.

Rather than write XAML off, or sit and complain, I'm interested in different ways of writing XAML that address some of the criticisms and in providing tools to make it easier.

This post is about one such new tool. I was excited to try it out and have been impressed by the difference it's made to my coding (once I'd gotten used to working in a different way).

Firstly, two pieces of background:

1. About 20 years ago, I was involved in hiring a web developer. (Obviously, web development has changed massively since then, but this story is still relevant.) One of the people we interviewed was really keen on pointing out how they thought it was important that they wrote everything by hand and didn't use an IDE with any tooling that made writing code easier. I don't agree with this attitude, and that's probably part of the reason I still remember the conversation (especially given how bad at remembering other things.) Yes, it's great to have full knowledge of a topic and be able to do something without assistance, but that assistance may save valuable time. If you have someone with deep or expert knowledge, isn't it better to have them focus on the tasks that use that knowledge rather than simple tasks that could be automated or accelerated?

2. Reading one of the many threads about developer frustration with the lack of tooling for WinUI3, I was prompted to think again about the Toolbox inside Visual Studio. Someone was complaining that the Toolbox isn't populated for WinUI3 projects. Having not used a drag-and-drop interface designer for many years, I'd only really thought about the Toolbox as a place to store code snippets. What if it could be useful for writing code directly in the editor too?


This is the Toolbox window (initialized within a .NET MAUI project) - it has groups (Controls, Layouts, Cells, and General) and items within each group.

The Toolbox window showing groups and items

That it's also possible to add arbitrary pieces of code (AKA snippets) into the toolbox made me think about the other snippets that are supported by Visual Studio.

The Code Snippet Manager window filtered to the XAML Language

These two types of "snippets" got me thinking:

  • Snippets in the toolbox are visual (and so more easily discoverable) but limited in functionality.
  • "Code snippets" have more functionality but aren't visible/discoverable.

What if there was a way to combine the two?

Before I continue, I should probably point out something many developers aren't aware of. You can use the items in the Toolbox with the XAML editor? (or any editor window.)

  • You can drag an item onto the editor, and it will add the XAML for the control at the point where you drop the item.
  • If you double-click on an item and it will add that same XAML wherever the cursor is.

🤯

Give it a try:

Open a new .NET MAUI project and drag a Button onto the editor. You'll see it adds the following:

<Button Text="" />

Or, double-click on the ListView and see it adds the following:

<ListView><ListView.ItemTemplate><DataTemplate></DataTemplate></ListView.ItemTemplate></ListView>

That's good, but it puts the cursor after the closing element. Not if you then want to add content to the DataTemplate.


Notice also that the items in the Toolbox don't include some of the things you're likely to use most in a .NET MAUI codebase. I suspect that this list is actually from the historic Xamarin.Forms functionality still in the underlying code base.


Perhaps I can do something "better"?


Introducing  Pro XAML Toolbox 

It's only one window, but here it is in dark and light themes.

Light and dark theme versions of the Pro XAML Toolbox inside Visual Studio

Ok, it doesn't look like much, but let me explain. [prefer to watch rather than read? - see this video]

It's an intended replacement for the built-in Toolbox when it comes to working with XAML in a .NET MAUI project.

The main goal is to get boilerplate code written faster. This can then be modified as necessary for the requirements of an individual app.


Boilerplate code is often challenging to work with, and different approaches are taken to remove or work around it. I'm not able to change the language, so it's not needed, and for XAML, there isn't an easy way to use code generation or compiler trickery to make it unnecessary. So, I've chosen to try and make it so that there's less need to type it yourself.


Let's look at a couple of examples.

Example 1 - A login screen

Imagine you wanted to create a login screen like this: It has an image at the top, two input fields for the username and password (each with a label above), one button to "sign in", and one for if the person has forgotten their password.

mockup of a login screen, showing: image placeholder, 2 labels followed by text fields and 2 buttons

If you're familiar with .NET MAUI and writing XAML this probably doesn't look too complicated to implement. You're right. It shouldn't be hard to implement this. You could create this quite quickly and without too much thought.

However, it's even easier and faster to create the basic scaffolding of this UI with the Pro XAML Toolbox.

All you need to do is set the cursor in the editor and then double-click on the appropriate items in turn.

That's: VerticalStackLayout > Image > Label > Entry > Label > Entry > HorizontalStackLayout > Button > Button

So, nine items double-clicked, and it produces all this code (here shown formatted):

<VerticalStackLayout>
  <Image Source="PATH-TO-IMAGE" />
  <Label SemanticProperties.HeadingLevel="Level1" Text="CHANGEME" />
  <Entry Placeholder="CHANGEME" Text="{Binding PropertyName}" />
  <Label SemanticProperties.HeadingLevel="Level1" Text="CHANGEME" />
  <Entry Placeholder="CHANGEME" Text="{Binding PropertyName}" />
  <HorizontalStackLayout>
    <Button
        Command="{Binding CommandName}"
        SemanticProperties.Hint="Add a description of what happens when clicked"
        Text="click me" />
    <Button
        Command="{Binding CommandName}"
        SemanticProperties.Hint="Add a description of what happens when clicked"
        Text="click me" />

  </HorizontalStackLayout>
</VerticalStackLayout>


If I started to create this myself and only used the keyboard, 9 keystrokes gest me this much code:

<VerticalStackLayout>
    <Image Source=""
</VerticalStackLayout>

I've clearly saved a lot of keystrokes and, therefore, time. Also, possibly, a bit of mental effort too.

It's not just the amount of code I've gained. I did it all without having to move the cursor. When I added an element likely to have child elements, the cursor was automatically positioned accordingly.

I've also got attributes for the properties I'm likely to need to set, and there are suitable default values with prompts to change them too.


Example 2 - A list with an item template

Here's another common scenario. We want a templated list, and each item in the list should contain an image with two pieces of related text beside it.

A placeholder mockup of a list. Each item in the list has an image with two pieces of text beside it

Again this is very simple to create yourself, but you shouldn't have to write it all by hand.

Let's set the cursor in the desired position and double-click some items in the Pro XAML Toolbox.

CollectionView > Grid > Image > VerticalStackLayout > Label > Label

That's six items that we've double-clicked, and it's provided all this code (again, line breaks and formatting have been added):

<CollectionView
  ItemsSource="{Binding PropertyName}"
  SelectionChangedCommand="{Binding CommandName}"
  SelectionMode="Single">
  <CollectionView.ItemTemplate>
    <DataTemplate>
      <Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto,*">
        <Image Source="PATH-TO-IMAGE" />
        <VerticalStackLayout>
          <Label SemanticProperties.HeadingLevel="Level1" Text="CHANGEME" />
          <Label SemanticProperties.HeadingLevel="Level1" Text="CHANGEME" />
        </VerticalStackLayout>
      </Grid>
    </DataTemplate>
   </CollectionView.ItemTemplate>
  <CollectionView.EmptyView>
    <ContentView>
      <StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
        <Label Text="Nothing to see here." />
      </StackLayout>
    </ContentView>
  </CollectionView.EmptyView>
</CollectionView>

Notice how the Grid is automatically put inside the DataTemplate and the Image inside the Grid.

I tried to type the above by hand and got this far with 6 keystrokes:

<CollectionView I

Intellisense helped a bit, but that's as far as I got. :(


But, you might point out, the generated code isn't finished!

No, but it is ready for you to make the specific tweaks you need. This could be removing the RowDefinitions from the Grid and specifying the Column that the VerticalStackLayout should be in. Both of which are trivial. And then you'll need to replace the placeholder text, but again that's easy. Yes, easier than typing the whole thing yourself


Your value is in producing finished software that provides value to those who use it.
Your value is not in the number of keystrokes you make or the amount of code you write.


Options/Configuration

But what if the generated code shown above isn't to your liking or preference? - You can configure it.

close up of the available options

Prefer to use events rather than commands? It's an option.
Don't want to include common (or recommended) accessibility/semantic properties? You don't have to.
Want every element to have an 'x:Name'? You can.

And the options to change these while you work are always accessible (not hidden away in a separate place), so you can easily and quickly change them while working on a file.


If (and when) there's some magical tooling (AI?) that can automatically give you everything you need to create a desired UI, then great. I'll happily use it.

For now, and until then, we can write code and build software much faster by using tools that do the easy, generic, and standardizable bits for us.


No, it's not the same as having a visual designer (something I know many people want, but Microsoft aren't likely to provide any time soon), but it's much faster than writing all that code by hand!


My hope is that others will find this useful too.

  • It's not a panacea or a silver bullet.
  • You don't have to use it.
  • It's not perfect for everything - I still write XAML by hand as well as using this.
  • It doesn't remove the need for other tools. (I have other tools to generate code in different ways)
  • But it could be another tool in your (pardon the pun) toolbox to help you create high-quality software faster and more easily.


Please install it, try it out, and let me know your thoughts.

I've already created issues to track some of the things I'd like to add and would love for you to add your ideas too.

And yes, there is likely to be WinUI/UWP and WPF support coming soon if other people want it.



Monday, July 10, 2023

UI summary representation without a treeview?

I tried to start this discussion on Twitter & Fosstodon but didn't do a good job of describing things with limited words.

I'm trying to find examples of the summary representation of a UI (could be a web page or a native app) which don't use a treeview.

For instance, assuming you're reading this in a browser, open the developer tools (F12), and you'll see something like this in the Elements tab. All the triangles are expandable and collapse nodes. You can expand an entry to see its children. It's a basic "tree view" layout. 

Example of the homepage of this site in the Elements tab of the developer tools

Or, for an app, here's the Live Visual Tree from Visual Studio

Partial screenshot of the Live Visual Tree tool window in Visual Studio

and the Document Outline

partial screenshot of the Document Outline tool window

Or this from Figma:

partial screenshot from Figma.com


They're all tree views.

I'm looking for examples of alternative UI for representing all (or part) of a UI "tree".

Got any examples?

I'm most interested in examples intended for developers that are clear and easy to understand. Or, at least, explained. Not different for the sake of it, but that are trying to communicate something different or in a different way.


My thought process was triggered when someone told me this is the only way this can (and has) to be done but couldn't tell me why.  I'm also suspicious that this might be leaking the abstraction of the underlying data model when this might not always be the best or most suitable thing for the person viewing it.


The only real variation I can find is like this (from http://bioub.github.io/dom-visualizer/), but all that really does is flip the axis.

screenshot of http://bioub.github.io/dom-visualizer/


Before I spend time exploring different options, I'd like to know why "everyone" does it the same way or if others have tried doing different things and what they learned from the process.

Know of anything?



Saturday, June 24, 2023

Code therapy (AKA: Lessons from a "mental health" Hack Day)

I'm halfway through my drive to the event and have stopped at a well-known coffee chain. While I wait for my drink, I see a poster on the "community noticeboard" advertising an art therapy course. It strikes me that there's a similarity between such events and how I'm planning to spend my day.


It starts a few months earlier when lamenting how depressing it can feel when work isn't satisfying.

Part of the reason I'm a software developer is that I like the job. I like the aspects that are creative problem-solving. 

I get pleasure from creating something that makes other people's lives better or easier. Even if only in a small way.

The satisfaction I get from shipping something new (even if only an update) energizes me.


But sometimes work is tough.

Sometimes it feels like days or weeks go by without real progress.

Sometimes a task that can bring joy and energy can suck!


Sometimes, the bad parts of the day can be offset by doing personal, fun projects in the evening.

But then there can be extended periods when life, family, and other responsibilities take priority.


So, we hatched a plan. What if we set aside a day to focus only on fun personal side projects? It doesn't matter what you work on as long as it makes you happy.


And for a few people, in certain circumstances, it can be a lifesaver.


Sitting on a bus heading into Cambridge, I'm excited about what today may bring.

I have a whole day (the room booking is for 8 hours) and can do whatever I want.

I've got quite an extensive list.

I know I won't even get halfway through it, but the prospect of completing any of these things that have been in the back of my mind, waiting for the right opportunity to get started, excites me.

This is going to be a great day.

It doesn't matter that only half a dozen people are expected.

Selfishly, this is all about me. It's my chance to do the things I want to do.

That I don't need to worry about the logistics of managing lots of other people is a blessing.


We booked a bigger room than we need and invited lots of other people in the hope it might benefit them too, but if no one else turns up, it's better for me as I'll have more time to focus on my projects.


The reason for booking a room somewhere is that it helps avoid the distractions of home. There's no Xbox or TV here to tempt my attention. There are no family members to knock on the door.

That this is weeks in coming means, I've primed myself to think that today is special. Days like this don't come around often, so I want to make the most of it.


That others have thought the same and turned up is an additional encouragement to make the most of this opportunity. Plus, we have the time and space to have niche, technical conversations that we don't get the chance to have elsewhere.



I knew my list was unrealistic. I knew that as I added more items to it, I will end up crossing off fewer things than I initially hoped.

But I also knew that doesn't matter.

Because, as time goes by, I am getting things done. The project that's been niggling away in the back of my mind for the last few months is slowly creaking out of my fingers, through the keyboard, and into my laptop.


And it works. In my mind, I always knew it would, but now I can prove it. I can see it running in front of me. 

It's far from finished. Far from something other people could use. Yet. But it's slowly taking shape.

I'm well beyond proving this concept. This is going to be a "real" project.


Can't stop for lunch.

No time.

Don't want to stop. 

Making this progress feels too good to interrupt.


That list I started writing last night (and added to this morning) no longer matters.

I know I'm not going to cross anything off it.

But the sub-list for the first thing I chose to work on has more items completed than not. And I know that more ticks are coming soon.


It's not a "proper" hackathon, but I start to get into a hackathon mindset.

As we start to think about when we'll have to leave, I decide I need to treat these last two hours as if I was preparing for an end-of-hack presentation.

How much can I get done before time runs out?

How can I best get this in a position to demonstrate it to others?


There's no competition. There are no prizes.

But I know that feedback from others will encourage me to keep working on this in the weeks ahead. (Whenever I get the opportunity.) The encouragement of others is likely to help me strive to make some opportunities.


The entry in my calendar for today says "destress hack." This is the placeholder I put in when we first booked the venue.

Officially we called it a "mental health hack." I assumed that "mental health" was more appropriate for communicating the idea as it's such a widely used term and--in my mind at least--more socially acceptable and supported.


Regardless of the name, this was unlike other hackathons. No theme or topic. No competition. Simply a challenge to myself.


But really, it was like the activity on the poster I saw this morning.

This was therapy.

It might not be art, but I feel better for it.

This has made me feel better about life. And work. And myself.