<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Tony Edwards</title>
    <description>A curation of learnings, musings and similarly captured day dreams.</description>
    <link>https://tonyedwardspz.co.uk</link>
    <atom:link href="https://tonyedwardspz.co.uk/feed.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>User Needs Mapping by Rich Allen</title>
        <description>&lt;p&gt;I took some time out of the office today, releshing the opportunity to read a good book in the sunshine.&lt;/p&gt;

&lt;p&gt;And it’s almost as good as the view!&lt;/p&gt;

&lt;p&gt;User needs are difficult to pin down, whether the individual is internal or external to the business. Sometimes they’re masked by complexity. Sometimes they’re hidden behind user pains. And sometimes. . . just sometimes. . . no one actually knows what they need. . . only what they want.&lt;/p&gt;

&lt;p&gt;All combined, they result in unaligned goals across a team/org, ill defined boundaries and responsibilities, and confusion between internal needs and the actual needs of the end user. (Developer experience is important. Honest boss!)&lt;/p&gt;

&lt;p&gt;Thankfully, Rich Allen is here to save the day!&lt;/p&gt;

&lt;p&gt;In User Needs Mapping, Rich draws from multiple Agile-esque processes to distill the core of User Needs Mapping. It gives you the language to talk about the issues to be solved with clients and the team around you, and breaks down the process step by step with really good illustrations to support the text.&lt;/p&gt;

&lt;p&gt;My favourite thing about this book is the examples. They’re as deep as they need to be, exceptionally well written, and not the usual. After reading a few books of this ilk, it’s nice to not see the same examples being regurgitated in an effort to draw new insights.&lt;/p&gt;

&lt;p&gt;Highly recommended 👍&lt;/p&gt;

&lt;p&gt;If User Needs Mapping is something you’ve been meaning to look deeper at, pick up a copy of this book and learn EVERYTHING you need to know to do the job.&lt;/p&gt;
</description>
        <pubDate>Mon, 20 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/user-needs-mapping-rich-allen/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/user-needs-mapping-rich-allen/</guid>
      </item>
    
      <item>
        <title>A quick guide to c# expressions in .net MAUI.</title>
        <description>&lt;p&gt;I’ve written more Boolean converters than I’d care to admit. Not complicated ones, either. They work, but a convertor is a lot of ceremony for something so small.&lt;/p&gt;

&lt;p&gt;C# expressions are coming to .NET MAUI in .NET 11, and they’re designed to remove a bunch of this sort of boilerplate. They let you write small C# expressions directly inside XAML attributes, which means conditions, calculations, formatting and simple event handling can live closer to the controls that use them.&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;VerticalStackLayout&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;IsVisible=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{!IsLoading}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;Button&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Save&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;IsEnabled=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{IsValid &amp;amp;&amp;amp; !IsSaving}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{$&apos;{FirstName} {LastName}&apos;}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is a fairly substantial change to the way we can work with XAML. It doesn’t mean view models, converters, commands or normal bindings are going away, and it certainly doesn’t mean every bit of application logic should now be squeezed into an XML attribute. What it does mean is that a lot of the tiny pieces of supporting code we write around XAML may no longer be necessary.&lt;/p&gt;

&lt;h2 id=&quot;what-are-c-expressions&quot;&gt;What are C# expressions?&lt;/h2&gt;

&lt;p&gt;C# expressions let you use C# syntax inside XAML attributes. That includes property access, Boolean conditions, arithmetic, string interpolation, null-coalescing, ternary expressions, method calls and small event-handler lambdas.&lt;/p&gt;

&lt;p&gt;The feature is being introduced as part of .NET MAUI in .NET 11 and is still experimental at the time of writing. Some of the syntax, behaviour and limitations may change before the final release, so this probably isn’t the moment to enthusiastically rewrite half a production application on a Friday afternoon.&lt;/p&gt;

&lt;p&gt;The interesting part is that these expressions aren’t simply strings being interpreted at runtime. They’re understood by the .NET MAUI XAML source generator, which can inspect an expression, work out which types and properties it uses, and generate the required C# or binding code at build time.&lt;/p&gt;

&lt;p&gt;That makes this more than shorter syntax. It gives the compiler a much better understanding of what the XAML is trying to do. It gives you less code to grep.&lt;/p&gt;

&lt;h2 id=&quot;why-is-this-happening&quot;&gt;Why is this happening?&lt;/h2&gt;

&lt;p&gt;XAML is very good at describing the structure of a user interface. It becomes less elegant when you need to add a small amount of presentation logic, particularly when that logic is too simple to deserve its own class or view-model property.&lt;/p&gt;

&lt;p&gt;Suppose you have an activity indicator that should be visible while data is loading, and some page content that should be visible when it isn’t. A fairly typical approach looks like this:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;ContentPage.Resources&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;toolkit:InvertedBoolConverter&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;x:Key=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;InvertedBoolConverter&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/ContentPage.Resources&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;ActivityIndicator&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;IsRunning=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding IsLoading}&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;IsVisible=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding IsLoading}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;VerticalStackLayout&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;IsVisible=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding IsLoading,
        Converter={StaticResource InvertedBoolConverter}}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Page content --&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;/VerticalStackLayout&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There’s nothing especially wrong with this. Converters are useful, particularly when transformation logic is shared across several views. In this case, though, we’ve introduced a converter, registered it as a resource and referenced it from the binding simply to invert a Boolean.&lt;/p&gt;

&lt;p&gt;With C# expressions, the same thing becomes:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;ActivityIndicator&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;IsRunning=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{IsLoading}&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;IsVisible=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{IsLoading}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;VerticalStackLayout&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;IsVisible=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{!IsLoading}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Page content --&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;/VerticalStackLayout&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The new version is shorter, but that isn’t the only benefit. The condition is right next to the element that uses it, and the intent is obvious without jumping around the project looking for a converter.&lt;/p&gt;

&lt;p&gt;A tiny bit of logic stays tiny.&lt;/p&gt;

&lt;h2 id=&quot;simple-property-bindings&quot;&gt;Simple property bindings&lt;/h2&gt;

&lt;p&gt;The most basic example is binding to a property.&lt;/p&gt;

&lt;h3 id=&quot;before&quot;&gt;Before&lt;/h3&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding Username}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding User.DisplayName}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;with-c-expressions&quot;&gt;With C# expressions&lt;/h3&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Username}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{User.DisplayName}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At first glance, this looks like shorthand for removing the word &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Binding&lt;/code&gt;, but the source generator is doing more than that. When the page has an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x:DataType&lt;/code&gt;, the expression can be checked against the binding context at build time.&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;ContentPage&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;x:Class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;MyApp.ProfilePage&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;x:DataType=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;viewModels:ProfileViewModel&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Username}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;/ContentPage&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Username&lt;/code&gt; doesn’t exist on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProfileViewModel&lt;/code&gt;, the tooling has enough information to complain about it. That’s rather more useful than discovering a typo after navigating to the page and wondering why the label is empty.&lt;/p&gt;

&lt;p&gt;Writable properties can still be used with controls that support two-way binding:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Entry&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Username}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This isn’t throwing away data binding. It’s giving the compiler a more direct and strongly typed way to describe it.&lt;/p&gt;

&lt;h2 id=&quot;boolean-expressions&quot;&gt;Boolean expressions&lt;/h2&gt;

&lt;p&gt;Boolean expressions are probably where many developers will see the quickest win. Applications tend to collect converters and calculated properties for conditions such as “invert this value”, “check whether both values are true” or “show this control when a count is greater than zero”.&lt;/p&gt;

&lt;p&gt;A view model might currently expose another property:&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CanSave&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IsValid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsSaving&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The XAML then binds to it:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Button&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Save&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;IsEnabled=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding CanSave}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This works, but the view model must also raise a property-change notification for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CanSave&lt;/code&gt; whenever either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IsValid&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IsSaving&lt;/code&gt; changes. That is easy to forget and can produce the sort of bug where the state is correct but the button remains stubbornly disabled.&lt;/p&gt;

