Showing posts with label MAUI. Show all posts
Showing posts with label MAUI. Show all posts

Thursday, May 22, 2025

Improve .NET MAUI's AppThemeBinding?

 The AppThemeBinding in .NET MAUI is great. But wouldn't it be better if it required a lot less text?

<Label Text="default way (verbose)" TextColor="{AppThemeBinding Light={StaticResource Primary},Dark={StaticResource White}}" />  <Label Text="my way (shorter)" TextColor="{lightDark:Primary_White}" />

I'm a massive fan of code that is clear, expressive, and as short as possible without obscuring any important details.

The default syntax in the top AppThemeBinding example above is indicative of what you'd expect from regular XAML use. It does everything you need, the names are clear, and anyone familiar with XAML will not struggle to read it.

But, I look at it and think:

  • That's a lot of text
  • Why the repetition?
  • Why are so many braces needed? (I know why but wish they weren't.)
  • Can't there be a better, simpler way of telling both the compiler/framework and any developer looking at the code in the future what I want to happen?


As you can see from the picture above, I have a better way, and you can see an example of it there.


Of course, I don't have all possible color combinations pre-defined. I used a Source Generator to create what I wanted by including this attribute somewhere in my code.

[AppThemeColorResource(AppColors.Primary, AppColors.White)]

This example also uses my RapidXaml.CodeGen.Maui library to generate constants for the names of the color resources defined in the Resource Dictionary. I could use hard-coded strings for the names, but that risks other possible maintainability issues.


I also have other variants of the attribute, so I can also do things like this:

[AppThemeNamedColor(nameof(Colors.Aqua), nameof(Colors.HotPink))]

[AppThemeHexColor("#FF00FF", "#8B0057", "PinkOrPurple")]

[AppThemeNamedBrush(AppBrushes.SecondaryBrush, AppBrushes.Gray200Brush)]


Each generates a MarkupExtension that can be used in place of an AppThemeBinding and is named based on the names of the provided brushes or a specifically provided name. (As in the AppThemeHexColor example above.)



The above example uses 'lightDark' as the xmlns alias. I tried various naming styles and conventions for the alias and the generated MarkupExtension but currently prefer this best. I think it communicates the maximum amount of helpful information with the least amount of text.

Examples of other things I've experimented with include:
{ifLight:WhiteElseBlack}
{color:PrimayIfLight_PrimaryDarkIfDark}
{if:LightUseFF0000_DarkUseDD3333}
{appThemeBrush:Green_ifLightElse_DarkGreen}

What would you use?


If you see something like the above, you might be tempted to think, "Yes, it's shorter and easier to read, but what's the downside? I bet it's slower."

If you've never measured how long it actually takes to load different XAML content, that is a reasonable assumption.

Previously, I would have thought the same too. However, I recently built a test harness that makes it easy to measure how long it takes to load different XAML files, and the results shocked me.

I created two pages. Each contains 100 Labels (in a VerticalStackLayout). In one page, each label uses the AppThemeBinding as shown above. The other page uses my syntax. 

In a quick test, loading each page multiple times and in a variety of scenarios, the version of the page that used my syntax loaded 25% faster!


So, my version:

  • is shorter
  • is easier to read/understand
  • has exactly the same functionality
  • and is faster!!!


Now, tell me why you wouldn't want to do this?



NOTE: If you're looking to hire someone to help you build apps with .NET MAUI and you appreciate code that is easy to read, understand, and maintain. Get in touch as I'm looking for work.



Monday, May 05, 2025

19 Questions to ask before migrating a Xamarin app to .NET MAUI

Xamarin Logo, right pointing arrow, .NET MAUI logo
I got asked about helping rewrite a "legacy Xamarin-based mobile app to .NET MAUI". They'd already determined how long it would take, but had very few details about the app or the rewrite/migration.

To help anyone else in a similar situation, here are a few questions to ask (and get answered) to determine how much time/effort will be required in such a project.
  1. What's driving the rewrite?
  2. What's driving the time scale for the rewrite?
  3. When was the code written initially?
  4. Who has been maintaining and updating the app since it was originally written?
  5. What does the existing app do?
  6. How is the existing app built?
  7. How is the existing app distributed?
  8. How is the existing app tested?
  9. Does the initial code base use Xamarin.Forms or Xamarin Native?
  10. Which platforms (operating systems) does the existing app run on?
  11. Does the application have any specific customisation or variation in functionality when running on different devices or operating systems?
  12. What programming languages does the existing app use?
  13. How large is the existing app?
  14. What 3rd party controls or tools does the existing app use?
  15. How are 3rd party tools licensed?
  16. Do the 3rd party tools have equivalent support for .NET MAUI?
  17. What external systems (including back-ends, analytics, etc.) does the existing app connect to?
  18. Beyond getting the app to build and run with .NET MAUI, what other changes are planned and/or needed?
  19. What are the long-term plans for the app? (Who's going to maintain and update it after this rewrite?)


Obviously, the answers to many of these questions will prompt follow-ups to identify relevant specifics.

What did I miss?

Friday, April 11, 2025

Choosing a framework to build a native app on Windows with .NET

"Thinking face" surrounded by logos of different frameworks

By "Native," I mean not using web technologies, either as a remotely hosted website or bundled into a package that is installed and runs locally.

Let's get this out of the way first. 

There is no "best". 

There is only best for your current circumstances and requirements at the current time.


That said, how do you decide what might be best for your circumstance?

Each option has slightly different capabilities. It's essential that you know what capabilities you'll need before you start building. If you don't know what you need to build, it's impossible to say which is best for you. This may make the decision for you. 
Doing the work in advance to fully understand the requirements can save a lot of frustration and wasted time and effort if you discover you need something the framework can't do. 

So, second disclaimer out of the way, how do you decide which .NET framework to evaluate first? 

If the first thing you evaluate does all you need, it's probably fine to go with that. If not, try another.


Q1. Do you think you might ever need to run on more than just Windows?

If Yes - go to Q2.

If No, go to Q4.


Q2. Do you want the software to also run on the web?

If Yes - Evaluate UNO Platform first.

If No - go to Q3.


Q3. Are you primarily interested in building an app that runs on desktop, or on mobile devices?

If Desktop - Evaluate Avalonia first.

If Mobile - Evaluate .NET MAUI first.


Q4. Do you already have any existing apps built with WinForms, WPF, UWP, or WinUI?

If Yes - continue using that. (Unless it's UWP, then go to Q7.)

If No - go to Q5. 


Q5. Are you building a "traditional line-of-business" app or something that could be described as "forms over data"?

If Yes - go to Q6.

If No - go to Q7.


Q6. Are you happy to use/learn XAML?

If Yes - evaluate WPF first.

In No - evaluate WinForms first.


Q7. Do you need to support XBox devices, game pad controls, or ink-based input?

If Yes - evaluate UWP first.

If No - evaluate WinUI first.



Happy evaluating!



Yes:

  • The above is probably an oversimplification.
  • There may be many situations where you don't go with the first suggested option above.
  • It doesn't consider personal preference. But if you already have a preference, you should probably use that. (Assuming it can do all you need).
  • I haven't considered support for different programming languages. (But you're almost certainly using C#).


This isn't intended to be a definitive guide. Without knowing your exact requirements, existing skills, and preferences, I can't say for sure. 

I just wanted to share some simple questions that others have found helpful when overwhelmed by the options available.


Also: Joe made the above into a flow chart.



Wednesday, April 02, 2025

Never create an IValueConverter again?

tl;dr: If using WPF or MAUI you can easily create a MarkupExtension to allow the use of static methods with a Binding, instead of using an IValueConverter. If using UWP or WinUI, you can do this with `x:Bind`.


An `IValue Converter` is a way to modify a value that is provided via a binding. I rarely use them, but others use them frequently and find the experience to be less than ideal.

I stopped using them a long time ago (while still using Silverlight) because they had a significant and noticeable performance impact. The performance impact today isn't as noticeable, but I haven't gone back.

By not using them, I also realised that they make the code easier to test. The logic I was performing in the converter (the way the docs and conventions of the time encouraged) actually made more sense in the ViewModel. When the logic is all in the ViewModel I only have to test that. I don't need to have tests that run the app and manipulate the UI to verify the internal logic.  (Yes, I test my MVVM code, and still have separate tests for UI verification--but not the internal application logic.)

That's me, but there are people who do create ValueConverters and don't feel happy about it.

There are two complaints that I hear frequently:

  1. The syntax is verbose.
  2. The need to create and initialize extra types seems unnecessary when all that is really needed is a static function.
This isn't such an issue for anyone using WinUI as that includes the `x:Bind` MarkupExtension which already supports the ability to call static functions as part of a binding.

So, if you had this class:

public static class Converter
{
    public static string MakeUpperCase(string input)
    {
        return input.ToUpper();
    }
    
    // .. other functions
}


You could apply the function as part of the binding like this:

<TextBlock
    Text="{x:Bind utils:Converter.MakeUpperCase(VM.Message)}" />


Yes, I'm using a trivial example throughout so as not to get caught up in the complexities of what the conversion function does and can instead focus on how it is used.


That's all well and good for WinUI code, but what if you're using .NET MAUI or WPF, where there is no x:Bind support?


Well, if what you want is the ability to provide a static function as part of a binding, why not create a MarkupExtension that does that? The X in XAML serves as a reminder of using something intended to be eXtended. Plus, this is software. If using a framework that doesn't provide the desired functionality, unless there's something preventing it, you can add it yourself.


So, why not create a MarkupExtension that behaves like a binding but also accepts a static function and automatically applies that to the value that is used?
It seems so obvious that I can't imagine why everyone isn't already doing this.

In this example, I've called by MarkupExtension "BossBinding" and it can be used like this:

<Label Text="{rx:BossBinding Message,
             Converter={x:Static utils:Converter.MakeUpperCase}}"
     />

This is from a .NET MAUI app. 
In all other ways, the BossBinding works and can be used like a regular Binding, but the Converter property takes a static function. 

To make it as flexible as a ValueConverter, it requires a slightly more complex signature, but the contents of the function is what would go in the `Convert` function of a class that implements `IValueConverter` so it doesn't feel that complicated.

public static class Converter
{
    public static Func<object, object> MakeUpperCase => (input) =>
    {
        if (input is string str)
        {
            return str.ToUpper();
        }
        return input;
    };

    // other functions
}


If wanting to be stricter about the types used in the conversion, a version of the static function and the property of the MarkupExtension could use types other than `object`.

To make this work for both .NET MAUI and WPF, it was necessary to have different implementations of the `ProvideValue` function. This was due to the differences between the two frameworks and the way they support bindings internally.

The XAML still ends up being the same.
For example, here's a snippet from a WPF app that does a similar thing to the above, but also uses a static method that accepts a parameter to set the text color based on the bound value.

<TextBlock 
    Text="{rx:BossBinding Path=Message,
             Converter={x:Static utils:Converter.MakeUpperCase}}"
    Foreground="{rx:BossBinding Path=Message,
       ConverterWithParameter={x:Static utils:Converter.ChangeColor},
       ConverterParameter=True}"
    />


The conversion function here is again very generic, matching what is done with an IValueConverter.
The code is also somewhat arbitrary and was created primarily as a quick way to demonstrate that this can work with parameters and return types other than strings.

public static Func<object, object, object> ChangeColor =>
(input, parameter) =>
{
     if (input is string str
         && parameter is string parameterAsString)
    {
        if (bool.TryParse(parameterAsString,
                 out bool parameterAsBool)
             && parameterAsBool)
        {
            switch (str.Length % 3)
            {
                case 0: return Colors.Blue;
                case 1: return Colors.Red;
                case 2: return Colors.Green;
            }
        }
    }

    return Colors.Black;
};



That solves the second problem mentioned at the start, but what about the first (syntax verbosity)?
Maybe that's something ENAMEL can help with..



Am I going to use something like I've shown above regularly in future? 
Maybe. I rarely use ValueConverters, so probably not.
It solves the problem of needing to create and instantiate custom types when all that's needed is a static function, but I still think it requires too much text in the XAML file.
Still, it's an option for anyone who prefers it. We don't all have to write code the same way, and there may be good reasons to sometimes need this.

If and when I do need to use a value converter, I prefer the automatic generation of MarkupExtensions based on the class implementing IValueConverter. I find it makes the required XAML much shorter and clearer. 

