public void FailsForFormatsWhichAreNotTimeFormat(object parameter) { var combiner = new DateTimeOffsetTimeFormatValueCombiner(TimeZoneInfo.Utc); var successful = tryGetValue(combiner, DateTimeOffset.UtcNow, parameter, out var convertedValue); successful.Should().BeFalse(); convertedValue.Should().Be(MvxBindingConstant.UnsetValue); }
public void WorksForValidFormats(TimeFormat format) { var time = DateTimeOffset.UtcNow; var combiner = new DateTimeOffsetTimeFormatValueCombiner(TimeZoneInfo.Utc); var successful = tryGetValue(combiner, time, format, out var convertedValue); successful.Should().BeTrue(); convertedValue.Should().BeOfType <string>(); convertedValue.Should().Be(time.ToString(format.Format)); }
private static bool tryGetValue(DateTimeOffsetTimeFormatValueCombiner combiner, DateTimeOffset duration, object format, out object convertedValue) { var dateStepDescription = new MvxLiteralSourceStepDescription(); dateStepDescription.Literal = duration; var formatStepDescription = new MvxLiteralSourceStepDescription(); formatStepDescription.Literal = format; var steps = new[] { new MvxLiteralSourceStep(dateStepDescription), new MvxLiteralSourceStep(formatStepDescription) }; return(combiner.TryGetValue(steps, out convertedValue)); }
public override void ViewDidLoad() { base.ViewDidLoad(); setupDismissingByTappingOnBackground(); prepareViews(); var durationCombiner = new DurationValueCombiner(); var dateCombiner = new DateTimeOffsetDateFormatValueCombiner(TimeZoneInfo.Local); var timeCombiner = new DateTimeOffsetTimeFormatValueCombiner(TimeZoneInfo.Local); var visibilityConverter = new MvxVisibilityValueConverter(); var invertedBoolConverter = new BoolToConstantValueConverter <bool>(false, true); var inverterVisibilityConverter = new MvxInvertedVisibilityValueConverter(); var projectTaskClientCombiner = new ProjectTaskClientValueCombiner( ProjectTaskClientLabel.Font.CapHeight, Color.EditTimeEntry.ClientText.ToNativeColor(), false ); var stopRunningTimeEntryAndEditDurationForStoppedConverter = new BoolToConstantValueConverter <IMvxCommand>( ViewModel.StopCommand, ViewModel.EditDurationCommand); var bindingSet = this.CreateBindingSet <EditTimeEntryViewController, EditTimeEntryViewModel>(); //Error message view bindingSet.Bind(ErrorMessageLabel) .For(v => v.Text) .To(vm => vm.SyncErrorMessage); bindingSet.Bind(ErrorView) .For(v => v.BindTap()) .To(vm => vm.DismissSyncErrorMessageCommand); bindingSet.Bind(ErrorView) .For(v => v.BindVisible()) .To(vm => vm.SyncErrorMessageVisible) .WithConversion(inverterVisibilityConverter); //Text bindingSet.Bind(DescriptionTextView) .For(v => v.RemainingLength) .To(vm => vm.DescriptionRemainingLength); bindingSet.Bind(DescriptionTextView) .For(v => v.BindText()) .To(vm => vm.Description); bindingSet.Bind(BillableSwitch) .For(v => v.BindAnimatedOn()) .To(vm => vm.Billable); bindingSet.Bind(DurationLabel) .ByCombining(durationCombiner, vm => vm.Duration, vm => vm.DurationFormat); bindingSet.Bind(ProjectTaskClientLabel) .For(v => v.AttributedText) .ByCombining(projectTaskClientCombiner, v => v.Project, v => v.Task, v => v.Client, v => v.ProjectColor); bindingSet.Bind(StartDateLabel) .ByCombining(dateCombiner, vm => vm.StartTime, vm => vm.DateFormat); bindingSet.Bind(StartTimeLabel) .ByCombining(timeCombiner, vm => vm.StartTime, vm => vm.TimeFormat); bindingSet.Bind(EndTimeLabel) .ByCombining(timeCombiner, vm => vm.StopTime, vm => vm.TimeFormat); //Commands bindingSet.Bind(CloseButton).To(vm => vm.CloseCommand); bindingSet.Bind(DeleteButton).To(vm => vm.DeleteCommand); bindingSet.Bind(ConfirmButton).To(vm => vm.ConfirmCommand); bindingSet.Bind(DurationView) .For(v => v.BindTap()) .To(vm => vm.EditDurationCommand); bindingSet.Bind(StartTimeView) .For(v => v.BindTap()) .To(vm => vm.EditDurationCommand); bindingSet.Bind(StopButton) .To(vm => vm.StopCommand); bindingSet.Bind(EndTimeView) .For(v => v.BindTap()) .To(vm => vm.IsTimeEntryRunning) .WithConversion(stopRunningTimeEntryAndEditDurationForStoppedConverter); bindingSet.Bind(ProjectTaskClientLabel) .For(v => v.BindTap()) .To(vm => vm.SelectProjectCommand); bindingSet.Bind(AddProjectAndTaskView) .For(v => v.BindTap()) .To(vm => vm.SelectProjectCommand); bindingSet.Bind(StartDateView) .For(v => v.BindTap()) .To(vm => vm.SelectStartDateCommand); bindingSet.Bind(TagsTextView) .For(v => v.BindTap()) .To(vm => vm.SelectTagsCommand); bindingSet.Bind(AddTagsView) .For(v => v.BindTap()) .To(vm => vm.SelectTagsCommand); bindingSet.Bind(BillableView) .For(v => v.BindTap()) .To(vm => vm.ToggleBillableCommand); //End time and the stop button visibility bindingSet.Bind(StopButton) .For(v => v.BindVisible()) .To(vm => vm.IsTimeEntryRunning) .WithConversion(inverterVisibilityConverter); bindingSet.Bind(EndTimeLabel) .For(v => v.BindVisible()) .To(vm => vm.IsTimeEntryRunning) .WithConversion(visibilityConverter); //Project visibility bindingSet.Bind(AddProjectAndTaskView) .For(v => v.BindVisible()) .To(vm => vm.Project) .WithConversion(visibilityConverter); bindingSet.Bind(ProjectTaskClientLabel) .For(v => v.BindVisible()) .To(vm => vm.Project) .WithConversion(inverterVisibilityConverter); //Tags visibility bindingSet.Bind(AddTagsView) .For(v => v.BindVisible()) .To(vm => vm.HasTags) .WithConversion(visibilityConverter); bindingSet.Bind(TagsTextView) .For(v => v.BindVisible()) .To(vm => vm.HasTags) .WithConversion(inverterVisibilityConverter); //Confirm button enabled bindingSet.Bind(ConfirmButton) .For(v => v.Enabled) .To(vm => vm.DescriptionLimitExceeded) .WithConversion(invertedBoolConverter); bindingSet.Bind(ConfirmButton) .For(v => v.Alpha) .To(vm => vm.DescriptionLimitExceeded) .WithConversion(new BoolToConstantValueConverter <nfloat>(0.5f, 1)); bindingSet.Bind(BillableView) .For(v => v.BindVisibility()) .To(vm => vm.IsBillableAvailable) .WithConversion(visibilityConverter); bindingSet.Apply(); }
public override void ViewDidLoad() { base.ViewDidLoad(); TitleLabel.Text = Resources.Edit; BillableLabel.Text = Resources.Billable; StartDateDescriptionLabel.Text = Resources.Startdate; DurationDescriptionLabel.Text = Resources.Duration; StartDescriptionLabel.Text = Resources.Start; EndDescriptionLabel.Text = Resources.End; ErrorMessageTitleLabel.Text = Resources.Oops; AddProjectTaskLabel.Text = Resources.AddProjectTask; CategorizeWithProjectsLabel.Text = Resources.CategorizeYourTimeWithProjects; AddTagsLabel.Text = Resources.AddTags; DeleteButton.SetTitle(Resources.Delete, UIControlState.Normal); ConfirmButton.SetTitle(Resources.ConfirmChanges, UIControlState.Normal); prepareViews(); prepareOnboarding(); contentSizeChangedDisposable = ScrollViewContent.AddObserver(boundsKey, NSKeyValueObservingOptions.New, onContentSizeChanged); var durationCombiner = new DurationValueCombiner(); var dateCombiner = new DateTimeOffsetDateFormatValueCombiner(TimeZoneInfo.Local); var timeCombiner = new DateTimeOffsetTimeFormatValueCombiner(TimeZoneInfo.Local); var visibilityConverter = new MvxVisibilityValueConverter(); var invertedBoolConverter = new BoolToConstantValueConverter <bool>(false, true); var inverterVisibilityConverter = new MvxInvertedVisibilityValueConverter(); var projectTaskClientCombiner = new ProjectTaskClientValueCombiner( ProjectTaskClientLabel.Font.CapHeight, Color.EditTimeEntry.ClientText.ToNativeColor(), false ); var stopRunningTimeEntryAndSelectStopTimeForStoppedConverter = new BoolToConstantValueConverter <IMvxCommand>( ViewModel.StopCommand, ViewModel.SelectStopTimeCommand); var isInaccessibleTextColorConverter = new BoolToConstantValueConverter <UIColor>( Color.Common.Disabled.ToNativeColor(), Color.Common.TextColor.ToNativeColor() ); var showTagsCombiner = new ShowTagsValueCombiner(); var bindingSet = this.CreateBindingSet <EditTimeEntryViewController, EditTimeEntryViewModel>(); //Error message view bindingSet.Bind(ErrorMessageLabel) .For(v => v.Text) .To(vm => vm.SyncErrorMessage); bindingSet.Bind(ErrorView) .For(v => v.BindTap()) .To(vm => vm.DismissSyncErrorMessageCommand); bindingSet.Bind(ErrorView) .For(v => v.BindVisible()) .To(vm => vm.SyncErrorMessageVisible) .WithConversion(inverterVisibilityConverter); //Text bindingSet.Bind(RemainingCharacterCount) .To(vm => vm.DescriptionRemainingLength); bindingSet.Bind(RemainingCharacterCount) .For(v => v.BindVisible()) .To(vm => vm.DescriptionLimitExceeded); bindingSet.Bind(DescriptionTextView) .For(v => v.BindText()) .To(vm => vm.Description); bindingSet.Bind(DescriptionTextView) .For(v => v.BindDidBecomeFirstResponder()) .To(vm => vm.StartEditingDescriptionCommand); bindingSet.Bind(DurationLabel) .ByCombining(durationCombiner, vm => vm.Duration, vm => vm.DurationFormat); bindingSet.Bind(ProjectTaskClientLabel) .For(v => v.AttributedText) .ByCombining(projectTaskClientCombiner, v => v.Project, v => v.Task, v => v.Client, v => v.ProjectColor); bindingSet.Bind(StartDateLabel) .ByCombining(dateCombiner, vm => vm.StartTime, vm => vm.DateFormat); bindingSet.Bind(StartTimeLabel) .ByCombining(timeCombiner, vm => vm.StartTime, vm => vm.TimeFormat); bindingSet.Bind(EndTimeLabel) .ByCombining(timeCombiner, vm => vm.StopTime, vm => vm.TimeFormat); //Commands bindingSet.Bind(CloseButton).To(vm => vm.CloseCommand); bindingSet.Bind(DeleteButton).To(vm => vm.DeleteCommand); bindingSet.Bind(ConfirmButton).To(vm => vm.SaveCommand); bindingSet.Bind(DurationView) .For(v => v.BindTap()) .To(vm => vm.SelectDurationCommand); bindingSet.Bind(StartTimeView) .For(v => v.BindTap()) .To(vm => vm.SelectStartTimeCommand); bindingSet.Bind(StopButton) .To(vm => vm.StopCommand); bindingSet.Bind(EndTimeView) .For(v => v.BindTap()) .To(vm => vm.IsTimeEntryRunning) .WithConversion(stopRunningTimeEntryAndSelectStopTimeForStoppedConverter); bindingSet.Bind(ProjectTaskClientLabel) .For(v => v.BindTap()) .To(vm => vm.SelectProjectCommand); bindingSet.Bind(AddProjectAndTaskView) .For(v => v.BindTap()) .To(vm => vm.SelectProjectCommand); bindingSet.Bind(StartDateView) .For(v => v.BindTap()) .To(vm => vm.SelectStartDateCommand); bindingSet.Bind(TagsTextView) .For(v => v.BindTap()) .To(vm => vm.SelectTagsCommand); bindingSet.Bind(AddTagsView) .For(v => v.BindTap()) .To(vm => vm.SelectTagsCommand); bindingSet.Bind(BillableSwitch) .For(v => v.BindValueChanged()) .To(vm => vm.ToggleBillableCommand); //End time and the stop button visibility bindingSet.Bind(StopButton) .For(v => v.BindVisible()) .To(vm => vm.IsTimeEntryRunning) .WithConversion(inverterVisibilityConverter); bindingSet.Bind(EndTimeLabel) .For(v => v.BindVisible()) .To(vm => vm.IsTimeEntryRunning) .WithConversion(visibilityConverter); //Project visibility bindingSet.Bind(AddProjectAndTaskView) .For(v => v.BindVisible()) .To(vm => vm.Project) .WithConversion(visibilityConverter); bindingSet.Bind(ProjectTaskClientLabel) .For(v => v.BindVisible()) .To(vm => vm.Project) .WithConversion(inverterVisibilityConverter); //Tags visibility bindingSet.Bind(AddTagsView) .For(v => v.BindVisible()) .To(vm => vm.HasTags) .WithConversion(visibilityConverter); bindingSet.Bind(TagsTextView) .For(v => v.BindVisible()) .To(vm => vm.HasTags) .WithConversion(inverterVisibilityConverter); //Confirm button enabled bindingSet.Bind(ConfirmButton) .For(v => v.Enabled) .To(vm => vm.DescriptionLimitExceeded) .WithConversion(invertedBoolConverter); bindingSet.Bind(ConfirmButton) .For(v => v.Alpha) .To(vm => vm.DescriptionLimitExceeded) .WithConversion(new BoolToConstantValueConverter <nfloat>(0.5f, 1)); bindingSet.Bind(BillableView) .For(v => v.BindVisibility()) .To(vm => vm.IsBillableAvailable) .WithConversion(visibilityConverter); //Regarding inaccessible entries getLabelsToChangeColorWhenEditingInaccessibleEntry().ForEach(createTextColorBindingForInaccessibleEntries); bindingSet.Bind(DescriptionTextView) .For(v => v.TextColor) .To(vm => vm.IsInaccessible) .WithConversion(isInaccessibleTextColorConverter); bindingSet.Bind(DescriptionTextView) .For(v => v.UserInteractionEnabled) .To(vm => vm.IsInaccessible) .WithConversion(invertedBoolConverter); bindingSet.Bind(BillableSwitch) .For(v => v.Enabled) .To(vm => vm.IsInaccessible) .WithConversion(invertedBoolConverter); bindingSet.Bind(TagsContainerView) .For(v => v.Hidden) .ByCombining(showTagsCombiner, vm => vm.IsInaccessible, vm => vm.HasTags) .WithConversion(invertedBoolConverter); bindingSet.Bind(TagsSeparator) .For(v => v.Hidden) .ByCombining(showTagsCombiner, vm => vm.IsInaccessible, vm => vm.HasTags) .WithConversion(invertedBoolConverter); bindingSet.Apply(); void createTextColorBindingForInaccessibleEntries(UILabel label) { bindingSet.Bind(label) .For(v => v.TextColor) .To(vm => vm.IsInaccessible) .WithConversion(isInaccessibleTextColorConverter); } }
public override void ViewDidLoad() { base.ViewDidLoad(); startTimeChangingSubscription = ViewModel.StartTimeChanging.Subscribe(startTimeChanging); setupDismissingByTappingOnBackground(); prepareViews(); var durationCombiner = new DurationValueCombiner(); var timeCombiner = new DateTimeOffsetTimeFormatValueCombiner(TimeZoneInfo.Local); var dateCombiner = new DateTimeOffsetDateFormatValueCombiner(TimeZoneInfo.Local, useLongFormat: false); var timeFormatToLocaleConverter = new TimeFormatToLocaleValueConverter(); var inverseBoolConverter = new BoolToConstantValueConverter <bool>(false, true); var editedTimeLabelColorConverter = new BoolToConstantValueConverter <UIColor>( Color.EditDuration.EditedTime.ToNativeColor(), Color.EditDuration.NotEditedTime.ToNativeColor()); var bindingSet = this.CreateBindingSet <EditDurationViewController, EditDurationViewModel>(); //Commands bindingSet.Bind(SaveButton).To(vm => vm.SaveCommand); bindingSet.Bind(CloseButton).To(vm => vm.CloseCommand); //Start and stop date/time bindingSet.Bind(StartTimeLabel) .ByCombining(timeCombiner, vm => vm.StartTime, vm => vm.TimeFormat); bindingSet.Bind(StartDateLabel) .ByCombining(dateCombiner, vm => vm.StartTime, vm => vm.DateFormat); bindingSet.Bind(EndTimeLabel) .ByCombining(timeCombiner, vm => vm.StopTime, vm => vm.TimeFormat); bindingSet.Bind(EndDateLabel) .ByCombining(dateCombiner, vm => vm.StopTime, vm => vm.DateFormat); //Editing start and end time bindingSet.Bind(StartView) .For(v => v.BindTap()) .To(vm => vm.EditStartTimeCommand); bindingSet.Bind(EndView) .For(v => v.BindTap()) .To(vm => vm.EditStopTimeCommand); bindingSet.Bind(SetEndButton) .For(v => v.BindVisibility()) .To(vm => vm.IsRunning) .WithConversion(inverseBoolConverter); bindingSet.Bind(SetEndButton) .To(vm => vm.EditStopTimeCommand); //Visiblity bindingSet.Bind(EndTimeLabel) .For(v => v.BindVisibility()) .To(vm => vm.IsRunning); bindingSet.Bind(EndDateLabel) .For(v => v.BindVisibility()) .To(vm => vm.IsRunning); //Stard and end colors bindingSet.Bind(StartTimeLabel) .For(v => v.TextColor) .To(vm => vm.IsEditingStartTime) .WithConversion(editedTimeLabelColorConverter); bindingSet.Bind(StartDateLabel) .For(v => v.TextColor) .To(vm => vm.IsEditingStartTime) .WithConversion(editedTimeLabelColorConverter); bindingSet.Bind(EndTimeLabel) .For(v => v.TextColor) .To(vm => vm.IsEditingStopTime) .WithConversion(editedTimeLabelColorConverter); bindingSet.Bind(EndDateLabel) .For(v => v.TextColor) .To(vm => vm.IsEditingStopTime) .WithConversion(editedTimeLabelColorConverter); //Date picker bindingSet.Bind(DatePickerContainer) .For(v => v.BindAnimatedVisibility()) .To(vm => vm.IsEditingTime); bindingSet.Bind(DatePicker) .For(v => v.BindDateTimeOffset()) .To(vm => vm.EditedTime); bindingSet.Bind(DatePicker) .For(v => v.MaximumDate) .To(vm => vm.MaximumDateTime); bindingSet.Bind(DatePicker) .For(v => v.MinimumDate) .To(vm => vm.MinimumDateTime); bindingSet.Bind(DatePicker) .For(v => v.Locale) .To(vm => vm.TimeFormat) .WithConversion(timeFormatToLocaleConverter); //The wheel bindingSet.Bind(DurationInput) .For(v => v.UserInteractionEnabled) .To(vm => vm.IsEditingTime) .WithConversion(inverseBoolConverter); bindingSet.Bind(DurationInput) .For(v => v.Duration) .To(vm => vm.Duration); bindingSet.Bind(DurationInput) .For(v => v.FormattedDuration) .ByCombining(durationCombiner, vm => vm.Duration, vm => vm.DurationFormat); bindingSet.Bind(WheelView) .For(v => v.UserInteractionEnabled) .To(vm => vm.IsEditingTime) .WithConversion(inverseBoolConverter); bindingSet.Bind(WheelView) .For(v => v.MaximumStartTime) .To(vm => vm.MaximumStartTime); bindingSet.Bind(WheelView) .For(v => v.MinimumStartTime) .To(vm => vm.MinimumStartTime); bindingSet.Bind(WheelView) .For(v => v.MaximumEndTime) .To(vm => vm.MaximumStopTime); bindingSet.Bind(WheelView) .For(v => v.MinimumEndTime) .To(vm => vm.MinimumStopTime); bindingSet.Bind(WheelView) .For(v => v.StartTime) .To(vm => vm.StartTime); bindingSet.Bind(WheelView) .For(v => v.EndTime) .To(vm => vm.StopTime); bindingSet.Bind(WheelView) .For(v => v.IsRunning) .To(vm => vm.IsRunning); bindingSet.Apply(); }
public override void ViewDidLoad() { base.ViewDidLoad(); startTimeChangingSubscription = ViewModel.StartTimeChanging.Subscribe(startTimeChanging); prepareViews(); var durationCombiner = new DurationValueCombiner(); var timeCombiner = new DateTimeOffsetTimeFormatValueCombiner(TimeZoneInfo.Local); var dateCombiner = new DateTimeOffsetDateFormatValueCombiner(TimeZoneInfo.Local, useLongFormat: false); var timeFormatToLocaleConverter = new TimeFormatToLocaleValueConverter(); var inverseBoolConverter = new BoolToConstantValueConverter <bool>(false, true); var editedTimeLabelColorConverter = new BoolToConstantValueConverter <UIColor>( Color.EditDuration.EditedTime.ToNativeColor(), Color.EditDuration.NotEditedTime.ToNativeColor()); var bindingSet = this.CreateBindingSet <EditDurationViewController, EditDurationViewModel>(); //Commands bindingSet.Bind(SaveButton).To(vm => vm.SaveCommand); bindingSet.Bind(CloseButton).To(vm => vm.CloseCommand); //Start and stop date/time bindingSet.Bind(StartTimeLabel) .ByCombining(timeCombiner, vm => vm.StartTime, vm => vm.TimeFormat); bindingSet.Bind(StartDateLabel) .ByCombining(dateCombiner, vm => vm.StartTime, vm => vm.DateFormat); bindingSet.Bind(EndTimeLabel) .ByCombining(timeCombiner, vm => vm.StopTime, vm => vm.TimeFormat); bindingSet.Bind(EndDateLabel) .ByCombining(dateCombiner, vm => vm.StopTime, vm => vm.DateFormat); //Editing start and end time bindingSet.Bind(StartView) .For(v => v.BindTap()) .To(vm => vm.EditStartTimeCommand); bindingSet.Bind(EndView) .For(v => v.BindTap()) .To(vm => vm.EditStopTimeCommand); bindingSet.Bind(SetEndButton) .For(v => v.BindVisibility()) .To(vm => vm.IsRunning) .WithConversion(inverseBoolConverter); bindingSet.Bind(SetEndButton) .To(vm => vm.EditStopTimeCommand); //Visibility bindingSet.Bind(EndTimeLabel) .For(v => v.BindVisibility()) .To(vm => vm.IsRunning); bindingSet.Bind(EndDateLabel) .For(v => v.BindVisibility()) .To(vm => vm.IsRunning); //Stard and end colors bindingSet.Bind(StartTimeLabel) .For(v => v.TextColor) .To(vm => vm.IsEditingStartTime) .WithConversion(editedTimeLabelColorConverter); bindingSet.Bind(StartDateLabel) .For(v => v.TextColor) .To(vm => vm.IsEditingStartTime) .WithConversion(editedTimeLabelColorConverter); bindingSet.Bind(EndTimeLabel) .For(v => v.TextColor) .To(vm => vm.IsEditingStopTime) .WithConversion(editedTimeLabelColorConverter); bindingSet.Bind(EndDateLabel) .For(v => v.TextColor) .To(vm => vm.IsEditingStopTime) .WithConversion(editedTimeLabelColorConverter); //Date picker bindingSet.Bind(DatePickerContainer) .For(v => v.BindAnimatedVisibility()) .To(vm => vm.IsEditingTime); bindingSet.Bind(DatePicker) .For(v => v.BindDateTimeOffset()) .To(vm => vm.EditedTime); bindingSet.Bind(DatePicker) .For(v => v.MaximumDate) .To(vm => vm.MaximumDateTime); bindingSet.Bind(DatePicker) .For(v => v.MinimumDate) .To(vm => vm.MinimumDateTime); bindingSet.Bind(DatePicker) .For(v => v.Locale) .To(vm => vm.TimeFormat) .WithConversion(timeFormatToLocaleConverter); //The wheel bindingSet.Bind(DurationInput) .For(v => v.UserInteractionEnabled) .To(vm => vm.IsEditingTime) .WithConversion(inverseBoolConverter); bindingSet.Bind(DurationInput) .For(v => v.Duration) .To(vm => vm.Duration); bindingSet.Bind(DurationInput) .For(v => v.FormattedDuration) .ByCombining(durationCombiner, vm => vm.Duration, vm => vm.DurationFormat); bindingSet.Bind(WheelView) .For(v => v.UserInteractionEnabled) .To(vm => vm.IsEditingTime) .WithConversion(inverseBoolConverter); bindingSet.Bind(WheelView) .For(v => v.MaximumStartTime) .To(vm => vm.MaximumStartTime); bindingSet.Bind(WheelView) .For(v => v.MinimumStartTime) .To(vm => vm.MinimumStartTime); bindingSet.Bind(WheelView) .For(v => v.MaximumEndTime) .To(vm => vm.MaximumStopTime); bindingSet.Bind(WheelView) .For(v => v.MinimumEndTime) .To(vm => vm.MinimumStopTime); bindingSet.Bind(WheelView) .For(v => v.StartTime) .To(vm => vm.StartTime); bindingSet.Bind(WheelView) .For(v => v.EndTime) .To(vm => vm.StopTime); bindingSet.Bind(WheelView) .For(v => v.IsRunning) .To(vm => vm.IsRunning); bindingSet.Apply(); // Interaction observables for analytics var editingStart = Observable.Merge( StartView.Rx().Tap().Select(true), EndView.Rx().Tap().Select(false) ); var dateComponentChanged = DatePicker.Rx().DateComponent() .WithLatestFrom(editingStart, (_, isStart) => isStart ? EditTimeSource.BarrelStartDate : EditTimeSource.BarrelStopDate ); var timeComponentChanged = DatePicker.Rx().TimeComponent() .WithLatestFrom(editingStart, (_, isStart) => isStart ? EditTimeSource.BarrelStartTime : EditTimeSource.BarrelStopTime ); var durationInputChanged = Observable .FromEventPattern(e => DurationInput.DurationChanged += e, e => DurationInput.DurationChanged -= e) .Select(EditTimeSource.NumpadDuration); Observable.Merge( dateComponentChanged, timeComponentChanged, WheelView.TimeEdited, durationInputChanged ) .Distinct() .Subscribe(ViewModel.TimeEditedWithSource) .DisposedBy(disposeBag); }