&lt;p&gt;Another option is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MultiBinding&lt;/code&gt; and converter:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Save&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Button.IsEnabled&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;MultiBinding&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Converter=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{StaticResource CanSaveConverter}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;Binding&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Path=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;IsValid&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;Binding&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Path=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;IsSaving&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/MultiBinding&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Button.IsEnabled&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That is a lot of XAML for a condition that is perfectly readable in one line.&lt;/p&gt;

&lt;h3 id=&quot;with-c-expressions-1&quot;&gt;With C# expressions&lt;/h3&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Button&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Save&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;IsEnabled=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{IsValid &amp;amp;&amp;amp; !IsSaving}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Other conditions are equally direct:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;IsVisible=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{ItemCount &amp;gt; 0}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;Button&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;IsEnabled=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{HasAcceptedTerms &amp;amp;&amp;amp; IsFormValid}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;VerticalStackLayout&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;IsVisible=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{IsSignedIn || IsGuestAccessEnabled}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is the sort of thing C# expressions are particularly good at. The logic is small, local to the view and understandable without extra context.&lt;/p&gt;

&lt;p&gt;Word-based operators are also being explored to avoid some of the awkwardness caused by XML escaping:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Button&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;IsEnabled=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{HasAcceptedTerms AND IsFormValid}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The available aliases include forms such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AND&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OR&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LT&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GT&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LTE&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GTE&lt;/code&gt;. Whether you prefer those or the normal C# operators will probably come down to readability and how much XML complains about what you’re trying to type.&lt;/p&gt;

&lt;h2 id=&quot;calculated-values&quot;&gt;Calculated values&lt;/h2&gt;

&lt;p&gt;Calculated properties are another common piece of view-model furniture. Suppose you have a price and quantity and want to show the total.&lt;/p&gt;

&lt;h3 id=&quot;before-1&quot;&gt;Before&lt;/h3&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;decimal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Price&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Quantity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;decimal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Total&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Price&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Quantity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding Total}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Again, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Total&lt;/code&gt; needs to raise a change notification whenever &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Price&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Quantity&lt;/code&gt; changes. Without that notification, the calculation may be correct in the view model while the UI continues showing an old value.&lt;/p&gt;

&lt;p&gt;With a C# expression, the calculation can be written directly in the XAML:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Price * Quantity}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The source generator can inspect the expression and work out which values it depends on. Because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Price * Quantity&lt;/code&gt; isn’t something that can be assigned back to the view model, the generated binding is one-way, which is exactly what you would expect.&lt;/p&gt;

&lt;p&gt;This works well for small presentation calculations. It doesn’t mean your pricing rules, discount logic and tax calculations should now live in a forty-line XAML expression. If the calculation has business meaning, is reused elsewhere or needs proper testing, keep it in C# and give it a useful name.&lt;/p&gt;

&lt;h2 id=&quot;string-interpolation&quot;&gt;String interpolation&lt;/h2&gt;

&lt;p&gt;Formatting text in XAML has always been possible, but it isn’t always pleasant. You might use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StringFormat&lt;/code&gt;, a calculated property or a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FormattedString&lt;/code&gt; full of spans.&lt;/p&gt;

&lt;p&gt;For example, displaying a full name might involve another property.&lt;/p&gt;

&lt;h3 id=&quot;before-2&quot;&gt;Before&lt;/h3&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FullName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;$&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FirstName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding FullName}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;with-c-expressions-2&quot;&gt;With C# expressions&lt;/h3&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{$&apos;{FirstName} {LastName}&apos;}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The single quotes are used because the XAML attribute itself is already wrapped in double quotes. You can use the same approach for other bits of display text:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{$&apos;Hello, {FirstName}&apos;}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{$&apos;{Quantity} × {ProductName}&apos;}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{$&apos;Total: {Price:C2}&apos;}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dates can be formatted in the same way:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{$&apos;Arriving {ArrivalDate:dddd, d MMMM}&apos;}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This should be particularly useful when the formatted text exists for one specific view. If several pages need the same formatting, or the formatting is part of the application’s behaviour rather than its presentation, a named property or formatter is probably still the better home.&lt;/p&gt;

&lt;h2 id=&quot;ternary-expressions&quot;&gt;Ternary expressions&lt;/h2&gt;

&lt;p&gt;Sometimes you need to choose between two values. A common way of doing this is to add another property to the view model.&lt;/p&gt;

&lt;h3 id=&quot;before-3&quot;&gt;Before&lt;/h3&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AccountTypeText&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;IsPremium&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Premium account&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Standard account&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding AccountTypeText}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;with-c-expressions-3&quot;&gt;With C# expressions&lt;/h3&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{IsPremium ? &apos;Premium account&apos; : &apos;Standard account&apos;}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can also combine a ternary with interpolation:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{ItemCount == 1 ? &apos;1 item&apos; : $&apos;{ItemCount} items&apos;}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is useful up to a point. One small ternary expression is easy to understand, but three nested ternaries and a method call will quickly make the XAML harder to follow.&lt;/p&gt;

&lt;p&gt;At that point, give the condition a name and move it back into C#.&lt;/p&gt;

&lt;h2 id=&quot;null-handling&quot;&gt;Null handling&lt;/h2&gt;

&lt;p&gt;Null fallback values are another good fit for expressions.&lt;/p&gt;

&lt;h3 id=&quot;before-4&quot;&gt;Before&lt;/h3&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DisplayName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Unknown user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding DisplayName}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;with-c-expressions-4&quot;&gt;With C# expressions&lt;/h3&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Name ?? &apos;Unknown user&apos;}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can also use null-aware property access:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{User?.DisplayName ?? &apos;Guest&apos;}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is useful when the fallback is specific to a particular element. If the application has a defined rule for how user names should be displayed everywhere, put that rule somewhere reusable rather than copying the same expression across six pages.&lt;/p&gt;

&lt;h2 id=&quot;method-calls&quot;&gt;Method calls&lt;/h2&gt;

&lt;p&gt;Expressions can call methods:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Name.ToUpperInvariant()}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;They can also call helper methods:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{GetFormattedDate()}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Static methods are supported too:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;ProgressBar&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Progress=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Math.Min(Progress, 1)}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This comes with an important caveat: not every expression is automatically reactive. An expression generated as a binding can update when its dependencies raise property-change notifications, but a method called directly from the page may be evaluated once when the view is created.&lt;/p&gt;

&lt;p&gt;If you write this:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{GetCurrentStatus()}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;you shouldn’t assume it will rerun whenever some unrelated property changes. The expression needs a clear set of observable dependencies for the generated binding to know when it should update.&lt;/p&gt;

&lt;p&gt;This is one of the areas worth testing carefully while the feature is still in preview.&lt;/p&gt;

&lt;h2 id=&quot;inline-event-handlers&quot;&gt;Inline event handlers&lt;/h2&gt;

&lt;p&gt;C# expressions can also be used to handle events. Imagine a button that increments a counter.&lt;/p&gt;

&lt;h3 id=&quot;before-5&quot;&gt;Before&lt;/h3&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Button&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Add&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Clicked=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;OnAddClicked&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OnAddClicked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;++;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;with-c-expressions-5&quot;&gt;With C# expressions&lt;/h3&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Button&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Add&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Clicked=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{(sender, args) =&amp;gt; Count++}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can call a method in the same way:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Button&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Reset&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Clicked=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{(sender, args) =&amp;gt; ResetForm()}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is useful for genuinely tiny synchronous actions. It becomes less useful when the event handler contains validation, logging, navigation, cancellation, error handling and three service calls. At that point, give it a name and put it somewhere sensible.&lt;/p&gt;

&lt;p&gt;Async lambdas aren’t currently supported, so asynchronous event handlers still need a normal method or command:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Button&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Save&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Clicked=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;OnSaveClicked&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OnSaveClicked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;EventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SaveAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That limitation may feel inconvenient, but it also stops the XAML from becoming a hiding place for sizeable chunks of asynchronous application logic. Probably not a bad thing.&lt;/p&gt;

&lt;h2 id=&quot;existing-xaml-markup-still-works&quot;&gt;Existing XAML markup still works&lt;/h2&gt;

&lt;p&gt;C# expressions are being added alongside the XAML features that already exist. Normal bindings, static resources and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x:Static&lt;/code&gt; all continue to work:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding Name}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{StaticResource PageTitle}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{x:Static local:AppConstants.AppName}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The source generator needs to work out whether the contents of the braces are a markup extension or a C# expression. Where something is ambiguous, you can be explicit:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Explicit expression --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{= SomeValue}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Resolve against the page --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{this.Title}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Resolve against the binding context --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{.Title}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The last two are useful when the page and its binding context contain properties with the same name. It’s one of those problems you may not have until you do, at which point you’ll be pleased the explicit syntax exists.&lt;/p&gt;

&lt;h2 id=&quot;what-could-this-replace&quot;&gt;What could this replace?&lt;/h2&gt;

&lt;p&gt;C# expressions may remove the need for quite a few small pieces of supporting code, including inverted Boolean converters, simple comparison converters, some multi-value converters, presentation-only calculated properties, basic formatting properties, straightforward triggers and tiny synchronous event handlers.&lt;/p&gt;

&lt;p&gt;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MultiBinding&lt;/code&gt; such as this:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Label.IsVisible&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;MultiBinding&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;Converter=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{StaticResource AllTrueConverter}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

            &lt;span class=&quot;nt&quot;&gt;&amp;lt;Binding&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Path=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;IsLoggedIn&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;Binding&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Path=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;HasSubscription&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/MultiBinding&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Label.IsVisible&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Label&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;can become:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;IsVisible=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{IsLoggedIn &amp;amp;&amp;amp; HasSubscription}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That is fewer lines, but the more useful change is that the condition is visible immediately. You don’t need to inspect a converter to discover whether &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AllTrueConverter&lt;/code&gt; really means all values must be true, whether null counts as false or whether it does something surprising because someone changed it four years ago.&lt;/p&gt;

&lt;h2 id=&quot;what-shouldnt-go-into-an-expression&quot;&gt;What shouldn’t go into an expression?&lt;/h2&gt;

&lt;p&gt;Just because C# can now be written inside XAML doesn’t mean every bit of application logic should move there. I’d avoid using expressions for business rules, network calls, database operations, complex state changes, reusable calculations, anything that needs focused unit testing or anything that requires a comment to explain what it does.&lt;/p&gt;

&lt;p&gt;You could write something like this:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;IsVisible=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{
        CurrentUser != null &amp;amp;&amp;amp;
        CurrentUser.Subscription != null &amp;amp;&amp;amp;
        CurrentUser.Subscription.ExpiresAt &amp;gt; DateTime.Now &amp;amp;&amp;amp;
        !CurrentUser.IsSuspended
    }&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But a named property is much easier to understand:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;IsVisible=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{CanAccessPremiumFeatures}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The second version tells me what the condition means. The first tells me how it is calculated and asks me to work out the meaning myself.&lt;/p&gt;

&lt;p&gt;That is the line I’d use when deciding whether an expression belongs in XAML: use an expression when it makes the XAML more obvious, and use a named property or method when it makes the intention more obvious.&lt;/p&gt;

&lt;h2 id=&quot;a-complete-example&quot;&gt;A complete example&lt;/h2&gt;

&lt;p&gt;Here’s a small page using several of the new expression types together:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;ContentPage&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;x:Class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ExpressionDemo.MainPage&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;x:DataType=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;viewModels:MainViewModel&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;VerticalStackLayout&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;Padding=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;24&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;Spacing=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;16&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

        &lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;FontSize=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;24&quot;&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{$&apos;Welcome, {FirstName}&apos;}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

        &lt;span class=&quot;nt&quot;&gt;&amp;lt;ActivityIndicator&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;IsRunning=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{IsLoading}&quot;&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;IsVisible=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{IsLoading}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

        &lt;span class=&quot;nt&quot;&gt;&amp;lt;VerticalStackLayout&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;IsVisible=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{!IsLoading}&quot;&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;Spacing=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;12&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

            &lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{$&apos;{Quantity} × {ProductName}&apos;}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

            &lt;span class=&quot;nt&quot;&gt;&amp;lt;Label&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{$&apos;Total: {Price * Quantity:C2}&apos;}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

            &lt;span class=&quot;nt&quot;&gt;&amp;lt;Button&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Place order&quot;&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;IsEnabled=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{
                    Quantity &amp;gt; 0 &amp;amp;&amp;amp;
                    HasAcceptedTerms &amp;amp;&amp;amp;
                    !IsSubmitting
                }&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/VerticalStackLayout&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/VerticalStackLayout&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;/ContentPage&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There are no converters here, no calculated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Total&lt;/code&gt; property and no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CanPlaceOrder&lt;/code&gt; property that needs change notifications whenever three other values change.&lt;/p&gt;

&lt;p&gt;The important question isn’t whether this version contains fewer lines. It’s whether someone opening the page can understand what it does.&lt;/p&gt;

&lt;p&gt;In this case, I think they probably can.&lt;/p&gt;

&lt;h2 id=&quot;when-can-i-try-it&quot;&gt;When can I try it?&lt;/h2&gt;

&lt;p&gt;C# expressions are being developed for .NET MAUI in .NET 11. .NET 11 is scheduled for release in November 2026, but the feature can be tried using the .NET 11 preview SDK and the matching .NET MAUI workload.&lt;/p&gt;

&lt;p&gt;It’s still experimental, so expect rough edges, incomplete tooling and behaviour that may shift between preview releases. I wouldn’t start converting a production application wholesale yet.&lt;/p&gt;

&lt;p&gt;A better approach is to create a small test project or pick one isolated page containing a few obvious candidates: an inverted Boolean converter, a basic &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MultiBinding&lt;/code&gt;, a display-only calculated property, a formatted string or a one-line synchronous event handler.&lt;/p&gt;

&lt;p&gt;Replace them one at a time and see what the resulting XAML feels like. Check whether it becomes easier to read, whether the expression updates when you expect it to, whether Hot Reload behaves and whether the compiler errors point you towards the problem when something goes wrong.&lt;/p&gt;

&lt;p&gt;Those are the useful questions during a preview.&lt;/p&gt;

&lt;h2 id=&quot;give-it-a-try&quot;&gt;Give it a try&lt;/h2&gt;

&lt;p&gt;C# expressions won’t replace MVVM, converters, commands, view models or code-behind, and they shouldn’t. What they offer is a way to remove some of the faff around small bits of presentation logic.&lt;/p&gt;

&lt;p&gt;That could mean fewer converters, fewer properties that exist purely for one label and less hopping between files to understand a simple condition.&lt;/p&gt;

&lt;p&gt;Try them in a small page and see which bits of boilerplate disappear. More importantly, notice which bits are still clearer with a proper name in the view model.&lt;/p&gt;

&lt;p&gt;Then tell the .NET MAUI team what worked, what didn’t and where the tooling got confused. Preview features improve when people use them for real things rather than admiring them from a release note.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/dotnet/maui/blob/main/docs/specs/XamlCSharpExpressions.md&quot;&gt;Read the spec&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 17 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/c-sharp-expressions-in-xaml/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/c-sharp-expressions-in-xaml/</guid>
      </item>
    
      <item>
        <title>Entertainment is consumed. Fun is created.</title>
        <description>
</description>
        <pubDate>Sat, 20 Jun 2026 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/entertainment-you-consume-fun-you-make/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/entertainment-you-consume-fun-you-make/</guid>
      </item>
    
      <item>
        <title>One day. . . I'll go straight there.</title>
        <description>&lt;p&gt;See you soon-ish City JS!&lt;/p&gt;
