Skip to content

ReactiveUI

A family of open-source .NET libraries for building apps. Use them together, or pick only the one you need.

Get started Browse on GitHub

Build your app

These libraries shape how your app fits together. Several of them use streams. A stream is a series of values that arrive over time, such as each new value of a property. You subscribe to a stream to receive its values.

  • ReactiveUI


    A model-view-viewmodel (MVVM) framework for WPF, WinForms, WinUI, MAUI, Avalonia and Uno. MVVM keeps screen logic in a view model class that you can test without a UI. Here the Save button turns off while the name is empty.

    IObservable<bool> canSave = this.WhenAnyValue(
        x => x.Name, name => !string.IsNullOrWhiteSpace(name));
    
    Save = ReactiveCommand.CreateFromTask(SaveAsync, canSave);
    

    Docs · GitHub

  • ReactiveUI.Binding


    Keeps a view and a view model in step. A source generator writes the binding code when you build, so bindings are safe to trim and to publish with Native AOT. Dispose a binding to stop it.

    // The text box shows Name, and typing updates Name.
    using var binding = view.Bind(
        viewModel, vm => vm.Name, v => v.NameBox.Text);
    

    Docs · GitHub

  • ReactiveUI.Validation


    Adds validation rules to a view model. Each rule names a property, a check and the message to show when the check fails.

    this.ValidationRule(
        vm => vm.Email,
        email => email?.Contains('@') == true,
        "Enter a valid email address.");
    

    Docs · GitHub

  • Sextant


    Navigation that starts from the view model. You open and close pages by naming view models, so you can test navigation without a UI.

    // Show the page for DetailsViewModel, then go back.
    await viewStack.PushPage<DetailsViewModel>();
    await viewStack.PopPage();
    

    Docs · GitHub

Foundations

Every library on this page uses ReactiveUI.Primitives for its streams. ReactiveUI, ReactiveUI.Binding, Akavache and Fusillade also use Splat. You can use either one on its own.

  • Splat


    A service locator and logging for every .NET platform. A service locator is one shared place that hands out services. Register a service when your app starts, then ask for it anywhere.

    AppLocator.CurrentMutable.RegisterLazySingleton<IWeatherService>(
        () => new WeatherService());
    
    var weather = AppLocator.Current.GetService<IWeatherService>();
    

    Docs · GitHub

  • ReactiveUI.Primitives


    Small, fast streams, ready for Native AOT. Turn events, timers and tasks into streams. Then shape them with operators, methods that take a stream and return a new one. Calm waits for 300 ms of quiet.

    using var search = Signal.FromEventPattern(
            h => box.TextChanged += h, h => box.TextChanged -= h)
        .Select(_ => box.Text)
        .Calm(TimeSpan.FromMilliseconds(300))
        .Subscribe(RunSearch);
    

    Docs · GitHub

Data and networking

These libraries call web services and keep data on the device. None of them needs ReactiveUI.

  • Refit


    Turns a C# interface into a REST client. An attribute on each method describes the request, and Refit writes the code that sends it. Refit takes advantage of System.Text.Json source generation to read JSON without reflection. AppJsonContext is only this example's name for your context class.

    public interface IGitHubApi
    {
        [Get("/users/{user}")]
        Task<User> GetUserAsync(string user, CancellationToken token);
    }
    
    var api = RestService.ForGenerated<IGitHubApi>(
        httpClient, AppJsonContext.Default);
    

    Docs · GitHub

  • Akavache


    Stores objects on the device: a cache, user settings and encrypted secrets. Ask for a key, and Akavache returns the saved copy, or fetches a new one when the copy is missing or has expired.

    var news = await CacheDatabase.LocalMachine.GetOrFetchObject(
        "news",
        () => api.GetNewsAsync(),
        DateTimeOffset.Now.AddHours(1));
    

    Docs · GitHub

  • Punchclock


    A queue that limits how many tasks run at once. When a slot frees up, the task with the highest priority runs next.

    using var queue = new OperationQueue(maximumConcurrent: 2);
    
    var page = queue.Enqueue(1, () => http.GetStringAsync(pageUrl));
    var urgent = queue.Enqueue(10, () => http.GetStringAsync(urgentUrl));
    await Task.WhenAll(page, urgent);
    

    Read the guide on GitHub

  • Fusillade


    An HttpClient handler that sends requests in order of importance. Requests the user waits on go first, background work waits, and identical requests share one download.

    using var client = new HttpClient(
        NetCache.UserInitiated, disposeHandler: false);
    
    string json = await client.GetStringAsync(url);
    

    Read the guide on GitHub

Open source

Every library here is free for commercial use under an OSI-approved licence. The ReactiveUI Association and its contributors maintain them. Contribute or sponsor the work.