In my last post I introduced the idea of pattern-based XML literals—XML literals which construct arbitrary types other than
XAttribute/etc. And as promised, I have recorded a video showing off the practical benefits of this design when using Xamarin.Forms from VB.NET. If you’re not familiar with Xamarin.Forms it’s an API that abstracts over the differences between mobile platforms like Android and iOS to make it easier to create and maintain cross-platform apps while sharing the maximum amount of code. Watch as I explore the Xamarin VB sample app from the official Xamarin samples repo using this new prototype:
As you can see, it’s pretty empowering to be able to use XAML everywhere.
- I can leverage my XAML skills from WPF to a degree and be more productive.
- If I’m looking at the documentation or a sample or blog post (most likely written from a C# developer) that uses XAML, I can use that XAML in my code rather than first translating it to VB imperative code.
- In places where today you’d possibly have to give up markup for code like dynamic view creation, I can still use declarative XAML even if it’s in the middle of a VB method (this scenario comes up in writing VS extensions to the WPF editor too).
- Even with object initializers there can be situations where you have to fallback to imperative syntax like using attached properties but that’s not an issue using markup.
- I get to embed any VB expression inside my markup in places where that expressiveness is a benefit over XAML.
WPF XAML vs Xamarin XAML
Xamarin has its own flavor of XAML. It’s essentially the same on the surface (syntactically) as what’s used in WPF and Silverlight (and UWP) but it’s not the same XAML engine and it uses different types internally. Not just in the “Controls” or as Xamarin calls them “Views” but in the infrastructure itself:
- So rather than
DependencyProperty, Xamarin has
- Xamarin has its own base types for type converters, and markup extensions, etc.
So, even though both it and WPF use the XAML syntax (which is XML based), Xamarin.Forms is powered by a completely different engine entirely. Possibly as a consequence of this the XAML used by Xamarin.Forms doesn’t support VB.NET. Which would normally mean you have to create your UI imperatively, rather than declaratively. VB guru Klaus Löffelmann wrote about how to do this back in 2017 on the VB team blog. It was a good post but the no-XAML part was kind of a bummer. This prototype changes all of that!
The Xamarin differences actually highlight another benefit to being pattern-based. Because the language understands patterns—certain methods with certain names and shapes existing—rather than specific types (like
DependencyObject) it’s possible to apply the feature to a completely different system than WPF. If the feature were just WPF XAML literals built to understand the specifics of the WPF infrastructure you couldn’t turn around and apply it to Xamarin but by being pattern-based you can do that easily.
Under the hood
As I indicate in the video, the compiler knows XML and how to translate certain idioms in XML into call-outs to extension methods that encapsulate all of the Xamarin-specific knowledge. I’m pretty sure the pattern will change as I explore more but the first page’s code:
Translates to this:
As you can see, the compiler knows how to translate attribute values to enum members at compile-time. So if I misspell and enum member I’ll get a compile-time error:
Likewise the compiler knows how to translate an attribute value to a delegate creation, so that too gets compile-time validation:
Both of these make it easy to give in-context completion support in the IDE for these cases.
The keen observer may have also noticed that when I selected name
CalculateButton in the value of the
Name attribute at around the 2:45 mark in the video that references to
CalculateButton in code were highlighted. This is another example of the power of Roslyn. Because the compiler binds that text to the
CalculateButton variable, the IDE understands it as such and features like Go-to-Definition work automatically!
THIS IS A WORK IN PROGRESS!!!
I accidentally edited out the part where I show what turns a regular XML literal into a pattern based one and it’s a magic
"clr-namespace:" XML namespace import at the top of each file (could also be in a project-level import). If I comment out that import you can see that I get conversion errors because the XML reverts to producing an
XElement as it does today:
I expect to find a better way to enable the feature though because of some trade-offs with that approach. This is just a draft version of the pattern and I fully expect it to change as I explore other shapes of XML to apply it to and weigh certain experiences that could be built.
For example, right now the pattern respects both a
AddChildContent bridge methods so that the compiler can report an error if you include more than one child element in a situation where only one child is allowed, but maybe it’s better to simplify the pattern and enforce things like that in a Roslyn Analyzer (let me know what you think).
If you’re really curious as to what each of these bridge methods looks like, I’ve uploaded the content of the
XmlExtensions.vb file from the sample app I showed in the video as a Gist. It’s just what I wrote out while exploring the pattern and shouldn’t be taken as the “best way” to write such methods and I played around with different approaches. Just take it all with a grain of salt.
I know Xamarin.Forms has been around for quite awhile now but honestly I haven’t been as excited to try it out until now. I can see some places where the Xamarin team made extremely reasonable choices in their content model (like how templating works). I’m anxious to see how I can broaden the pattern to work well with those patterns and to just generally explore mobile app development from VB.NET.
Fun Fact: Due to Windows Mobile and Compact Framework and then Windows Phone and Windows 10 Mobile, I have not owned a phone that I couldn’t program in VB.NET in almost 15 years. I’m excited to continue that tradition.
One thing this video didn’t show off was tooling. Because it’s all just the VB.NET language and the IDE is powered by Roslyn, getting things like completion, go-to-definition, F1 help, etc. to work in such XML literals is much easier than it would have been pre-VS2015. Also, there’s this other unrelated prototype I plan to show off… 4-5 prototypes from now that could really improve on both desktop apps using WPF/WinForms and mobile apps using Xamarin too. So whether it’s to show off better tooling, to show off another prototype, or just because I’m having fun exploring Xamarin.Forms I don’t think this will be the last video I make featuring this topic.
As for my next post it’ll be a continuation of this series about this prototype but instead applied to web development. I think you’re going to love it so look out for it.
Until then, as always, thanks for reading, thanks for watching, please share this post, and let me know your thoughts in the comments below and/or on Twitter.
P.S. As in my last series, I’ll upload all of my notes from implementing the prototype in a GitHub issue after the last post in the series. Don’t sweat the specifics of the pattern too much, they’re subject to and very likely to change. This post took me much longer than intended before the first few iterations of the video were over 30-minutes! It took some re-recording and aggressive editing to get it down to 5.X minutes, but I think that’s optimal for online viewing and sharing. I hope you agree!
“I have made this [letter] longer than usual because I have not had time to make it shorter.”