It means that instead of having to write this in the XAML file:

<Label Text="{Binding Message,
             Converter={StaticResource MakeUpperCaseConverter}}" />

I can write this:

<Label Text="{conv:MakeUpperCase Message}" />


But that's probably another post for another day.



I appreciate being reminded that there are simple ways to create something that solves a problem when you don't like what comes out of the box.


What I really reject is the idea that someone should complain about a limitation of a framework (which can never do everything that everyone might want or need) when there are simple solutions that any developer should be able to write themselves. I'm almost surprised that this is a situation where developers don't want to write code to solve a problem they're facing. Writing more code as the first solution is frequently something that developers need to be stopped from doing.



Friday, March 21, 2025

The state (& future?) of XAML - A summary of a summary

Last week I gave a talk to a room full of .NET MAUI developers about "Rethinking UI Code".

The talks at the conference weren't recorded so I wrote up some of the key details for anyone not there but interested. 

That write-up became quite long, so here's the very short version (because I know you're busy):

  • Everyone agrees that XAML has issues but loads of people still use it anyway.
  • There are ways to make XAML much nicer to work with, but few realize this.
  • Many of these improvements can be made by treating XAML like you would any other programming language.
  • C# probably isn't the solution you want unless you want to rewrite everything you already have.
  • I have lots of tools that can generate code and make XAML easier to work with.
  • I've created a prototype of a language (I'm currently calling ENAMEL) that produces XAML and so sits on top of existing tools and toolchains. This language helps address many criticisms of working with XAML.
  • I've done this as a way to encourage further discussion about what's possible and what the future might hold. (Not because I have answers. But because I have lots and lots of questions.) 


Now that you're intrigued, you can go and read the full version here or as a series on LinkedIn.


My talk at MAUI Day in London

For most developers working with MAUI (or WPF, or WinUI, or UWP?), creating the UI means using XAML. I've probably spent more time thinking about how this could be better than anyone--not a boast, and I wish this wasn't the case--so it was a privilege to share my thoughts with an audience who uses this technology every day.

With MAUI.. so productive (it's an art) you know you're good when you can even do it with XAML
Yes, I included multiple Taylor Swift references in my slides. What of it?

This was originally posted on LinkedIn as a 1, 2, 3, 4, 5 part series. The actual talk was only 3 sections, but writing it up in 5 parts felt more appropriate.


The following is a brief summary of the talk (and without music, memes, most of the 116 slides, some of the demos, lots of energy, and only a few things being thrown.) That's the thing about in-person events. They're not the same as blog posts or recordings.



Part 1 - If XAML is bad, why is no one doing more than "just" complaining?


XAML is the default option for defining UIs in MAUI (and WinUI, WPF, & UWP) yet everyone seems to agree that XAML is far from great. It can be verbose, hard to read, hard to understand, and hard to maintain.

Lots of people complain about it, but no one does anything about it.*


If it's so bad as to be worth repeatedly complaining about:

  • Maybe the solutions are so obvious to everyone else that it doesn't even need saying. But, if that's the case, why does everyone: complain, write objectively bad (I said "poopy" in my talk) code, and write code that looks like it could have been written 18+ years ago?
  • Maybe the complaints aren't real; people just like complaining, and XAML got the short straw when it came to choosing what everyone should moan about. But that can't be the case, as it is objectively bad.
  • Maybe what I see as bad is "good enough" for everyone else. But if that's the case, why all the complaints?

Surely I can't be the only one who sees the issues and has thought about doing things differently?

If that's the case, it's a very scary thought.


XAML has been used by hundreds of thousands of people since it came out in 2006 (for building WPF apps) and little has changed since then:
  • The books from that time are still mostly relevant.
  • The examples from that time are still mostly relevant.
  • The way it is taught has not changed since that time.

Are there other languages that are actively encouraged to be used and have seen so little development in almost 20 years?

Imagine trying to use a 19-year-old book on C# today!


It's not just that there are no new versions, it's that the way we think about it hasn't changed. When every other aspect of technology is evolving and being updated at a great pace, why has something that we all know to be bad not been given any consideration to how it could even be used in better ways?


How do people justify choosing to use this technology today?

If an employee or co-worker told me, "We're going to use X technology, we know it's not great, and we make fun of how bad it is, but we're going to use it anyway." it would raise some serious red flags:
  • Why are you using it?
  • What are the alternatives?
  • Are there ways it can be used that address some of the problems?
  • What other decisions have you made with the same justification?
  • Why is this acceptable?
Developers are supposed to be smart people. Does this seem smart?


*Some people (probably between 6 and 12% of MAUI developers) have decided to abandon XAML and use C# instead. 

The argument goes something along the lines of "XAML is bad, but I like C#; why don't I [or we] just use C# for everything."

It's a reasonable argument and certainly possible, but I don't think it's the silver bullet that some claim:
  • Most UIs defined in C# (all examples I've seen) adopt the same structures, patterns, and mistakes seen in XAML files. The code is basically the same as the equivalent XAML. Just because it's a different syntax, doesn't make it better.
  • Claims of a "fluent interface" are exaggerated due to the use of method chaining for some functionality. In reality, the need to combine setting some properties directly, setting some properties via chained methods with the property name, setting some properties via a chained method with a different name, and having to rely on massively overloaded fallbacks for some functionality means you can only really be fluent if you're very familiar with all the options and which to use when.
  • That C# is "easier" and has "helpers" available ignores the fact that XAML can be written to be "easier" to read and helpers can be created to work with it too.
  • Claims that the use of C# creates a faster application than using XAML, ignores the benefits, of using compiled XAML. More importantly, the performance of code is often down to the way it's written and used, rather than an underlying benefit. I've not seen these performance claims backed up with real data to show the benefit, and people arguing this position don't seem as concerned with optimizing every aspect of their code for performance. If performance is a problem or is critical to an application, then, of course, you should do what's necessary to produce software that performs adequately. If you claim to make a decision for performance reasons but don't measure performance or optimize for performance consistently, I don't consider it a good argument.
  • That C# needs to use fewer "magic strings" ignores that there are ways to remove the need to use any kind of "magic value" in most XAML scenarios and that most C# code (including demos and reference examples) is littered with "magic numbers".
  • One argument for using XAML is that it encourages the separation of logic from presentation code. Though it's possible to maintain this separation when using C# for everything, it can lead to more complex code, and the effort required to separate things means it is rarely done.
  • Even if everyone did decide to switch to using C#, does that mean they need to rewrite all their existing XAML? Would that be the best use of people's time? Would everyone be able to do this confidently because they have good UI test coverage and so could avoid introducing any unintended changes while doing the rewrite? - No!
  • And if using a single language for everything is so great and such a wonderful solution, why don't we see this elsewhere on other platforms and with other technologies? For the people switching to Blazor because they don't like XAML, they still use HTML and C#. Why is almost all web development done with at least three languages (HTML, JS, & CSS)?

I'm not going to stop anyone from using C# for their UIs. In fact, I use it for some things myself. When there is logic required in determining what the UI should look like or be comprised of, using C# can be much more productive and performant than trying to do everything in XAML.

There was never meant to be a decision between using XAML or C#. It has always been the case that you get the best results when you use both. XAML and C# work together.


Of course, if the tools and languages you're using to create your app UIs are as good as you need and can imagine, and you're super productive, and couldn't possibly get any better, keep doing what you're doing.

I've yet to meet anyone where this is the case, and there was no one at the conference who admitted to this situation either.


I was worried I was "bringing sand to the beach" to present these ideas to a room full of experts and highly experienced individuals who work with XAML on a regular basis.

Sadly, I'm still to find others who are not writing the same bad XAML as everyone else.



Part 2 - How XAML can be written in more maintainable and developer friendly way.



Aside: What does good XAML look like? - If you've never thought about it before, take a minute to consider this. Barely anyone has a good idea.



It's not "just XAML" or "only a markup language".

What we put (type) in files that become part of an application and which we later need to read and possibly edit all have a lot in common. Yes, C# and XAML look very different and are typically used for different tasks and in different ways, but there are some truths that hold for both (or all) programming languages.



For any "code" that we'll have to maintain, we want it to be:

  • Easy to write
  • Easy to read (and understand)
  • Consistent
  • Well formatted
  • Unambiguous
  • As concise as possible without inhibiting understanding
  • Without unnecessary duplication or redundancy

There's nothing controversial in that list. Is there?

Nothing you'd disagree with? - If there is, please leave a comment.



But, does that sound like most XAML you've ever seen?

I doubt it. And I think that's a problem.



If you think about it for a moment you'll start to question this too.



Above I got you to think about 'what good XAML looks like'. Almost everyone I've ever asked this question doesn't have an answer. The couple that did, said "it should be well formatted."

If formatting is the standard for quality, I think we have a big problem.

And, as people do want more maintainable XAML, we have a big problem.



So, what can we do?



I think consistent formatting is just the start.

Here are some other things to do:

  • [Only] include useful, relevant comments.
  • Order content within the file so that it matches the order of items being output.
  • Structure the use of files within directories in a consistent manner.
  • Avoid miscellaneous files that become a "dumping ground" for assorted functionality.
  • Follow the Single Responsibility Principle. Give elements in the XAML a single task and, therefore, a single reason to need changing.
  • Simplify layout structures within files.
  • Avoid using unnecessary elements.
  • Avoid setting redundant or duplicate property values. 
  • Avoid specifying properties with their default values (unless there's a good reason and you add an appropriate comment to explain it to people looking at the code in the future .)
  • Don't repeatedly define the same values/items.
  • Make use of language features.
  • Use inheritance where appropriate.
  • Don't use "magic strings"
  • Don't use "magic numbers"
  • Encapsulated repeated logic.
  • Use language features (such as a custom MarkupExtension) to show relationships between values and make those relationships clearer.
  • Avoid repetition of text. (So you only need to change it once, in one place.)
  • Use semantically meaningful names that show where and when to use something. (Not what it does or looks like.)
  • Don't use variations of "Hungarian Notation" when naming UI elements or resources.
  • Use inheritance to simplify code. (There are tools that can help with this.)
  • Create new types that combine existing ones that are repeatedly used together.
  • Create new controls to isolate stand-alone pieces of logic.

There is more detail on the above can be found in the MAUI - Focus on XAML workshop. (Sorry that this means giving you homework, but I'm not sure it's in anyone's benefit to repeat that here.)



Applying the above means that it's easy to go from code like this:

Complex and deeply nested XAML code
This code produces the screen in the screenshot.

To something much shorter, clearer, and easier to maintain, while still producing the same output (the image in the top right):


A small amount of meaningful XAML that is easy to maintain - and produces the same UI as the last example
Yes, this produces the same as the above, shown in the inset screenshot.


 
Additionally, as there are often multiple ways of achieving the same results, why not use some of those things to reduce the nesting, verbosity, and complexity of XAML with something much shorter and clearer.

For example, why not use an Attached Property to add a gesture recognizer? Like this:

3 highlighted examples of different ways of achieving the same result
3 ways of triggering an event or command when a button is tapped.


Or something similar for adding behaviours to a control:

eight lines of code or one?
2 ways of triggering a command when the button is "Clicked"

Or maybe you want an easier way to specify the values to pick from:

Give a picker three options with 7 lines of code, or as a single property taking a comma separated list?
Again, both code snippets produce the same UI.


Have a look through the above examples. Take a moment to get past the shock of seeing XAML that isn't as unnecessarily verbose as you're used to.

Which is easier to read and understand?

Which is quicker to type?

Which would you rather maintain?



Why doesn't everyone write code like the above? Each attached property is only a few lines of C#, and yet it makes working with the XAML massively more pleasant.



We're not limited to attached properties.

Creating custom Markup Extensions can greatly reduce the amount of text needed to apply a conversion to a binding and also make the text clearer. 

For example, the following shows four versions of a string being displayed. The first is without any conversion, the following examples show different ways of using a converter.
Text="{conv: AsUpperCase SomeTextProperty}"
Isn't it nice when there are fewer words needed and those words are all necessary and helpful!

Plus, creating the extension only required adding an attribute to an existing converter. How simple is that?
AsMarkupExtensionAttribute !


Using XML namespaces and carefully choosing names can make code embarrassingly easy to read and understand. Even if you're not familiar with XAML or the code base, is there any confusion about what the following would do?

Lots of short, meaningful pieces of code -- like no one is used to seeing in XAML
Some people complain about the inclusion of XML namespace aliases, I prefer to use them in ways that provide clarity.


Or, maybe we use a markup extension to reduce the creation of a complex item with properties (StartPoint, EndPoint, and Offset) that I can't and don't want to have to remember:

Two ways of creating a horizontal gradient. One with 7 lines of code, the other with only 1.
Two ways of creating a horizontal gradient. One with 7 lines of code, the other with only 1.
Yes, both code snippets produce the same output (as seen in the top right)




XAML doesn't have to be verbose and complex, it comes with ways to use it that are significantly easier to maintain and (relatively) a pleasure to work with.

What is stopping everyone (anyone?) from writing XAML like the simpler versions above? I'm not aware of anything. - If you have an answer, please share it.



Part 3 - Creating XAML doesn't need as much typing as you might think


The tools we get "out of the box" for working with XAML in MAUI basically come down to creating a sparsely populated application and the need to type everything by hand (with a bit of intellisense).

I've created some tools (and experiments) that make getting from nothing to a basic project architecture much easier, and from an empty file to useful appropriate XAML content much faster.



The MAUI App Accelerator is a Visual Studio extension that enables the creation of MAUI apps through a wizard-style interface. (Remember I said I like GUIs.)

It allows you to specify :
  1. Which version of .NET to use (You should be using .NET 9 for your MAUI apps!)
  2. Whether you want to use XAML+MVVM, XAML+CodeBehind, or C# to create your UI
  3. If you want to use the Shell, and what sort of navigation style (tabs or flyouts) to use
  4. How many pages you want in the app, what they should be called, and what (if any) default content they should include
  5. What features, functionality, libraries, and dependencies should also be included in the app
It then produces an application with all these options, all correctly configured and with dependencies and initialization already done. 

It doesn't sound like the most revolutionary thing in the world, but it can definitely save minutes and maybe even hours to go from nothing to a complex working application full of correctly configured and useful dependencies.


That's great for new apps, but what about extending existing apps?

Well, version 2.0 is "coming very soon", and among numerous other improvements is the ability to use the same wizard to add new pages and features. Of course, it does this with the same level of integration into the existing app, so it automatically registers dependencies, adds resources, and correctly configures and initializes all it adds.

Screenshot showing the new "Add page..." and "Add feature..." options
These new options can be a massive time saver


So, that's great, we can now build the basic structure of our application much faster, but what about getting the XAML we want inside the pages of the app?

I have two ideas to show on that subject.


First is the Pro XAML Toolbox. 

This is a variation on the default Toolbox, but it adds more useful and appropriate content to the page. Many options are configurable, and items can be dragged where desired or double-clicked to be added where the cursor is.
The Pro XAML Toolbox in action. Showing different elements being very quickly added by dragging and double-clicking on elements  in the toolbox
See how quickly a page can be filled with useful, appropriate XAML

While that allows the creation of XAML much faster than typing by hand, I still think there is a faster way.



For most data types in a ViewModel, it's possible to make a reasonable assumption about the UI controls that can be used to display and allow interaction with them.

When those assumptions are codified (in a configurable way--of course), then it's possible to generate the XAML corresponding to a particular ViewModel file.

My preferred way of implementing this is to simply drag the ViewModel file onto the View and have the XAML code be automagically added.

When doing this, the file is analysed, and appropriate elements are created depending on the types, their names and if they can be changed.

See below that:
  • A bool called IsRefreshing becomes bound to an ActivityIndicator.
  • An ObservableCollection<T> produces a CollectionView and the DataTemplate includes entries for each of the properties for the Type.
  • Commands cause buttons to be added to the XAML to trigger the invocation of the command.
  • etc...
Animated screen capture of a file being dragged onto a file and appropriate XAML being created
No steps were removed. It really is this fast

It's also possible to open the ViewModel, select some properties and choose "Copy as XAML" which you can paste wherever you want.



As with the Pro XAML Toolbox, this isn't going to always give you exactly what you need, but it is much quicker and easier to make small modifications to something that is almost right than it is to type the entire thing from scratch.



This isn't all just me showing off. I'd much rather that someone else had created the above (and shown how XAML can be made more maintainable.)

The above is to show that other things are possible.

Given that this is possible, why has no one else done anything like this before? (There are a few command-line-based template options available, but nothing else with a GUI or as much flexibility. And nothing beyond that.)




Ok, we've seen that while everyone agrees that most XAML is bad, it doesn't have to be that way.  I've also shown that there are ways of writing XAML to make it much easier and more pleasurable to work with, and that it's possible to create tools to make working with XAML files easier.

Is this as far as we can go?

Is this as good as it can get?



Microsoft doesn't seem interested or motivated to consider any big changes. 

No one else is doing anything in this area.

That's not going to stop me.

Thanos:  "Fine. I'll do it myself."
Not that I want to be comparable to Thanos in other ways



Part 4 - What if we didn't write XAML?

If XAML has so many problems and it's taken this many years to identify and try and address them, maybe we should look for something new to replace it.

However, introducing a new language to replace XAML would have a number of challenges:

  • It would need to be able to work with existing XAML (& C#?) to avoid the need to rewrite all that already exists.
  • Many people would still assume the need to rewrite in the new option as the other option(s) would (eventually) go away.
  • Assuming that the new language also came from Microsoft, the number of things they need to support and maintain would be increased (they'd need to ensure all pre-existing things continue to work) and this extra requirement would slow down development/advancement in other areas.
  • What about all (sigh) the tools that already exist? Would they need replacing or updating?
  • It would require thorough documentation (which takes time and effort).
  • All the SEO goodness of existing docs, blogs, etc. would make it hard to find appropriate, up-to-date information about whatever is new.
  • Developing a new language is hard to get right.
  • Developing all the required integrations with developer pipelines and other tooling (there's more to MAUI than just XAML) is complex and would be a lot of effort.

That's a lot of reasons not to do it, or to not expect something anytime soon.


It's especially tricky as my expectation (based on 25+ years in the Microsoft/.NET developer ecosystem) is that developers are highly unlikely to pay for a solution that doesn't come from Redmond. Nor would there be a lot of participation in creating an open-source solution.


But, I'm channelling my inner Thanos right now, and I think I have a possible solution.

Come. Let me help you.
Is this too much Marvel?



Rather than replace what already exists (both code bases and toolchains), why not sit on top of that? 


I've created a rough specification and prototype of a new language that produces XAML.
The output XAML (& C#) can then be used just like the files you have and write today.

The intention is to define the UI in the new language which then produces XAML and everything continues to work as before. 
Tooling and IDE integrations quickly make this feel natural.


This way, everything that currently works will continue to work. New things are extras and on top.

  • By having a new language that can produce XAML (& C#) files that are used as the project system and developer tools currently expect, there isn't the time and effort needed to change what already exists. We can experiment and iterate faster on possible alternative solutions.
  • By producing files that are valid even if the experimental language goes away or you decide not to use it, there is little risk. You still have working code, and you're not stuck with something that needs to be rewritten in a way you can support and maintain going forward.
  • As it works on top of existing files, it can be used in whole or part within a project or a team. Just start using it for the files (pages/controls/dictionaries) that you want. It's entirely optional.
  • By treating XAML as acceptable input, it's also really easy to try it out. Just copy the existing XAML into the new file and start modifying it there. You can progressively switch to the new, simplified syntax and make use of new functionality a bit at a time. If there's anything that can't be done with the new language (or you don't know how) simply fall back to doing it with XAML.
  • By generating code at design time, it's possible to do things that hand-written XAML can't.

Added bonus: this could also work with WPF and WinUI. There is nothing here that is specific to MAUI.


So:
  • Low effort
  • Low risk
  • Big improvement


I think this is worth exploring further.



Because it's helpful to have a name to refer to things, I call it ENAMEL. (Experimental Native Application Markup Extension Language)

Here's a very basic teaser of it in action:

Video of Visual Studio. Enamel file is edited, causing the XAML file to be updated and a "previsualization" of the page reflecting that change.
An ENAMEL (.enml) file in use inside Visual Studio

The above animation shows 3 windows inside Visual Studio. 
  • On the left is an .enml file in an editor window. 
  • In the middle is the .xaml file produced from the ENAMEL. 
  • On the right is a design-time "pre-visualization" of what the page will [approximately] look like.
Yes, this is the default new page with some additional buttons at the bottom.

In the animation:

  1. A property (highlighted in pink) is uncommented in the ENAMEL and the file saved.
  2. This causes the XAML to be updated (yellow highlight) and that property added.
  3. This change is also reflected in the "pre-visualization" of the XAML. 


Aside 1: The highlighting of parts of the code was done with this extension. 


Aside 2: The "pre-visualizer" is a tool I previously built for myself to give me an approximation of what the rendered app will look like. It doesn't remove the need for running and testing the app on real devices but it increases my confidence that the XAML I have will produce the output I expect. While tools like Hot Reload and Live Preview are useful, the "pre-viz" helps me avoid the frustration and disappointment of compiling and launching the app to discover I've left something out or made a silly mistake. This isn't specific to ENAMEL.


I'm not going to show here the details of the ENAMEL language that I showed on the day.

I'm not doing this to be a tease. I will share more details soon.

I'm trying to avoid making the discussion about my specific implementation when I want it to be about the concept.



The point I'm trying to make is that once I identified that there was a way to create a simple experiment with alternatives, it was easy to produce something that let me try it out.



I admit that I was well-placed to produce such a seemingly polished proof-of-concept. I've built DSLs (Domain Specific Languages) before and have experience integrating with Visual Studio.

To get as far as I did took a total of less than two days effort to implement. (Not including time spent in advance thinking about rules/syntax for the language.) Most of the Visual Studio integration was cut and pasted from previous projects, and I spent less than an hour doing the simplest possible thing I could to get basic colorization (classification) of the code.

In reality, all it's doing is taking a multi-line string as input, parsing it and returning another string containing XAML. It's basic stuff that anyone with at least some basic C# experience could do. If it was a separate app or had a command line interface to turn one file into another it wouldn't seem so remarkable.



Forget my implementation. Is this a good idea?


How would you feel about using a new, powerful, yet simple language to define your UI?
And, that then gets turned into XAML and used when compiling your app?


I know there are much smarter people than me out there who may have much better ideas.


I'm not trying to say I have the solution.
I am trying to say that we need a solution; how about this as a starting point?


What do you think:
  • How can we make existing and future XAML easier to work with?
  • If it's another language, what should it be like?
  • If not another language, then what?


Part 5 - Now what? The future of writing XAML and me



So, now what?



On the day, I stated what thought the best and worst possible outcomes of my talk would be.



The best possible outcome would have been if multiple attendees could point out why I was wrong and explain why what we had at the moment was actually much better than I realized.

This would be the best option as only my time would have been wasted. 



The worst possible outcome would be if I'm right.

It's bad because it means everyone has been wrong. "Forever". And no one has pointed this out before. It's also bad because it probably means most people will want to wait for a solution from Microsoft and that's unlikely to come any time soon.



Ok, so this isn't life or death stuff, but it's what tens (hundreds?) of thousands of developers spend time on every day. If that time is being wasted and people are working more slowly because it's hard and frustrating to do what they want, I still think this is worth improving. How could that time better be used? What are we missing out on because of all the time lost to fighting "poopy" XAML?



Maybe there's a middle ground between my best and worst scenarios.



I'd love to continue to develop these tools and ideas. However, I'm currently in need of paid work, and what I get will determine how much time and energy I can spend to continue this.

  • In an ideal world, there's someone in need of my development skills and an interest in these tools so that I can continue to develop them in ways that become beneficial to that company/project(s) and the wider community.
  • Or maybe there's a company I can help build some software and this will leave me to continue developing these things in my own time.
  • Or, maybe there's a company somewhere that has seen my creativity, skills, and way of thinking, and has an opportunity for me to discover entirely new things to work on. (And I find that so exciting I forget all about XAML and someone else can lead the charge to make things better.)


I'm also torn because despite having worked with these technologies for so long, I'm wondering: if this is an ecosystem where no one else is even thinking that things could be better while admitting that they're bad, do I want to keep working with these technologies?

I have the tools (and now the language) I've always wanted to work with these technologies and build native (mobile & desktop) apps. Part of me would be happy to keep them around while I have side projects that benefit from them. If I get work in a different industry and no one is interested in taking them forward, it won't have been a complete waste of my time.




Don't Clap (for me)


I ended with the "DON'T CLAP" slide I have included above.

It's easy to treat clapping as the recognition of the end of something and then mentally switch to something else. I didn't (and don't) want me talking about this topic to be a temporary distraction or a momentary diversion only for everyone to go back to things as they were. I wanted (and still want) this to be the start of a discussion about how things can improve.

I don't have and can't provide all the answers. You're probably much smarter than me. I want to know your thoughts on this subject. Ok, you may still be taking in some of these ideas, but once you have thoughts, please share.



Yes, this is your prompt to leave a comment with your thoughts before you leave. 😃

If you don't want to (or can't) comment here, you can reach me via most social networks.