Skip to content

Instantly share code, notes, and snippets.

@bradphelan
Created February 16, 2018 08:24
Show Gist options
  • Save bradphelan/a998fd7609c5f564785af800c76c5992 to your computer and use it in GitHub Desktop.
Save bradphelan/a998fd7609c5f564785af800c76c5992 to your computer and use it in GitHub Desktop.
public class TwoWayBindingWithConversionDemo
{
public class Model : ReactiveObject
{
/// <summary>
/// The model length will be in units meters
/// </summary>
[Reactive] public double LengthInMeters { get; set;}
}
public class ViewModel : ReactiveObject
{
public enum UnitsEnum
{
Meters
, Milliters
};
private readonly SubjectAsPropertyHelper<double> _Length;
[Reactive]
public UnitsEnum Units { get; set; }
public double LengthInCurrentUnits { get => _Length.Value; set => _Length.Value = value; }
public Model Model { get; }
public ViewModel( Model model, IScheduler scheduler = null )
{
Model = model;
var subject = model
.PropertySubject( p => p.LengthInMeters ) // Generate an ISubject<double>
.CombineLatest
( this.WhenAnyValue( p => p.Units ) // current value of units
, UnitsToScaleConstraintFactory // Function for generating the converter
, Observer.Create<Option<Exception>>
( e =>
{
} ) // Error handler
)
;
_Length = subject.ToProperty( this, p => p.LengthInCurrentUnits, scheduler: scheduler );
}
/// <summary>
/// Converts the units enum to a constraint that converts between
/// the base unit meters and the selected unit.
/// </summary>
/// <param name="u"></param>
/// <returns></returns>
private static TwoWayConstraint<double, double> UnitsToScaleConstraintFactory( UnitsEnum u )
{
switch (u)
{
case UnitsEnum.Meters:
return Constraint.Multiply( 1.0 );
case UnitsEnum.Milliters:
return Constraint.Multiply( 1000 );
default:
throw new ArgumentOutOfRangeException( nameof(u), u, null );
}
}
}
[StaFact]
public async Task ShouldWork()
{
var m = new Model();
var vm = new ViewModel(m);
m.LengthInMeters = 10;
m.LengthInMeters.Should().Be( 10 );
vm.Units = ViewModel.UnitsEnum.Meters;
vm.LengthInCurrentUnits.Should().Be( 10 );
vm.LengthInCurrentUnits.Should().Be( 10 );
vm.LengthInCurrentUnits = 20;
m.LengthInMeters.Should().Be( 20 );
vm.Units = ViewModel.UnitsEnum.Milliters;
vm.LengthInCurrentUnits.Should().Be( 20000 );
m.LengthInMeters.Should().Be( 20 );
m.LengthInMeters = 5;
vm.LengthInCurrentUnits.Should().Be( 5000 );
vm.LengthInCurrentUnits = 6000;
m.LengthInMeters.Should().Be( 6 );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment