public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            projectTaskClientToAttributedString = new ProjectTaskClientToAttributedString(
                ProjectTaskClientLabel.Font.CapHeight,
                Colors.EditTimeEntry.ClientText.ToNativeColor());

            tagsListToAttributedString = new TagsListToAttributedString(TagsTextView);

            localizeLabels();
            prepareViews();
            prepareOnboarding();

            contentSizeChangedDisposable = ScrollViewContent.AddObserver(boundsKey, NSKeyValueObservingOptions.New, onContentSizeChanged);

            DescriptionTextView.Text = ViewModel.Description.Value;

            ViewModel.Preferences
            .Select(preferences => preferences.DurationFormat)
            .Select(format => ViewModel.GroupDuration.ToFormattedString(format))
            .Subscribe(GroupDuration.Rx().Text())
            .DisposedBy(DisposeBag);

            CloseButton.Rx().Tap()
            .Subscribe(ViewModel.CloseWithDefaultResult)
            .DisposedBy(DisposeBag);

            ConfirmButton.Rx()
            .BindAction(ViewModel.Save)
            .DisposedBy(DisposeBag);

            DescriptionTextView.TextObservable
            .Subscribe(ViewModel.Description.Accept)
            .DisposedBy(DisposeBag);

            DescriptionTextView.SizeChangedObservable
            .Subscribe(adjustHeight)
            .DisposedBy(DisposeBag);

            ViewModel.SyncErrorMessage
            .Subscribe(ErrorMessageLabel.Rx().Text())
            .DisposedBy(DisposeBag);

            ViewModel.IsSyncErrorMessageVisible
            .Subscribe(ErrorView.Rx().IsVisible())
            .DisposedBy(DisposeBag);

            ErrorView.Rx().Tap()
            .Subscribe(ViewModel.DismissSyncErrorMessage.Inputs)
            .DisposedBy(DisposeBag);

            ViewModel.ProjectClientTask
            .Select(info => projectTaskClientToAttributedString.Convert(
                        info.Project,
                        info.Task,
                        info.Client,
                        new Color(info.ProjectColor).ToNativeColor()))
            .Subscribe(ProjectTaskClientLabel.Rx().AttributedText())
            .DisposedBy(DisposeBag);

            ViewModel.ProjectClientTask
            .Select(info => info.HasProject)
            .Subscribe(ProjectTaskClientLabel.Rx().IsVisible())
            .DisposedBy(DisposeBag);

            ViewModel.ProjectClientTask
            .Select(info => !info.HasProject)
            .Subscribe(AddProjectAndTaskView.Rx().IsVisible())
            .DisposedBy(DisposeBag);

            SelectProject.Rx()
            .BindAction(ViewModel.SelectProject)
            .DisposedBy(DisposeBag);

            TagsTextView.Rx()
            .BindAction(ViewModel.SelectTags)
            .DisposedBy(DisposeBag);

            AddTagsView.Rx()
            .BindAction(ViewModel.SelectTags)
            .DisposedBy(DisposeBag);

            var containsTags = ViewModel.Tags
                               .Select(tags => tags.Any());

            containsTags
            .Invert()
            .Subscribe(AddTagsView.Rx().IsVisible())
            .DisposedBy(DisposeBag);

            containsTags
            .Subscribe(TagsTextView.Rx().IsVisible())
            .DisposedBy(DisposeBag);

            ViewModel.IsBillable
            .Subscribe(BillableSwitch.Rx().CheckedObserver())
            .DisposedBy(DisposeBag);

            BillableSwitch.Rx().Changed()
            .Subscribe(ViewModel.ToggleBillable.Inputs)
            .DisposedBy(DisposeBag);

            ViewModel.IsBillableAvailable
            .Subscribe(BillableView.Rx().IsVisible())
            .DisposedBy(DisposeBag);

            ViewModel.IsInaccessible
            .Subscribe(adjustUIForInaccessibleTimeEntry)
            .DisposedBy(DisposeBag);

            ViewModel.StartTime
            .WithLatestFrom(ViewModel.Preferences,
                            (startTime, preferences) => DateTimeToFormattedString.Convert(
                                startTime,
                                preferences.TimeOfDayFormat.Format))
            .Subscribe(StartTimeLabel.Rx().Text())
            .DisposedBy(DisposeBag);

            ViewModel.StartTime
            .WithLatestFrom(ViewModel.Preferences,
                            (startTime, preferences) => DateTimeToFormattedString.Convert(
                                startTime,
                                preferences.DateFormat.Short))
            .Subscribe(StartDateLabel.Rx().Text())
            .DisposedBy(DisposeBag);

            StartTimeView.Rx().Tap()
            .SelectValue(EditViewTapSource.StartTime)
            .Subscribe(ViewModel.EditTimes.Inputs)
            .DisposedBy(DisposeBag);

            StartDateView.Rx().Tap()
            .Subscribe(ViewModel.SelectStartDate.Inputs)
            .DisposedBy(DisposeBag);

            ViewModel.IsTimeEntryRunning
            .Subscribe(StopButton.Rx().IsVisible())
            .DisposedBy(DisposeBag);

            ViewModel.IsTimeEntryRunning
            .Select(CommonFunctions.Invert)
            .Subscribe(EndTimeLabel.Rx().IsVisible())
            .DisposedBy(DisposeBag);

            ViewModel.StopTime
            .Where(stopTime => stopTime.HasValue)
            .Select(stopTime => stopTime.Value)
            .WithLatestFrom(ViewModel.Preferences,
                            (stopTime, preferences) => DateTimeToFormattedString.Convert(
                                stopTime,
                                preferences.TimeOfDayFormat.Format))
            .Subscribe(EndTimeLabel.Rx().Text())
            .DisposedBy(DisposeBag);

            EndTimeView.Rx().Tap()
            .SelectLatestFrom(ViewModel.IsTimeEntryRunning)
            .Invert()
            .Where(CommonFunctions.Identity)
            .SelectValue(EditViewTapSource.StopTime)
            .Subscribe(ViewModel.EditTimes.Inputs)
            .DisposedBy(DisposeBag);

            EndTimeView.Rx().Tap()
            .Merge(StopButton.Rx().Tap())
            .SelectLatestFrom(ViewModel.IsTimeEntryRunning)
            .Where(CommonFunctions.Identity)
            .SelectUnit()
            .Subscribe(ViewModel.StopTimeEntry.Inputs)
            .DisposedBy(DisposeBag);

            ViewModel.Duration
            .WithLatestFrom(ViewModel.Preferences,
                            (duration, preferences) => duration.ToFormattedString(preferences.DurationFormat))
            .Subscribe(DurationLabel.Rx().Text())
            .DisposedBy(DisposeBag);

            DurationView.Rx().Tap()
            .SelectValue(EditViewTapSource.Duration)
            .Subscribe(ViewModel.EditTimes.Inputs)
            .DisposedBy(DisposeBag);

            DeleteButton.Rx()
            .BindAction(ViewModel.Delete)
            .DisposedBy(DisposeBag);
        }