</description>
        <pubDate>Tue, 14 Apr 2026 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/one-day-ill-go-straight-there/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/one-day-ill-go-straight-there/</guid>
      </item>
    
      <item>
        <title>MAUI Day and the stowaway ladybird</title>
        <description>&lt;p&gt;7 Talks + 2 nights away + a stowaway ladybird = another successful MAUI Day!&lt;/p&gt;

&lt;p&gt;With almost 100 attendees in the room, how could it not be?&lt;/p&gt;

&lt;p&gt;The gaggle of .NET MAUI developers had descended from around the globe on central London for a day of cross-platform knowledge sharing. Not only did we learn a whole bunch, but we also got to meet and mingle with the faces behind the avatars that we chat with day in and out.&lt;/p&gt;

&lt;p&gt;Between Syncfusion providing the food, NewDay providing the venue, and the community providing the conversations, the room was in exceptionally high spirits.&lt;/p&gt;

&lt;p&gt;Was it fun?&lt;/p&gt;

&lt;p&gt;It sure was.&lt;/p&gt;

&lt;p&gt;Did it run on time?&lt;/p&gt;

&lt;p&gt;Hell no!&lt;/p&gt;

&lt;p&gt;Will we do it again?&lt;/p&gt;

&lt;p&gt;For sure!&lt;/p&gt;

&lt;p&gt;Where?&lt;/p&gt;

&lt;p&gt;Everywhere!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2026/maui-day-shriram.jpg&quot; alt=&quot;Photo of Shriram at MAUI Day&quot; title=&quot;Photo of Shriram at MAUI Day&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For as long as another group of speakers are willing to assemble to provide an excuse to get together, then we’ve got no excuse not to. Massive thanks to David, Stéphane, Mark, Matt, Shriram, and Clifford for giving the days conversations a focal point, plus allowing the conf to ✅ the 5 continents box.&lt;/p&gt;

&lt;p&gt;Not sure how we’ll reach six!&lt;/p&gt;

&lt;p&gt;In a distributed sector, within a distributed world, opportunities to connect in person and deepen the rapport built on top of hundreds of online chats is important. Both to the individual and the whole. Communities thrive based on the value of conversations, and judging by the buzz in the room last week the hashtag#dotnetMAUI community has never been so alive.&lt;/p&gt;

&lt;p&gt;Just like the ladybird.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2026/maui-day-ladybird.jpg&quot; alt=&quot;The Ladybird packed into a suitcase&quot; title=&quot;The Ladybird packed into a suitcase&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;She’s part of the colony hibernating in the bedroom back home, although one of the family decided to come on the 580 mile round train trip.&lt;/p&gt;

&lt;p&gt;Thankfully, Premier Inn rooms are hermetically sealed. . . meaning she could fly around the room in the evening without me having to worry about her escaping. Countryside bugs don’t deserve city life, although I’m sure she has some stories to tell the others!&lt;/p&gt;

&lt;p&gt;We both have to be fair.&lt;/p&gt;

&lt;p&gt;Overall, it was another successful trip to the UK capital for the hashtag#MAUIDay crew.&lt;/p&gt;

&lt;p&gt;But multiple attendees on the day gave me feedback that there should be more focus on performance amongst the sessions.&lt;/p&gt;

&lt;p&gt;Hopefully we’ll be able to arrange that for London 2027, and maybe even add a little performance to the panel 🤞&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2026/maui-day-panel.jpg&quot; alt=&quot;The MAUI Day closing pannel&quot; title=&quot;The Ladybird packed into a suitcase&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 06 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/maui-day-and-the-stowaway-ladybird/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/maui-day-and-the-stowaway-ladybird/</guid>
      </item>
    
      <item>
        <title>3 minutes to go. Stuck in the toilet 🤦‍♂️</title>
        <description>&lt;p&gt;3 mins left and I was stuck in the toilet&lt;/p&gt;

&lt;p&gt;It was broadcast time.&lt;/p&gt;

&lt;p&gt;Eat a Banana. Drink some water. Go to the bathroom.&lt;/p&gt;

&lt;p&gt;Gran always said to never miss an opportunity, and this wasn’t the moment to defy such hefty wisdom.&lt;/p&gt;

&lt;p&gt;Hearing the click of the door behind me, it didn’t cross my mind that this is the high security HQ of Microsoft. Doors have locks. A few minutes later I soon realised the consequences of this lapse in concentration.&lt;/p&gt;

&lt;p&gt;The call was made.&lt;/p&gt;

&lt;p&gt;I was rescued.&lt;/p&gt;

&lt;p&gt;Everything worked out in the end. But it wasn’t the warm-up I’d imagined for my guest appearance on the &lt;a href=&quot;https://www.youtube.com/watch?v=8X03ksPKX6A&quot;&gt;dotnet YouTube channel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I wouldn’t worry about watching.&lt;/p&gt;

&lt;p&gt;My appearance amounts to just babbling about chocolate salty balls.&lt;/p&gt;

&lt;p&gt;They are tasty tho.&lt;/p&gt;
</description>
        <pubDate>Thu, 05 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/3-minuts-to-go/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/3-minuts-to-go/</guid>
      </item>
    
      <item>
        <title>Life - All about the bounce back</title>
        <description>
</description>
        <pubDate>Wed, 28 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/life-all-about-the-bounce-back/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/life-all-about-the-bounce-back/</guid>
      </item>
    
      <item>
        <title>.NET MAUI - Toggle fullscreen for MacCatalyst desktop app</title>
        <description>&lt;p&gt;.NET MAUI Mac Catalyst apps run on macOS, but use UIKit (iOS frameworks) rather than AppKit (native macOS frameworks). To toggle full screen, the same behavior as clicking the green ”zoom” button in the window chrome, we need to bridge into AppKit’s NSApplication and NSWindow using the Objective-C runtime.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#if MACCATALYST

    var nsAppClass = ObjCRuntime.Class.GetHandle(&quot;NSApplication&quot;);
    var nsApp = ObjCRuntime.Runtime.GetNSObject(nsAppClass);
    var sharedApp = nsApp?.PerformSelector(new ObjCRuntime.Selector(&quot;sharedApplication&quot;));
    var keyWindow = sharedApp?.PerformSelector(new ObjCRuntime.Selector(&quot;keyWindow&quot;));
    keyWindow?.PerformSelector(new ObjCRuntime.Selector(&quot;toggleFullScreen:&quot;), keyWindow);

#endif
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you want to see it in action, check out &lt;a href=&quot;https://github.com/tonyedwardspz/MAUI-full-screen-mac-demo-project&quot;&gt;this demo project&lt;/a&gt; containing a Mac App.&lt;/p&gt;

&lt;p&gt;Here’s how it works.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var nsAppClass = ObjCRuntime.Class.GetHandle(&quot;NSApplication&quot;);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Gets a handle (pointer) to the Objective-C class &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSApplication&lt;/code&gt;. This is AppKit’s application singleton class that manages the macOS app lifecycle. Since Mac Catalyst doesn’t directly expose AppKit types to C#, we access it dynamically through the Objective-C runtime.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var nsApp = ObjCRuntime.Runtime.GetNSObject(nsAppClass);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Wraps the raw class handle in an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSObject&lt;/code&gt; that we can interact with from C#. This gives us a managed object representing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSApplication&lt;/code&gt; class itself, which we get with the next line.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var sharedApp = nsApp?.PerformSelector(new ObjCRuntime.Selector(&quot;sharedApplication&quot;));&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This calls the sharedApplication class method on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSApplication&lt;/code&gt;, which returns the singleton instance of the running application.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var keyWindow = sharedApp?.PerformSelector(new ObjCRuntime.Selector(&quot;keyWindow&quot;));&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This retrieves the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keyWindow property&lt;/code&gt; from the shared application, i.e. the window that will receive any keypresses. This returns an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSWindow&lt;/code&gt; instance. Then. . . finally. . .&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keyWindow?.PerformSelector(new ObjCRuntime.Selector(&quot;toggleFullScreen:&quot;), keyWindow);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Calls toggleFullScreen: on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSWindow&lt;/code&gt;. This is the same method macOS invokes when you click the green full screen button. The method takes a sender parameter (we pass the window itself), and toggles between full screen and windowed mode. This mean you can call it again to revert the full screen.&lt;/p&gt;

&lt;p&gt;And with that, you now have a fullscreen Mac app using .NET MAUI.&lt;/p&gt;

&lt;h3 id=&quot;what-about-windows&quot;&gt;What about Windows?&lt;/h3&gt;

&lt;p&gt;If you want to implement the same functionality within MAUI for Windows, I highly recommend this &lt;a href=&quot;https://blog.verslu.is/maui/full-screen-disable-minimize-maximize-for-net-maui-windows-apps/&quot;&gt;blog post&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Fri, 23 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/muai-toggle-fullscreen-on-maccatalyst/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/muai-toggle-fullscreen-on-maccatalyst/</guid>
      </item>
    
      <item>
        <title>A MAUI example starter project</title>
        <description>&lt;p&gt;Setting a project up in the right way from day one is key to long term success. But with a myriad of different ways to achieve the same goal, it’s fairly easy to go down the wrong path. Especially as a learner. This is even more true with MAUI, given how much it’s changed in recent years.&lt;/p&gt;

&lt;p&gt;Quite often example projects are created by experts in software engineering, who’ve internalised abstractions and know the APIs inside out. These abstractions and helper libraries might make complete sense to someone with years of experience in a field, but to a learner, they’re can be plain confusing.&lt;/p&gt;

&lt;p&gt;To AI as well.&lt;/p&gt;

&lt;p&gt;By setting up the basics of a project, and then handing off to AI to fill in the gaps, the end result is much better and quicker to get to. With a little prompting, an AI coding assistant will scan a project and pattern match what exists already, making the right setup even more foundational and key.&lt;/p&gt;

&lt;p&gt;At the outset of a recent vibe Mac app, I created &lt;a href=&quot;https://github.com/tonyedwardspz/maui-di-vm-settings-example&quot;&gt;a boilerplate project&lt;/a&gt; to act as an example of a good starting point for a .NET MAUI app to grow from. It:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Uses view models via the community toolkit to allow for a clean separation of UI and business logic&lt;/li&gt;
  &lt;li&gt;Sets up dependency injection for services, and consumes them in the view models&lt;/li&gt;
  &lt;li&gt;Uses app settings to pull config from&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It achieves these things in the simplest way possible, without abstracting the reader of the code from how it fits together. It also offers a great starting point to experiment with using something more fancy to achieve the same goals, and will work on any platform if you alter the platform identifiers.&lt;/p&gt;

&lt;p&gt;Hopefully you’ll find it useful on your MAUI journey.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/tonyedwardspz/maui-di-vm-settings-example&quot;&gt;https://github.com/tonyedwardspz/maui-di-vm-settings-example&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Wed, 17 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/maui-starter-project/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/maui-starter-project/</guid>
      </item>
    
      <item>
        <title>Festive friday at Sapphire House</title>
        <description>&lt;p&gt;34 people, 23 dishes, (only) 4 bottles of Prosecco, and 1 happy chef *.&lt;/p&gt;

&lt;p&gt;That’s a festive Friday at Sapphire House.&lt;/p&gt;

&lt;p&gt;To bring the team together before we start disappearing ahead of Christmas, the Sapphire Holidays IT team, joined up with parts of the Aspects Holidays and Classic Cottages teams to craft the ultimate office roast. Of course, this came shortly after giving out the presents.&lt;/p&gt;

&lt;p&gt;The meal itself was both a success and tasty!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/ff-people.jpg&quot; alt=&quot;People enjoying the Festive food&quot; title=&quot;The festive friday food spread&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Honey glazed parsnips met crispy roast potatoes. Succulent beef collided with terrific turkey. Cute little piggies nestled in their blankets, with a trio of gravies smothering them all. It’s was one of those moments that having multiple full kitchens in the building became a major highlight of office life.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/ff-beef.jpg&quot; alt=&quot;Festive friday beef&quot; title=&quot;The festive friday food spread&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/ff-parsnips.jpg&quot; alt=&quot;Festive friday parsnips&quot; title=&quot;The festive friday food spread&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/ff-cabbage.jpg&quot; alt=&quot;Festive friday cabbage&quot; title=&quot;The festive friday food spread&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately, expectations for 2026 are now super high.&lt;/p&gt;

&lt;p&gt;I suspect we’ll only top 2025 by getting a visit from Santa himself. . . although Dan was a adequate stand-in come time for secret Santa.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/ff-santa-dan.jpg&quot; alt=&quot;Santa Dan&quot; title=&quot;Santa Dan giving out presents&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ok. There were actually two chefs. . . but only one of them regularly makes me bacon sandwiches so he’s getting all the credit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/ff-happy-chef.jpg&quot; alt=&quot;Happy chef&quot; title=&quot;Happy Chef after the meal&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 15 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/festive-friday/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/festive-friday/</guid>
      </item>
    
      <item>
        <title>10 years of Digital Plymouth</title>
        <description>&lt;p&gt;10 year of bringing Plymouth’s digital community together!&lt;/p&gt;

&lt;p&gt;Getting to come along for the journey has been an honor.&lt;/p&gt;

&lt;p&gt;We’re too quick to say that something is life changing nowadays. So much so that its become a cliché. But for this meetup, the people around it, and those that attend, it is often true in the truest sense of the word.&lt;/p&gt;

&lt;p&gt;Whenever I’m doing something amazingly fun professionally, in the farthest corners of Europe, I can ALWAYS trace the origin back to the encouragement and support that came from being a part of the Digital Plymouth / Plymouth Web / PlymouthJS communities 🙏&lt;/p&gt;

&lt;p&gt;It been great to watch it grow over the past decade into something bigger, more diverse, and even more impactful to the city.&lt;/p&gt;

&lt;p&gt;Here’s to 10 more years of the same 🥂&lt;/p&gt;

&lt;p&gt;A response to &lt;a href=&quot;This LinkedIn post&quot;&gt;https://www.linkedin.com/feed/update/urn:li:activity:7402436542780305408/&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Thu, 04 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/10-years-of-digital-plymouth/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/10-years-of-digital-plymouth/</guid>
      </item>
    
      <item>
        <title>Hanging up the wigs</title>
        <description>&lt;p&gt;I’ve hung up the wigs for 2025.&lt;/p&gt;

&lt;p&gt;But be warned. . . they’ll be back on occasion in 2026.&lt;/p&gt;

&lt;p&gt;In recent years, the two talks I’ve delivered the most have both had a gimmick. Something to create a photo opportunity as part of an event, and hopefully to put a smile on the audiences face.&lt;/p&gt;

&lt;p&gt;It worked!&lt;/p&gt;

&lt;p&gt;Well. . . most of the time.&lt;/p&gt;

&lt;p&gt;Without giving away the moment, the wigs and hats were both an integral part of the talks. But you (or even the organiser) can only play the fool so often, and it’s time to be a little more serious with the content I deliver. So whilst they’ll both be back, they’ll be used mainly for meetups where things are a little more informal and expectations on takeaway learnings are a little lower.&lt;/p&gt;

&lt;p&gt;But one of the projects behind the talk has changed a huge amount over the years. Plus it’s super fun to work on.&lt;/p&gt;

&lt;p&gt;Back then it was little more that a clone of a platform demo with a changed h1 tag, a ton of showmanship, and a dash of hot bars. Today, it’s grown into a multi API backend encompassing locally hosted speech recognition, LLMs, and image recognition paired with either a website or .NET tMAUI desktop app as the interface. It’s even binging in the hot newness that is Aspire to both the web and .NET stacks.&lt;/p&gt;

&lt;p&gt;Naturally, the software is a bit shaky. That’s part of the fun. However the learnings are solid and it keeps a mechanism for growing my hat collection a little more.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/hats.jpg&quot; alt=&quot;Hat collection&quot; title=&quot;Hat collection&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The trickiest part?&lt;/p&gt;

