R3Utility 0.2.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package R3Utility --version 0.2.0                
NuGet\Install-Package R3Utility -Version 0.2.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="R3Utility" Version="0.2.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add R3Utility --version 0.2.0                
#r "nuget: R3Utility, 0.2.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install R3Utility as a Cake Addin
#addin nuget:?package=R3Utility&version=0.2.0

// Install R3Utility as a Cake Tool
#tool nuget:?package=R3Utility&version=0.2.0                

R3Utility

A utility library for Cysharp/R3 that provides enhanced reactive programming capabilities, focusing on validation and property binding.

Features

Two-Way Binding Extensions

  • Convert INotifyPropertyChanged properties to BindableReactiveProperty
  • Automatic value propagation in both directions
  • Support for deep property path binding (up to 3 levels)

Reactive Validation

  • Combine multiple boolean observables with various logical operations
  • Support for creating executable command sources based on validation states

Observable Element Property Monitoring (New)

  • Observe changes in specific properties of elements within a collection.
  • Customizable option, pushCurrentValueOnSubscribe to control initial value emission.
  • Support for deep property path binding (up to 3 levels)

API Reference

ReactivePropertyExtensions

Method Parameters Return Type Description
ToTwoWayBindableReactiveProperty<T, TProperty> T value, Expression<Func<T, TProperty>> propertySelector BindableReactiveProperty<TProperty> Converts a single property to two-way bindable reactive property
ToTwoWayBindableReactiveProperty<T, TProperty1, TProperty2> T value, Func<T, TProperty1?> propertySelector1, Func<TProperty1, TProperty2> propertySelector2 BindableReactiveProperty<TProperty2> Converts a nested property (2 levels) to two-way bindable reactive property
ToTwoWayBindableReactiveProperty<T, TProperty1, TProperty2, TProperty3> T value, Func<T, TProperty1?> propertySelector1, Func<TProperty1, TProperty2?> propertySelector2, Func<TProperty2, TProperty3> propertySelector3 BindableReactiveProperty<TProperty3> Converts a deeply nested property (3 levels) to two-way bindable reactive property

ReactiveValidationHelper

Method Parameters Return Type Description
CombineLatestValuesAreAllFalse IEnumerable<Observable<bool>> Observable<bool> Combines multiple observables and returns true only when all source values are false
CombineLatestValuesAreAllTrue IEnumerable<Observable<bool>> Observable<bool> Combines multiple observables and returns true only when all source values are true
CombineLatestValuesAreAnyFalse IEnumerable<Observable<bool>> Observable<bool> Combines multiple observables and returns true when any source value is false
CombineLatestValuesAreAnyTrue IEnumerable<Observable<bool>> Observable<bool> Combines multiple observables and returns true when any source value is true
CreateCanExecuteSource IBindableReactiveProperty[] Observable<bool> Creates an observable that monitors HasErrors property of multiple BindableReactiveProperty instances

ObservableCollectionsExtensions

Method Parameters Return Type Description
ObserveElementProperty<T, TProperty> IObservableCollection<T> source, Func<T, TProperty> propertySelector, bool pushCurrentValueOnSubscribe = true, CancellationToken cancellationToken = default Observable<PropertyPack<T, TProperty>> Observes a specific property of each element in a collection and emits its values.
ObserveElementProperty<T, TProperty1, TProperty2> IObservableCollection<T> source, Func<T, TProperty1?> propertySelector1, Func<TProperty1, TProperty2> propertySelector2, bool pushCurrentValueOnSubscribe = true, CancellationToken cancellationToken = default Observable<PropertyPack<T, TProperty2>> Observes a nested property (2 levels) in a collection and emits its values.
ObserveElementProperty<T, TProperty1, TProperty2, TProperty3> IObservableCollection<T> source, Func<T, TProperty1?> propertySelector1, Func<TProperty1, TProperty2> propertySelector2, Func<TProperty2, TProperty3> propertySelector3, bool pushCurrentValueOnSubscribe = true, CancellationToken cancellationToken = default Observable<PropertyPack<T, TProperty3>> Observes a deeply nested property (3 levels) in a collection and emits its values.

Usage Examples

Two-Way Binding

// Create a BindableReactiveProperty<T> that is two-way bound
BindableReactiveProperty<string> name = item.ToTwoWayBindableReactiveProperty(x => x.Name);

// This will also update the Name property of the item object
name.Value = "X"; //item.Name = "X"

// This will also update the Value property of the BindableReactiveProperty
item.Name = "Y"; //name.Value = "Y"


// Deep property path binding
BindableReactiveProperty<string> nestedProperty = viewModel.ToTwoWayBindableReactiveProperty(
    x => x.User,
    x => x.Profile,
    x => x.DisplayName
);

Validation Helpers

// Combine multiple validation states
Observable<bool> isValid = ReactiveValidationHelper.CombineLatestValuesAreAllTrue(
      emailValidation,
      passwordValidation,
      termsAccepted
);

// Create executable command source
Observable<bool> canExecute = ReactiveValidationHelper.CreateCanExecuteSource(
      emailProperty,
      passwordProperty
);
command = canExecute.ToReactiveCommand();

Observing Properties in a Collection

using ObservableCollections;
using R3;
using R3Utility;

ObservableList<Item> collection = [];
Item item1 = new() { Name = "foo" };

collection.Add(item1);
var disposable = collection.ObserveElementProperty(x => x.Name, pushCurrentValueOnSubscribe: false)
                           .Subscribe(property => Console.WriteLine($"Instance:{property.Instance}, propertyName:{property.PropertyName}, Value:{property.Value}"));
        
//Changes are output. `Instance:WpfApp1.Item, propertyName:Name, Value:bar`
item1.Name = "bar";

disposable.Dispose();

Installation

dotnet add package R3Utility

License

R3Utility is distributed under a free and open-source license. Feel free to use it in your projects!

Contributions

We welcome contributions to the R3Utility project! If you have any suggestions, bug reports, or feature requests, please feel free to open an issue or submit a pull request. We're excited to make R3Utility better together.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 is compatible. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.2.1 73 11/23/2024
0.2.0 82 11/16/2024
0.1.0 105 11/9/2024