Early experimental release

Build Avalonia UI with Akbura

A declarative .NET UI language and compiler with reactive state, typed styling, and direct access to Avalonia controls.

.NET Avalonia Reactive state AKCSS
Counter.akbura
using Avalonia.Controls;

state int count = 0;

<StackPanel Spacing="12">
    <TextBlock Text={$"Count: {count}"}/>
    <Button Click={count++}>
        Increment
    </Button>
</StackPanel>

Declarative components

Compose native Avalonia controls with concise, readable markup.

Reactive state

Declare state, bindings, effects, and commands close to the UI that uses them.

Native Avalonia

Use Avalonia controls, properties, routed events, and host integration directly.

Typed AKCSS

Style controls with semantic property binding, utilities, and reusable layers.

Feature Support level Notes
Compatibility with Avalonia Full Akbura components can be used directly in AXAML views and vice versa – any Avalonia control (including custom controls) works without extra attributes or imports.
MarkupExtensions Partial Common markup extensions (StaticResource, DynamicResource, Binding) work exactly as in Avalonia. The IServiceProvider supplies IProvideValueTarget, IRootObjectProvider, IUriContext, IXamlTypeResolver, and IAvaloniaXamlIlEagerParentStackProvider. The old {} syntax is replaced by ${} (no quotes). XML‑element syntax for markup extensions, MarkupExtensionOptionAttribute, and some advanced scenarios are not supported.
Binding Full Bindings are fully supported: both ReflectionBinding and CompiledBinding work, including BindingPath parsing, mode selection, converters, etc.
TemplateContent Full Properties decorated with [TemplateContent] are automatically handled – Akbura generates an IDeferredContent implementation, so templates work out of the box.

Quick Start

Experimental

Akbura is under active development. Syntax, generated code, and runtime APIs may change between releases.

Install the package:

dotnet add package Akbura

Create Counter.akbura:

using Avalonia.Controls;

namespace Demo.Pages;

state int count = 0;

<StackPanel Spacing="12">
    <TextBlock Text={$"Count: {count}"}/>
    <Button Click={count++}>Increment</Button>
</StackPanel>

Use the generated component directly inside an Avalonia AXAML view:

<UserControl
    xmlns="https://github.com/avaloniaui"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:pages="using:Demo.Pages">

    <pages:Counter />

</UserControl>

Akbura components are Avalonia controls, so no separate host control is required.

What Akbura Is

Akbura is a library and compiler for Avalonia, not a replacement framework.

It adds a declarative component language, reactive state, typed expressions, hooks, commands, and AKCSS while continuing to use native Avalonia controls and APIs.

An .akbura file declares one component:

Pages/Counter.akbura -> Demo.Pages.Counter

Generated components are partial and can be extended with regular C#.

Components and Markup

Akbura markup uses Avalonia controls directly:

state string title = "Dashboard";
state bool isOpen = false;

<StackPanel>
    <TextBlock Text={title}/>
    <Button Click={isOpen = true}>Open</Button>
    <Border IsVisible={isOpen}/>
</StackPanel>

Attributes may contain literals, C# expressions, bindings, and markup extensions.

Reactive State

Declare local reactive values with state:

state int selectedIndex = 0;
state string query = "";

State may also connect to object properties:

state MyViewModel vm = new MyViewModel();

state string name = bind vm.Name;
state string fullName = out vm.FullName;
state string surname = in vm.Surname;

Parameters

Parameters define a component's public API:

param int UserId = 1;
param string Title;
param bind string Search = "";
param out TaskItem SelectedTask;

Parameters without default values are required. bind enables two-way flow, while out publishes a value to the parent.

Binding

Akbura supports Avalonia bindings directly in markup:

<TextBlock Text=${Binding Title} />
<TextBox Text=${Binding Search, Mode=TwoWay} />

Bindings are resolved against the expected property type and may be compiled when a data type is known.

Inside item templates, Akbura can infer the item type from ItemsSource. A template must contain a single root control, so multiple child controls should be wrapped in a panel:

<ItemsControl ItemsSource={Vm.Items}>
    <ItemsControl.ItemTemplate x.ItemName="item">
        <StackPanel Spacing="6">
            <TextBlock Text=${Binding Title} />

            <Button Click={() => Open(item)}>
                Open {item.Id.ToString("D")} — {item.Title}
            </Button>
        </StackPanel>
    </ItemsControl.ItemTemplate>
</ItemsControl>

x.ItemName exposes the current item as a typed variable. The item can participate in property expressions, event handlers, method calls, and inline content expressions.

Use x.DataType when the item type cannot be inferred automatically.

Markup Extensions

Akbura does not restrict markup attributes to a special binding-only syntax. Regular markup extensions can be used directly alongside C# expressions and literals:

<TextBlock Text=${Binding Title} />
<Border Background=${StaticResource CardBackground} />
<Border BorderBrush=${DynamicResource AccentBrush} />

Custom markup extensions are also supported when they expose a compatible constructor and ProvideValue method:

<TextBlock Text=${Format 1, Value={count}‎} />

The compiler resolves the extension type, constructor arguments, properties, ProvideValue, and the conversion to the target Avalonia property type.

Effects and Hooks

useEffect runs after rendering and can react to dependencies:

using Akbura.Hooks;

state int count = 0;

useEffect(
    () => Console.WriteLine(count),
    [count]);

Akbura also supports Avalonia-property hooks and experimental user-defined hooks.

Commands

Commands expose typed operations with reactive execution state:

command int Refresh(int userId);

<Button Click={async () => {
    var result = await Refresh.Execute(42);
    Console.WriteLine(result);
}‎}>
    Refresh
</Button>

Command facades provide Execute, CanExecute, and IsExecuting.

AKCSS

AKCSS is Akbura's typed styling language:

@akcss {
    .card {
        Padding: (10, 20);
        Background: White;
    }
}

<Border class="card"/>

AKCSS supports reusable classes, utilities, @apply, conditional rules, resources, imports, and C# interceptors.

Project Status

Akbura is experimental and is not yet intended as a stable production library.

Current limitations include:

  • markup-level @if, @else, @for, and @foreach are not supported;
  • some APIs and generated code may change without backward compatibility.

Community and Feedback

Ideas, bug reports, documentation improvements, and focused pull requests are welcome.

;