&lt;p&gt;Fitting the details into a paragraph or two so I can submit to conferences!&lt;/p&gt;

&lt;p&gt;Wish me luck 🤞&lt;/p&gt;
</description>
        <pubDate>Fri, 28 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/hanging-up-the-wigs/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/hanging-up-the-wigs/</guid>
      </item>
    
      <item>
        <title>The value of user testing</title>
        <description>&lt;p&gt;At work, the project I head up is entering its final phase of development before release. To make sure that we’re making guests life easier, I’ve hosted a user testing session in recent days. The results are surprisingly unsurprising. Bugs have been flagged up, paths through the app were broken, and features were not used as expected.&lt;/p&gt;

&lt;p&gt;It was enlightening!&lt;/p&gt;

&lt;p&gt;Whilst we’re well past the prototyping phase, the &lt;a href=&quot;https://www.sitepoint.com/premium/books/designing-ux-prototyping/&quot;&gt;Designing UX: Prototyping&lt;/a&gt; book by &lt;a href=&quot;https://bsky.app/profile/bouncingdan.bsky.social&quot;&gt;Dan Goodwin&lt;/a&gt; and Ben has been super useful in setting up this activity. It pushed me into the right mindset for testing in a high fidelity context, giving a great framework for asking the right questions and setting the right tasks for users to work though. Although some of the tooling in the book in out dated, the concepts are solid and will never not be relevant. It’s also a super easy read, and pairs up well with lessons withing ‘The Mum Test’. Both are highly recommended if you’re about to perform this type of task.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/testing-book.jpg&quot; alt=&quot;Designing UX: Prototyping book&quot; title=&quot;Designing UX: Prototyping&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;On the day, test users were provided with four groups of related tasks, the kind of things that guests will over the lifecycle of their stay. Feedback was gathered via both a form and conversation, plus observational notes to pair with screen and audio recordings. The perspective afforded by looking over a shoulder instead of testing yourself allows different elements of the product to jump out. E.g,&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I never miss the hit box to open the account edit screen, but every single tester did.&lt;/li&gt;
  &lt;li&gt;Users consistently look for X as part of the search interface.&lt;/li&gt;
  &lt;li&gt;I think feature X is complete, but the people from within the brand think Y and Z are missing from it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/testing-user2.jpg&quot; alt=&quot;Testing MAUI apps with users&quot; title=&quot;Testing MAUI apps with users&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Talking with frontline staff, those on the end of the phone during both the booking process and during the stay, uncovered a bunch of easy wins for the product.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;“20% of our calls are about X”&lt;/li&gt;
  &lt;li&gt;“Our life would be easier if guests had Y when they called up”&lt;/li&gt;
  &lt;li&gt;“99% of guests only have one booking at a time”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The process also threw me back to a conversation at the &lt;a href=&quot;https://tonyedwardspz.co.uk/blog/product-tank-cologne/&quot;&gt;Product Task meetup in Köln&lt;/a&gt;. I was talking about testing with a fellow attendee, with the conversation continuing afterwards digitally. I highlighted that my test group will come from within the company. It was suggested that they’d use the product differently to actual guests due to institutional knowledge, whilst I exibited an undeserved level of hubris that they wouldn’t.&lt;/p&gt;

&lt;p&gt;Surprise surprise. . . they did.&lt;/p&gt;

&lt;p&gt;One of the tasks was to navigate to a booked property, effectivly the stay starting tomorrow. Everyone within the business checked to see if the textual directions were present in the app. Everyone outside of the business simply clicked the map to start navigation within their maps app. This really highlighted how institutional knowledge affects the was a user performs a task. Martin. You were right. . . but only one of us knew that at the time! To paraphrase Tim Herberg, the speaker on the night:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Gut feeling has a place in the discovery process. It can inform the direction in the early days, but should quickly be backed up or discarded due to data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Unfortunatly, I’d forgotten that point in the sime since and neglected to get the data to back up my assumptions.&lt;/p&gt;

&lt;p&gt;Overall this was an enlightening process, and one that reminded me of the value that the rapid feedback loop that often comes with an agile-esque development process. Whilst some of the things that were flagged up are solid suggestions, there’s not really enough time to both polish what exists and introduce the refined features before launch day.&lt;/p&gt;

&lt;p&gt;Lesson learned.&lt;/p&gt;

&lt;p&gt;This was a fun and very useful process to go through as a product developer. I’m now sitting on a pile of actionable feedback, insights from different levels of the business, and even a few ideas that can help make the wider teams life easier via minimal changes to existing products or a quickly vibed prototype.&lt;/p&gt;

&lt;p&gt;Oh. . . and biscuits. We ate a lot of biscuits.&lt;/p&gt;
</description>
        <pubDate>Wed, 26 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/the-value-of-testing/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/the-value-of-testing/</guid>
      </item>
    
      <item>
        <title>Looking around @ HalfStack London</title>
        <description>
</description>
        <pubDate>Fri, 21 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/looking-around-at-halfstack/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/looking-around-at-halfstack/</guid>
      </item>
    
      <item>
        <title>Rings - Aesop Rock</title>
        <description>&lt;p&gt;Used to draw&lt;br /&gt;
Hard to admit that I used to draw&lt;br /&gt;
Portraiture and the human form&lt;br /&gt;
Doodle of a two-headed unicorn&lt;br /&gt;
It was soothin’, movin’ his arm in a fusion&lt;br /&gt;
Of man-made tools and a muse from beyond&lt;br /&gt;
Even if it went beautifully wrong&lt;br /&gt;
It was tangible truth for a youth who refused to belong&lt;br /&gt;
No name nuisance, stews in a bedroom&lt;br /&gt;
Oozing a brand new cuneiform&lt;br /&gt;
Barely commune with the horde&lt;br /&gt;
Got a whole gray scale ungluing his world&lt;/p&gt;

&lt;p&gt;Might zone out to the yap of the magpie&lt;br /&gt;
Unseen hand dragging his graphite&lt;br /&gt;
Cross contour, little bit of backlight&lt;br /&gt;
Black ink after a Bristol to baptize&lt;br /&gt;
You can’t imagine the rush that ensue&lt;br /&gt;
When you get three dimensions stuffed into two&lt;br /&gt;
Then it’s off to a school where it’s all that you do&lt;br /&gt;
Being trained and observed by a capable few&lt;br /&gt;
Back in New York, five peeps and a dog&lt;br /&gt;
In a two-bedroom doing menial jobs&lt;br /&gt;
Plus, rhymin’ and stealin’ and being a clod&lt;br /&gt;
Distractions free to maraud&lt;/p&gt;

&lt;p&gt;I left some years a deer in the light&lt;br /&gt;
I left some will to spirit away&lt;br /&gt;
I let my fears materialize&lt;br /&gt;
I let my skills deteriorate&lt;br /&gt;
Haunted by the thought of what I should have been continuing&lt;br /&gt;
A mission that was rooted in a 20-year affinity&lt;br /&gt;
In rickety condition with an ID crisis&lt;br /&gt;
Nap on the front lawn, look up in the sky, it’s…&lt;/p&gt;

&lt;p&gt;Shapes falling out of the fringe&lt;br /&gt;
All heart, though we would’ve made cowardly kings&lt;br /&gt;
They will chop you down just to count your rings&lt;br /&gt;
Just to count your rings, just to count your rings&lt;br /&gt;
And there were colors pouring out of the fringe&lt;br /&gt;
All heart, though we would’ve made cowardly kings&lt;br /&gt;
They will chop you down just to count your rings&lt;br /&gt;
Just to count your rings, just to count your rings&lt;/p&gt;

&lt;p&gt;Used to paint&lt;br /&gt;
Hard to admit that I used to paint&lt;br /&gt;
Natural light on a human face&lt;br /&gt;
Stenciled fire on his roommate’s bass&lt;br /&gt;
It was blooming addiction&lt;br /&gt;
Amiss in the pushing of pigment&lt;br /&gt;
Book like a tattooed pigskin, look&lt;br /&gt;
Pinhead kids of the minute&lt;br /&gt;
Drank Kool-Aid from a tube of acrylic&lt;br /&gt;
And it grew up into linseed oil over linen&lt;br /&gt;
Joy to the poison, voice of the resin&lt;br /&gt;
Capture a map of the gesture&lt;br /&gt;
Back up, add a little accurate fat to the figure&lt;/p&gt;

&lt;p&gt;Redo that, move that inward&lt;br /&gt;
Zinc white lightning shoots from his fingers&lt;br /&gt;
Studio strewn with illusion and tinctures&lt;br /&gt;
Stay tuned for the spooky adventures&lt;br /&gt;
You can’t imagine the stars that align&lt;br /&gt;
When a forearm starts foreshortening right&lt;br /&gt;
Or a torso hung on a warping spine&lt;br /&gt;
In proportion reads as warm and alive&lt;br /&gt;
Routine day with a dirt cheap brush&lt;br /&gt;
Then a week goes by and it goes untouched&lt;br /&gt;
Then two, then three, then a month&lt;br /&gt;
And the rest of your life, you beat yourself up&lt;/p&gt;

&lt;p&gt;I left some seasons eager to fall&lt;br /&gt;
I left some work to bury alive&lt;br /&gt;
I let my means of being dissolve&lt;br /&gt;
I let my person curl up and die&lt;br /&gt;
Eating up his innards, an unfeasible anxiety&lt;br /&gt;
Has brutally committed to relinquishing his privacy&lt;br /&gt;
Aligning with the trials of the anti-Midas&lt;br /&gt;
Nap on the back lawn, look up in the sky, it’s…&lt;/p&gt;

&lt;p&gt;Shapes falling out of the fringe&lt;br /&gt;
All heart, though we would’ve made cowardly kings&lt;br /&gt;
They will chop you down just to count your rings&lt;br /&gt;
Just to count your rings, just to count your rings&lt;br /&gt;
And there were colors pouring out of the fringe&lt;br /&gt;
All heart, though we would’ve made cowardly kings&lt;br /&gt;
They will chop you down just to count your rings&lt;br /&gt;
Just to count your rings, just to count your rings&lt;/p&gt;
</description>
        <pubDate>Tue, 18 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/rings/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/rings/</guid>
      </item>
    
      <item>
        <title>Environment dictates performance</title>
        <description>&lt;p&gt;A recent conversation with a mentee who is stepping out of education into the world reminded me of this well known phrase. It’s one that makes logical sense.&lt;/p&gt;

&lt;p&gt;If you’re in a high performing environment, your much more likely to perform to a high level.&lt;/p&gt;

&lt;p&gt;If you’re in a creative environment, you’re much more likely to be creative.&lt;/p&gt;

&lt;p&gt;If you’re surrounded by people who are learning, incrementing skills upwards, and pushing boundaries. . . you will as well.&lt;/p&gt;

&lt;p&gt;The world around us is a normalising factor.&lt;/p&gt;

&lt;p&gt;My advice to them at the outset of their career. . . be eternally careful about the world you choose to inhabit.&lt;/p&gt;
</description>
        <pubDate>Mon, 17 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/environment-dictates-performance/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/environment-dictates-performance/</guid>
      </item>
    
      <item>
        <title>Tech Mids community conference</title>
        <description>&lt;p&gt;Woah.&lt;/p&gt;

&lt;p&gt;That’s how you bring a community together!&lt;/p&gt;

&lt;p&gt;230 of the Midlands best and brightest descended on the Mailbox in Birmingham for the &lt;a href=&quot;https://conf.techmids.org&quot;&gt;TechMids conference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/techmids-bull.jpg&quot; alt=&quot;Big Bull at Tech Mids Conference&quot; title=&quot;Big Bull at Tech Mids Conference&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Did we have fun? We sure did 😎&lt;/p&gt;

&lt;p&gt;The sessions across the day covered an extremely broad range of topics. Whilst every single one deserves a mention, there are a few highlights that provided value that is being taken back to the Sapphire Holidays dev team.&lt;/p&gt;

&lt;p&gt;Becki Floyd dropped a UX bomb, showing the audience the inner awesomeness of the Voxpopme, a tool to validate ideas and garner feedback at a humungous scale.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/techmids-becki.jpg&quot; alt=&quot;Becki Floyd at Tech Mids Conference&quot; title=&quot;Becki Floyd at Tech Mids Conference&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Guy Barker shared a11y insights drawn from his dotnetMAUI Accessible Solitaire app, backed by a lifetime of experience in the field. What the talk lacked in chanting (this time), it made up for in actionable insights 🙌&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/techmids-guy-barker.jpg&quot; alt=&quot;Guy Barker at Tech Mids Conference&quot; title=&quot;Guy Barker at Tech Mids Conference&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Si Jobling dispensed psychological safety from the stage, thanks to the PETALS framework. It’s a simple framework for continuously improve a tech team’s health. Don’t worry Si. . . I refused to do the exercise with Toby as suggested. . . instead having a useful topic adjacent conversation during that part of the proceedings 💬&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/techmids-si-jobling.jpg&quot; alt=&quot;Si Jobling at Tech Mids Conference&quot; title=&quot;Si Jobling at Tech Mids Conference&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Wrapping up the day was a wonderful talk from Shaun Lawrence which perfectly walked the tightrope of informative, fun, and inspirational. I’ve not yet managed to convince the team to set up a IoT brewing operation in the corner of the office, but I suspect it won’t take much more persuasion.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/techmids-shawn-lawrence.jpg&quot; alt=&quot;Shawn Lawrence at Tech Mids Conference&quot; title=&quot;Shawn Lawrence at Tech Mids Conference&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Overall, this is tied with WhatTheStack Conference as my favourite community led event to be a part of in 2025.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;As a speaker, you know you’re part of a great line-up when you don’t want to be in your own talk!&lt;/li&gt;
  &lt;li&gt;You also know you’re in safe hands when the track host, conf team, and audience join forces to fix show stopping problems in the moments before your talk starts (thanks Bruce 🙏)&lt;/li&gt;
  &lt;li&gt;You know your witnessing a thriving community when the conversations carry on LAAAAATE into the night.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With TechMids over, my speaking engagements for 2025 are complete. There is no other conference on the earth that would have provided a juicier cherry to top this years conf cake.&lt;/p&gt;

&lt;p&gt;It. Was. Perfect.&lt;/p&gt;

&lt;p&gt;Let’s make this a tradition and do it again next year.&lt;/p&gt;

&lt;p&gt;It’s lovely to finish the year with a short-long trip home 🚗&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/techmids-cornwall.jpg&quot; alt=&quot;Coming home from Tech Mids Conference&quot; title=&quot;Coming home from Tech Mids Conference&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;P.S - If anyone knows how to take good a selfie whilst facing the camera into a cinema projector. . . please let me know. It’s turning into a recurring problem 😂&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/techmids-beats-talk.jpg&quot; alt=&quot;Tony Edwards at Tech Mids Conference&quot; title=&quot;Tony Edwards at Tech Mids Conference&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 14 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/tech-mids-is-fin/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/tech-mids-is-fin/</guid>
      </item>
    
      <item>
        <title>The end of the HalfStack era</title>
        <description>&lt;p&gt;I’ve never been so sad to have a day watching fun talks, have conversations with friends, all whilst munching tasty pizza and late night bagels.&lt;/p&gt;

&lt;p&gt;Why???&lt;/p&gt;

&lt;p&gt;HalfStack London is fin. . . but it went out with the creative flair that I’ve come to love about Londons Tech Community. Over the past nine years, this conference has been a highlight of each and every year for a multitude of reasons.&lt;/p&gt;

&lt;p&gt;Every talk added something to the event, with a few highlights coming via Jo Francetti, Eduardo Cardenes, Leo Rivera, Carly Richmond and Steve Goodwin. Combined, they served up sessions based around LLM assisted procedural generation, cutting edge APIs, Star Wars themed vector databases, advice on progressing through a company, with a dash of midi madness thrown in for good luck.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/hs-jo.jpg&quot; alt=&quot;Jo Francetti speaking at HalfStack&quot; title=&quot;Jo Francetti speaking at HalfStack&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/hs-eduardo.jpg&quot; alt=&quot;Eduardo Cardenes at HalfStack&quot; title=&quot;Eduardo Cardenes at HalfStack&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/hs-leo.jpg&quot; alt=&quot;Leo Rivera at HalfStack&quot; title=&quot;Leo Rivera at HalfStack&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/hs-steve.jpg&quot; alt=&quot;Steve Goodwin talking MIDI&quot; title=&quot;Steve Goodwin talking MIDI&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In all honesty, these were the standout sessions because they were the ones I caught. Every other talk would have made the list, but with so many interesting attendees to chat with, the hallway track was as popular as ever. Plans for 2026 were hatched, ideas for talks bounced around, and musical collaborations planned.&lt;/p&gt;

&lt;p&gt;So why is this conference so special to me?&lt;/p&gt;

&lt;p&gt;As a student, it was the first one I attended outside of the southwest and got to meet the people whose tutorials I was following. It was the conference that really sparked my love of tech events. It was a place where I got to meet future friends, collaborators, and speakers for my events. It’s the gathering that I wrote my most popular talk for, one which is still paying dividends all these years later.&lt;/p&gt;

&lt;p&gt;It’s the event that opened my eyes to the broader tech industry beyond bashing out code.&lt;/p&gt;

&lt;p&gt;Whilst the London outing of the conference is coming to a close. . . for now at least. . . the things it’s added to my life will remain until the end of time.&lt;/p&gt;

&lt;p&gt;A massive thank you to Dylan for putting on the jewel in the conf crown, and for the support with various adventures over the years.&lt;/p&gt;
</description>
        <pubDate>Wed, 12 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/end-of-the-halfstack-era/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/end-of-the-halfstack-era/</guid>
      </item>
    
      <item>
        <title>WhatTheStack Community Conference, Skopje</title>
        <description>&lt;p&gt;WTF was that WTS!?!&lt;/p&gt;

&lt;p&gt;To call &lt;a href=&quot;https://wts.sh/&quot;&gt;WhatTheStack&lt;/a&gt; a conference would be doing it a disservice.&lt;/p&gt;

&lt;p&gt;Community conference comes closer. But still not quite right. Even amongst the best grassroots tech events in Europe(ish) , this one stood out amongst them all. And not just for the conference itself.&lt;/p&gt;

&lt;p&gt;Skopje offered the perfect location for a late summer tech event. Clear blue skies provided the backdrop for a architecturally interesting city. Vienna-esque grandeur blended with Soviet style buildings to offer one of the most interesting walks to an event venue ever, with the venue itself offering a peek inside a great example of the brutalist style.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/whatthestackconf-statue.jpg&quot; alt=&quot;Not Alexander The Great&quot; title=&quot;Not Alexander The Great&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;But 30+ speakers didn’t descend on Macedonia from around the globe to take in the buildings, weather, and the THOUSANDS of statues. We were there to share our love of the web through our talks.&lt;/p&gt;

&lt;p&gt;We certainly did that!&lt;/p&gt;

&lt;p&gt;The big event on Saturday was preceded by a week of smaller events at &lt;a href=&quot;https://base42.mk/&quot;&gt;Base42&lt;/a&gt;, a hackerspace in the heart of the city. As part of it, I dropped some Beats, Rhymes, and Neural Nets on the audience. Thankfully, the audience were right into it. I’m always hesitant with this talk in far flung places, as not all cultures appreciate talks at the fun end of the spectrum. This lot. . . they appreciated it more than most 💪&lt;/p&gt;

&lt;p&gt;For the main conference, the speakers brought their A++ game. Despite the demo-gods not being on the side of everyone, the sessions were clearly a hit with audience. Whether you wanted to deep dive into React, Angular, (software) architecture, hear case studies, or be made to think, there was something for everyone. Whilst I didn’t get to see a whole host of the sessions, one of the ones I did really shone a light on how useful Supabase would be when prototyping software. Thanks &lt;a href=&quot;https://www.linkedin.com/in/prodromouf/&quot;&gt;Fanis&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/whatthestackconf-fanis.jpg&quot; alt=&quot;Fanis talking about Supabase&quot; title=&quot;Fanis talking about Supabase&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Once the audience had filtered away after the event, the awesomeness of the gathering really shone through. After comparing notes amongst the speaker group, the consensus is that attendees were proactive in seeking out speakers to talk to. Whilst this might not sound like much, typically you’d get a couple of “thanks, that was great” comments and maybe a question or two.&lt;/p&gt;

&lt;p&gt;Not at What the Stack.&lt;/p&gt;

&lt;p&gt;The community were keen to talk. Very keen in fact. And this is a great sign of a thriving, safe, and engaged community that you don’t get at many events, and one of the things a community conferences should be. Rough around the edges, but polished in the places that matter. Informal, but without becoming a collection of cliques. Honest to what it is, whilst trying to grow into something greater.&lt;/p&gt;

&lt;p&gt;This is a direct reflection of the team behind the event, and the communities in the city. To say the speakers were given a personal touch is an understatement. It was more of a concierge service. Want a table at a restaurant booked? Sure. Need a taxi? No problem. Want a day trip to Kosovo? Be ready at 9am. EVERY single tech event organiser, regardless of the scale of the gathering, could learn a thing or two from the team here.&lt;/p&gt;

&lt;p&gt;Overall, this has been my favorite conference in a very long time, with Skopje rocketing to the top three of my favorite cities. If you are a speaker in the web world, follow the conf page and keep an eye out for next years CFP. You won’t regret it.&lt;/p&gt;

&lt;p&gt;If you are lucky enough to be selected, and you ask nicely, &lt;a href=&quot;https://www.faziz-dev.com/&quot;&gt;Faris&lt;/a&gt; might even buy you a post-event ice cream as well 🙏&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://tonyedwardspz.co.uk/assets/images/2025/whatthestackconf-icecream.jpg&quot; alt=&quot;Faris treating us to Ice Cream&quot; title=&quot;Faris treating us to Ice Cream&quot; loading=&quot;lazy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Hope to see you there in 2026!&lt;/p&gt;
</description>
        <pubDate>Sat, 20 Sep 2025 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/what-the-stack-conference/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/what-the-stack-conference/</guid>
      </item>
    
      <item>
        <title>Putting it to the test</title>
        <description>&lt;p&gt;For the past few years I’ve been learning German on and off. Today the is the day my approach is to be put to the test.&lt;/p&gt;

&lt;p&gt;Instead of spending an extortionate amount of time with apps, books, and AI tools the method has essentially been to overwhelm my brain with the language without worrying what is being said. Almost without exception, every audio book, podcast, book, TV show, song, and Formula 1 race has been purposely undecipherable. The theory. . . no German word will ever take me by surprise.&lt;/p&gt;

&lt;p&gt;It’s been a weird experience.&lt;/p&gt;

&lt;p&gt;Whilst I only know the very basics of the language off by heart, I can recognise and say hundreds of words without knowing what they mean. Reading basic text out loud is no problem. And, hopefully, being a host of Europe’s largest software development conference in Berlin won’t present too many linguistic challenges.&lt;/p&gt;

&lt;p&gt;If all else fails, they’ll be treated to a few raps to fill the time.&lt;/p&gt;

&lt;p&gt;Whilst I might struggle to order a meal in German, I’m fully prepped to rock the karaoke stage 🎤&lt;/p&gt;

&lt;p&gt;Gotta have your priorities right 😎&lt;/p&gt;
</description>
        <pubDate>Tue, 08 Jul 2025 00:00:00 +0000</pubDate>
        <link>https://tonyedwardspz.co.uk/blog/put-it-to-the-test/</link>
        <guid isPermaLink="true">https://tonyedwardspz.co.uk/blog/put-it-to-the-test/</guid>
      </item>
    
  </channel>
</rss>
