uno-csharp-markup

star 4

C# Markup for Uno Platform: code-first UI with fluent API, strongly-typed data binding, resources, styles, templates, and Uno Toolkit integration. Use when: (1) Building UI in C# instead of XAML, (2) Using fluent data binding with expression trees, (3) Applying styles and templates in C# Markup, (4) Integrating Uno Toolkit controls in C# Markup, (5) Setting up a C# Markup project from scratch, (6) Converting XAML patterns to C# Markup. Do NOT use for: XAML-based UI (see winui-xaml) or Toolkit control reference (see uno-toolkit).

mtmattei By mtmattei schedule Updated 4/4/2026

name: uno-csharp-markup description: "C# Markup for Uno Platform: code-first UI with fluent API, strongly-typed data binding, resources, styles, templates, and Uno Toolkit integration. Use when: (1) Building UI in C# instead of XAML, (2) Using fluent data binding with expression trees, (3) Applying styles and templates in C# Markup, (4) Integrating Uno Toolkit controls in C# Markup, (5) Setting up a C# Markup project from scratch, (6) Converting XAML patterns to C# Markup. Do NOT use for: XAML-based UI (see winui-xaml) or Toolkit control reference (see uno-toolkit)." intent: >- Build Uno Platform UI using C# Markup fluent API with strongly-typed data binding, resources, styles, and templates. best_for: - "Building UI in C# instead of XAML" - "Using fluent data binding with expression trees" - "Integrating Toolkit controls in C# Markup" license: "Apache 2.0 (patterns derived from Uno Platform documentation)" metadata: version: "1.0.0"

Uno Platform C# Markup

Declarative, fluent-style C# syntax for building Uno Platform UIs. Same underlying object model as XAML with compile-time validation, IntelliSense, and refactoring support.

Setup

Select C# Markup in the project template:

dotnet new unoapp -markup csharp

Add CSharpMarkup to UnoFeatures for existing projects:

<UnoFeatures>
    CSharpMarkup;
    Material;
    Toolkit;
</UnoFeatures>

Pages use .cs files instead of .xaml + .xaml.cs pairs.

Core Patterns

Creating Controls and Setting Properties

Fluent API chains property setters. Type conversion is automatic for common types (Thickness, Brush, Color, CornerRadius, FontFamily).

new TextBlock()
    .Margin(12)                              // auto-converts int to Thickness
    .TextAlignment(TextAlignment.Center)     // strongly typed enum
    .Text("Hello Uno Platform!")

Children and Content

new StackPanel()
    .VerticalAlignment(VerticalAlignment.Center)
    .HorizontalAlignment(HorizontalAlignment.Center)
    .Children(
        new TextBlock().Text("First"),
        new TextBlock().Text("Second"),
        new Button().Content("Click me")
    )

DataContext and Binding

Use expression trees for strongly-typed binding. The vm parameter is a placeholder, not a live reference.

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.DataContext(new MainViewModel(), (page, vm) => page
            .Background(ThemeResource.Get<Brush>("ApplicationPageBackgroundThemeBrush"))
            .Content(
                new StackPanel()
                    .VerticalAlignment(VerticalAlignment.Center)
                    .Children(
                        new TextBlock()
                            .Text(() => vm.Count, count => $"Counter: {count}"),
                        new TextBox()
                            .Text(x => x.Bind(() => vm.Step).TwoWay()),
                        new Button()
                            .Command(() => vm.IncrementCommand)
                            .Content("Increment")
                    )
            )
        );
    }
}

Binding modes:

  • Default (OneWay): () => vm.Property
  • TwoWay: .Text(x => x.Bind(() => vm.Property).TwoWay())
  • OneTime: .Text(x => x.Bind(() => vm.Property).OneTime())

Without ViewModel instance (type-only):

this.DataContext<MainViewModel>((page, vm) => page
    .Content(...)
);

Resources

Access theme and static resources with strongly-typed API:

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

// Static resource
new TextBlock()
    .Style(StaticResource.Get<Style>("TitleLarge"));

Styles

new TextBlock()
    .Style(new Style<TextBlock>()
        .Setters(s => s
            .Foreground(ThemeResource.Get<Brush>("OnSurfaceBrush"))
            .FontSize(24)
        )
    )

Templates

new ListView()
    .ItemsSource(() => vm.Items)
    .ItemTemplate<MyItem>(item =>
        new StackPanel()
            .Orientation(Orientation.Horizontal)
            .Children(
                new TextBlock().Text(() => item.Name),
                new TextBlock().Text(() => item.Description)
            )
    )

Uno Toolkit in C# Markup

Toolkit controls work with the same fluent API:

using Uno.Toolkit.UI;

new AutoLayout()
    .Spacing(16)
    .Padding(24)
    .PrimaryAxisAlignment(AutoLayoutAlignment.Center)
    .Children(
        new NavigationBar().Content("Page Title"),
        new SafeArea()
            .Insets(SafeArea.InsetMask.Top | SafeArea.InsetMask.Bottom)
            .Child(
                new TextBlock().Text("Safe content")
            )
    )

ResponsiveExtension in C# Markup

Responsive values require XAML-style markup extensions. In C# Markup, use adaptive logic or VisualStateManager instead:

// Use VisualStateManager for responsive layouts in C# Markup
new Grid()
    .VisualStateManager(vsm => vsm
        .Group(g => g.Name("WidthStates")
            .State(s => s.Name("Narrow")
                .StateTriggers(new AdaptiveTrigger() { MinWindowWidth = 0 })
                .Setters(/* narrow layout */)
            )
            .State(s => s.Name("Wide")
                .StateTriggers(new AdaptiveTrigger() { MinWindowWidth = 800 })
                .Setters(/* wide layout */)
            )
        )
    )

MVUX with C# Markup

C# Markup pairs naturally with MVUX models. Bind directly to Feed/State properties:

this.DataContext<MainModel>((page, vm) => page
    .Content(
        new FeedView()
            .Source(() => vm.Items)
            .DataTemplate<ItemViewModel>(item =>
                new TextBlock().Text(() => item.Name)
            )
    )
);

Common Mistakes

  • Using string-based {Binding} syntax instead of expression-tree bindings
  • Forgetting that vm is a placeholder, not a live object (don't call methods on it outside binding expressions)
  • Setting DataContext in code-behind AND in the fluent chain (double initialization)
  • Not adding CSharpMarkup to UnoFeatures (extension methods won't be generated)
  • Mixing XAML and C# Markup in the same page (use one or the other per page)

Related Skills

Skill Use instead when...
winui-xaml Writing UI in XAML instead of C# Markup
uno-toolkit Looking up Toolkit control APIs, properties, or XAML examples
uno-platform-agent Setting up projects, MVVM/MVUX patterns, or navigation
uno-extensions-services Configuring hosting, DI, authentication, or HTTP clients

XAML Equivalence and Limitations

For a full XAML-to-C# Markup mapping table, see references/01-getting-started.md. Key limitations: Hot Design supports XAML only (not C# Markup), {utu:Responsive} needs VisualStateManager alternatives, and x:Uid localization requires manual ResourceLoader usage.

Detailed References

Install via CLI
npx skills add https://github.com/mtmattei/UnoPlatformSkills --skill uno-csharp-markup
Repository Details
star Stars 4
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator