The Rise of C# Markup for Cross Platform Development

Dating back to the early days of WPF, developers have been asking for a way to build native applications in C#, and only C#. Recently, our team announced C# Markup, which combines the full power of C# with a declarative, fluent-style API for defining the application user interface. This means any .NET cross-platform application powered by Uno Platform can be developed entirely in C#, both for the layout and the business logic.

Catch up on what you've missed

Want to learn more about C# markup? Check out the Uno Platform 5.0 webinar as the team goes in-depth on the most significant Uno Platform advancements.

What is C# Markup

C# Markup is a declarative, fluent-style syntax for defining the layout of an application in C#. It’s not a new language and it doesn’t require learning additional types. C# markup, while new to some developers, maintains a familiar feel to XAML development. It uses the same UI components as any Uno Platform app, such as buttons, text blocks, text boxes, sliders, etc. While also keeping the method for declaring and arranging, the application’s layout in C# markup is comparable to the approach used in XAML. 

C# Markup offers a strongly typed API, providing benefits like Intellisense and compile-time validation, helping developers identify errors early in coding. It supports standard WinUI controls, Uno.Toolkit, Uno.Extensions and third-party control libraries through its source generator without requiring vendor modifications.

C# Markup supports the same feature set as traditional XAML markup, including data binding, styles, resources, templates, and visual states. It allows the use of resources, converters, commands, and direct calls to properties, methods, and functions. Using C# Markup still maintains a clear separation between UI and business logic and integrates seamlessly with existing namespaces used in Uno Platform and WinUI controls.

To improve development speed further, C# Markup supports Hot Reload for controls, properties, layout, bindings, templates, resources and global resources.

Let’s dig into some code samples to exemplify how you’d approach common tasks with C# Markup.

Building an application with C# Markup

Define Page and Control Layout

Use C# to define the layout of pages and controls in your application. This code adds a TextBlock as the Content for the MainPage, with the Text property set to “Hello Uno Platform”.

				
					public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.Content(
            new TextBlock()
                .Text("Hello Uno Platform!")
        );
    }
}


				
			

Existing Controls

Use the controls you’re familiar with – just call their constructor to add them. This code nests the TextBlock from the previous example in a StackPanel and adds an Image that will appear under the TextBlock.

				
					this.Content(
    new StackPanel()
        .Children(
            new TextBlock()
                .Text("Hello Uno Platform!")
            new Image()
        )
)

				
			

Properties as Extension Methods

Generated methods provide a fluent-style API for setting control properties. In this code, we’re setting the Image’s Margin, HorizontalAlignment, Width, Height, and Source properties.

				
					new Image()
        .Margin(12)
        .HorizontalAlignment(HorizontalAlignment.Center)
        .Width(150)
        .Height(150)
        .Source("ms-appx:///Counter/Assets/logo.png")

				
			

Robust Layouts with Grids:

Enables sophisticated UI designs with minimal effort, paving the way for more robust UIs. In this example, the code creates a new Grid with four rows and three columns. A TextBlock is added to the Grid in Row 3 and Column 2.

				
					new Grid()
    .RowDefinitions("*,*,*,Auto")
    .ColumnDefinitions("*,*,Auto")
    .Children(
        new TextBlock()
            .Grid(row: 3, column: 2)
    )



				
			

More information on Attached Properties at our docs.

MVVM, MVUX and Data Binding:

Supports data binding, including converters and supporting different binding modes. Both MVVM (for example using CommunityToolkit.Mvvm) and MVUX (Uno.Extensions.Reactive) can be data bound to elements to facilitate transient state management.

Strongly Typed Data Binding:

Set the DataContext type to use strongly typed data binding. This code uses the DataContext method to set a new instance of MainViewModel as the DataContext on the page. The Count property of the MainViewModel is data bound to the Text property of the TextBlock, using an inline conversion from an integer to a string value.

				
					this.DataContext(new MainViewModel(), (page, vm) => page
    .Content(
       new TextBlock()
            .Margin(12)
            .HorizontalAlignment(HorizontalAlignment.Center)
            .TextAlignment(Microsoft.UI.Xaml.TextAlignment.Center)
            .Text(() => vm.Count, count => $"Counter: {count}")
    )
)

				
			

More information on Data Binding at our docs.

Using Static and Theme Resource:

Consume existing static and theme resources using the StaticResource and ThemeResource extension methods. This code sets the Background on the page to the ApplicationPageBackgroundThemeBrush theme resource.

				
					this.Background(ThemeResource.Get<Brush>
    ("ApplicationPageBackgroundThemeBrush"));
				
			

More information on Consuming Resources at our docs.

Custom Resources

Create both static and theme resources. This example adds a new Color resource, MyColor, with values Red and White for the Light and Dark themes, respectively, as a resource for the page.

				
					this.Resources(resources => resources
        .Add("MyColor", Colors.Red, Colors.White))

				
			

More information on Adding Resources at our docs.

Explicit and Implicit Styles:

Override existing styles or create your own implicit or explicit styles for controls. This code creates an explicit TextBlock Style, named LargeTextBlockStyle, that sets the FontSize to 42. It also creates an implicit Style that’s based on the LargeTextBlockStyle and also sets the Foreground color on the TextBlock.

				
					this.Resources(resources => resources
    .Add("LargeTextBlockStyle",
        new Style<TextBlock>()
            .Assign(out var largeTextBlockStyle)
            .Setters(s => s.FontSize(42))
    )
    .Add(
        new Style<TextBlock>()
            .BasedOn(largeTextBlockStyle)
            .Setters(s => s.Foreground(Theme.Brushes.Primary.Default))
    )
);
				
			

More information on Styles at our docs.

Hot Reload for Rapid C# Development

Our Hot Reload feature accelerates UI development, offering instant feedback and fostering an iterative design process. See it in action below:

Custom and third-party Controls:

C# Markup isn’t just about simplicity; it’s also about power. Using libraries like SKIA Sharp, or the Windows Community Toolkit, for custom controls demonstrates C# Markup’s capability to create complex user experiences.

More information on Extensions for 3rd party controls at our docs.

Figma to C# Markup

Working C# Markup for creating UI is great. Easily converting Figma designs into C# Markup is even better. The Uno Platform Figma Plugin is designed to take care of the time-consuming task normally associated with hand-coding UI markup, either with C# markup or XAML. This lets developers focus on what they’re best at without getting bogged down in the details of high-fidelity designs.

See how to integrate it in your workflow with our Tube Player workshop.

Embracing the Future with C# Markup

C# Markup is a forward-looking solution needed by modern .NET app developers. Its harmonious blend of UI and business logic, compatibility, and flexibility make it an indispensable tool for .NET developers. As the application development landscape continues to evolve, C# Markup is well-positioned to be a cornerstone in the future of application development.

Give C# a try using our  Simple Calc application & workshop or our more advanced workshop Tube Player. For more information on C# Markup, check out the developer documentation.

Next Steps

C# Markup represents a forward-thinking approach; its harmonious blend of UI and business logic, compatibility, and flexibility make it an indispensable tool for contemporary .NET developers. As the application development landscape continues to evolve, C# Markup is well-positioned to be a cornerstone in the future of application development.

Give C# markup a try using our Counter workshop and Simple Calc workshop. For a more advanced workshop, try out our Tube Player. To upgrade to the latest release of Uno Platform, please update your packages to 5.0 via your Visual Studio NuGet package manager! For more information on C# Markup, check out the developer documentation.

Uno Platform

Uno Platform

Follow us on Twitter

Tags: