internal BogieViewModel(Car.Bogie bogie) { CultureInfo culture = CultureInfo.InvariantCulture; DefinedAxles = bogie .ToReactivePropertyAsSynchronized(x => x.DefinedAxles) .AddTo(disposable); FrontAxle = bogie .ToReactivePropertyAsSynchronized( x => x.FrontAxle, x => x.ToString(culture), x => double.Parse(x, NumberStyles.Float, culture), ignoreValidationErrorValue: true ) .AddTo(disposable); RearAxle = bogie .ToReactivePropertyAsSynchronized( x => x.RearAxle, x => x.ToString(culture), x => double.Parse(x, NumberStyles.Float, culture), ignoreValidationErrorValue: true ) .AddTo(disposable); Reversed = bogie .ToReactivePropertyAsSynchronized(x => x.Reversed) .AddTo(disposable); Object = bogie .ToReactivePropertyAsSynchronized(x => x.Object) .AddTo(disposable); DefinedAxles.Subscribe(_ => { FrontAxle.ForceValidate(); RearAxle.ForceValidate(); }); FrontAxle.SetValidateNotifyError(x => { double front; string message; if (Utilities.TryParse(x, NumberRange.Any, out front, out message)) { double rear; if (DefinedAxles.Value && Utilities.TryParse(RearAxle.Value, NumberRange.Any, out rear) && front <= rear) { message = "RearAxleはFrontAxle未満でなければなりません。"; } } return(message); }) .Subscribe(_ => RearAxle.ForceValidate()) .AddTo(disposable); FrontAxle.ObserveHasErrors .ToReadOnlyReactivePropertySlim(mode: ReactivePropertyMode.DistinctUntilChanged) .Where(x => !x) .Subscribe(_ => FrontAxle.ForceNotify()) .AddTo(disposable); RearAxle.SetValidateNotifyError(x => { double rear; string message; if (Utilities.TryParse(x, NumberRange.Any, out rear, out message)) { double front; if (DefinedAxles.Value && Utilities.TryParse(FrontAxle.Value, NumberRange.Any, out front) && rear >= front) { message = "RearAxleはFrontAxle未満でなければなりません。"; } } return(message); }) .Subscribe(_ => FrontAxle.ForceValidate()) .AddTo(disposable); RearAxle.ObserveHasErrors .ToReadOnlyReactivePropertySlim(mode: ReactivePropertyMode.DistinctUntilChanged) .Where(x => !x) .Subscribe(_ => RearAxle.ForceNotify()) .AddTo(disposable); }
internal CarViewModel(Car car) { CultureInfo culture = CultureInfo.InvariantCulture; Model = car; Mass = car .ToReactivePropertyAsSynchronized( x => x.Mass, x => x.ToString(culture), x => double.Parse(x, NumberStyles.Float, culture), ignoreValidationErrorValue: true ) .SetValidateNotifyError(x => { double result; string message; Utilities.TryParse(x, NumberRange.Positive, out result, out message); return(message); }) .AddTo(disposable); Length = car .ToReactivePropertyAsSynchronized( x => x.Length, x => x.ToString(culture), x => double.Parse(x, NumberStyles.Float, culture), ignoreValidationErrorValue: true ) .SetValidateNotifyError(x => { double result; string message; Utilities.TryParse(x, NumberRange.Positive, out result, out message); return(message); }) .AddTo(disposable); Width = car .ToReactivePropertyAsSynchronized( x => x.Width, x => x.ToString(culture), x => double.Parse(x, NumberStyles.Float, culture), ignoreValidationErrorValue: true ) .SetValidateNotifyError(x => { double result; string message; Utilities.TryParse(x, NumberRange.Positive, out result, out message); return(message); }) .AddTo(disposable); Height = car .ToReactivePropertyAsSynchronized( x => x.Height, x => x.ToString(culture), x => double.Parse(x, NumberStyles.Float, culture), ignoreValidationErrorValue: true ) .SetValidateNotifyError(x => { double result; string message; Utilities.TryParse(x, NumberRange.Positive, out result, out message); return(message); }) .AddTo(disposable); CenterOfGravityHeight = car .ToReactivePropertyAsSynchronized( x => x.CenterOfGravityHeight, x => x.ToString(culture), x => double.Parse(x, NumberStyles.Float, culture), ignoreValidationErrorValue: true ) .SetValidateNotifyError(x => { double result; string message; Utilities.TryParse(x, NumberRange.Any, out result, out message); return(message); }) .AddTo(disposable); DefinedAxles = car .ToReactivePropertyAsSynchronized(x => x.DefinedAxles) .AddTo(disposable); FrontAxle = car .ToReactivePropertyAsSynchronized( x => x.FrontAxle, x => x.ToString(culture), x => double.Parse(x, NumberStyles.Float, culture), ignoreValidationErrorValue: true ) .AddTo(disposable); RearAxle = car .ToReactivePropertyAsSynchronized( x => x.RearAxle, x => x.ToString(culture), x => double.Parse(x, NumberStyles.Float, culture), ignoreValidationErrorValue: true ) .AddTo(disposable); FrontBogie = car .ObserveProperty(x => x.FrontBogie) .Do(_ => FrontBogie?.Value.Dispose()) .Select(x => new BogieViewModel(x)) .ToReadOnlyReactivePropertySlim() .AddTo(disposable); RearBogie = car .ObserveProperty(x => x.RearBogie) .Do(_ => RearBogie?.Value.Dispose()) .Select(x => new BogieViewModel(x)) .ToReadOnlyReactivePropertySlim() .AddTo(disposable); ExposedFrontalArea = car .ToReactivePropertyAsSynchronized( x => x.ExposedFrontalArea, x => x.ToString(culture), x => double.Parse(x, NumberStyles.Float, culture), ignoreValidationErrorValue: true ) .SetValidateNotifyError(x => { double result; string message; Utilities.TryParse(x, NumberRange.Positive, out result, out message); return(message); }) .AddTo(disposable); UnexposedFrontalArea = car .ToReactivePropertyAsSynchronized( x => x.UnexposedFrontalArea, x => x.ToString(culture), x => double.Parse(x, NumberStyles.Float, culture), ignoreValidationErrorValue: true ) .SetValidateNotifyError(x => { double result; string message; Utilities.TryParse(x, NumberRange.Positive, out result, out message); return(message); }) .AddTo(disposable); Performance = car .ObserveProperty(x => x.Performance) .Do(_ => Performance?.Value.Dispose()) .Select(x => new PerformanceViewModel(x)) .ToReadOnlyReactivePropertySlim() .AddTo(disposable); Delay = car .ObserveProperty(x => x.Delay) .Do(_ => Delay?.Value.Dispose()) .Select(x => new DelayViewModel(x)) .ToReadOnlyReactivePropertySlim() .AddTo(disposable); Move = car .ObserveProperty(x => x.Move) .Do(_ => Move?.Value.Dispose()) .Select(x => new MoveViewModel(x)) .ToReadOnlyReactivePropertySlim() .AddTo(disposable); Brake = car .ObserveProperty(x => x.Brake) .Do(_ => Brake?.Value.Dispose()) .Select(x => new BrakeViewModel(x)) .ToReadOnlyReactivePropertySlim() .AddTo(disposable); Pressure = car .ObserveProperty(x => x.Pressure) .Do(_ => Pressure?.Value.Dispose()) .Select(x => new PressureViewModel(x)) .ToReadOnlyReactivePropertySlim() .AddTo(disposable); Reversed = car .ToReactivePropertyAsSynchronized(x => x.Reversed) .AddTo(disposable); Object = car .ToReactivePropertyAsSynchronized(x => x.Object) .AddTo(disposable); LoadingSway = car .ToReactivePropertyAsSynchronized(x => x.LoadingSway) .AddTo(disposable); DefinedAxles.Subscribe(_ => { FrontAxle.ForceValidate(); RearAxle.ForceValidate(); }); FrontAxle.SetValidateNotifyError(x => { double front; string message; if (Utilities.TryParse(x, NumberRange.Any, out front, out message)) { double rear; if (DefinedAxles.Value && Utilities.TryParse(RearAxle.Value, NumberRange.Any, out rear) && front <= rear) { message = "RearAxleはFrontAxle未満でなければなりません。"; } } return(message); }) .Subscribe(_ => RearAxle.ForceValidate()) .AddTo(disposable); FrontAxle.ObserveHasErrors .ToReadOnlyReactivePropertySlim(mode: ReactivePropertyMode.DistinctUntilChanged) .Where(x => !x) .Subscribe(_ => FrontAxle.ForceNotify()) .AddTo(disposable); RearAxle.SetValidateNotifyError(x => { double rear; string message; if (Utilities.TryParse(x, NumberRange.Any, out rear, out message)) { double front; if (DefinedAxles.Value && Utilities.TryParse(FrontAxle.Value, NumberRange.Any, out front) && rear >= front) { message = "RearAxleはFrontAxle未満でなければなりません。"; } } return(message); }) .Subscribe(_ => FrontAxle.ForceValidate()) .AddTo(disposable); RearAxle.ObserveHasErrors .ToReadOnlyReactivePropertySlim(mode: ReactivePropertyMode.DistinctUntilChanged) .Where(x => !x) .Subscribe(_ => RearAxle.ForceNotify()) .AddTo(disposable); }