示例#1
0
        public override void AwakeFromNib()
        {
            base.AwakeFromNib();

            this.DelayBind(() =>
            {
                var colorConverter   = new MvxRGBValueConverter();
                var durationCombiner = new DurationValueCombiner();
                var bindingSet       = this.CreateBindingSet <ReportsLegendViewCell, ChartSegment>();

                //Text
                bindingSet.Bind(ProjectLabel).To(vm => vm.ProjectName);
                bindingSet.Bind(PercentageLabel)
                .For(v => v.Text)
                .ByCombining("Format", "'{0:0.00}%'", nameof(ChartSegment.Percentage));

                bindingSet.Bind(TotalTimeLabel)
                .ByCombining(durationCombiner,
                             vm => vm.TrackedTime,
                             vm => vm.DurationFormat);

                // Color
                bindingSet.Bind(ProjectLabel)
                .For(v => v.TextColor)
                .To(vm => vm.Color)
                .WithConversion(colorConverter);

                bindingSet.Bind(CircleView)
                .For(v => v.BackgroundColor)
                .To(vm => vm.Color)
                .WithConversion(colorConverter);

                bindingSet.Apply();
            });
        }
        public override void AwakeFromNib()
        {
            base.AwakeFromNib();

            ContentView.BackgroundColor = UIColor.White;
            DurationLabel.Font          = DurationLabel.Font.GetMonospacedDigitFont();

            this.DelayBind(() =>
            {
                var visibilityConverter = new MvxVisibilityValueConverter();
                var durationCombiner    = new DurationValueCombiner();
                var dateTitleConverter  = new DateToTitleStringValueConverter();

                var bindingSet = this.CreateBindingSet <TimeEntriesLogHeaderViewCell, TimeEntryViewModelCollection>();

                //Text
                bindingSet.Bind(DateLabel)
                .To(vm => vm.Date)
                .WithConversion(dateTitleConverter);

                bindingSet.Bind(DurationLabel)
                .ByCombining(durationCombiner,
                             vm => vm.TotalTime,
                             vm => vm.DurationFormat);

                bindingSet.Apply();
            });
        }
示例#3
0
        public override void AwakeFromNib()
        {
            base.AwakeFromNib();

            var templateImage = TotalDurationGraph.Image.ImageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate);

            TotalDurationGraph.Image = templateImage;

            var durationCombiner = new DurationValueCombiner();

            this.DelayBind(() =>
            {
                var bindingSet = this.CreateBindingSet <ReportsHeaderView, ReportsViewModel>();

                //Text
                bindingSet.Bind(BillablePercentageLabel)
                .For(v => v.AttributedText)
                .To(vm => vm.BillablePercentage)
                .WithConversion(new ReportPercentageLabelValueConverter());

                bindingSet.Bind(TotalDurationLabel)
                .For(v => v.Text)
                .ByCombining(durationCombiner,
                             vm => vm.TotalTime,
                             vm => vm.DurationFormat);

                //Loading chart
                bindingSet.Bind(LoadingPieChartView)
                .For(v => v.BindVisible())
                .To(vm => vm.IsLoading);

                //Pretty stuff
                bindingSet.Bind(PieChartView)
                .For(v => v.Segments)
                .To(vm => vm.Segments);

                bindingSet.Bind(BillablePercentageView)
                .For(v => v.Percentage)
                .To(vm => vm.BillablePercentage);

                bindingSet.Bind(TotalDurationGraph)
                .For(v => v.TintColor)
                .To(vm => vm.TotalTimeIsZero)
                .WithConversion(new BoolToConstantValueConverter <UIColor>(
                                    Color.Reports.Disabled.ToNativeColor(),
                                    Color.Reports.TotalTimeActivated.ToNativeColor()
                                    ));

                //Visibility
                bindingSet.Bind(EmptyStateView)
                .For(v => v.BindVisible())
                .To(vm => vm.ShowEmptyState);

                bindingSet.Apply();
            });
        }
        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 AwakeFromNib()
        {
            base.AwakeFromNib();

            var templateImage = TotalDurationGraph.Image.ImageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate);

            TotalDurationGraph.Image = templateImage;

            prepareViews();

            var colorConverter = new BoolToConstantValueConverter <UIColor>(
                Color.Reports.Disabled.ToNativeColor(),
                Color.Reports.TotalTimeActivated.ToNativeColor()
                );

            var durationCombiner = new DurationValueCombiner();

            this.DelayBind(() =>
            {
                var bindingSet = this.CreateBindingSet <ReportsHeaderView, ReportsViewModel>();

                //Text
                bindingSet.Bind(BillablePercentageLabel)
                .For(v => v.AttributedText)
                .To(vm => vm.BillablePercentage)
                .WithConversion(new ReportPercentageLabelValueConverter());

                bindingSet.Bind(TotalDurationLabel)
                .For(v => v.Text)
                .ByCombining(durationCombiner,
                             vm => vm.TotalTime,
                             vm => vm.DurationFormat);

                //Loading chart
                bindingSet.Bind(LoadingPieChartView)
                .For(v => v.BindVisibilityWithFade())
                .To(vm => vm.IsLoading);

                bindingSet.Bind(LoadingCardView)
                .For(v => v.BindVisibilityWithFade())
                .To(vm => vm.IsLoading);

                //Pretty stuff
                bindingSet.Bind(PieChartView)
                .For(v => v.Segments)
                .To(vm => vm.GroupedSegments);

                bindingSet.Bind(BillablePercentageView)
                .For(v => v.Percentage)
                .To(vm => vm.BillablePercentage);

                bindingSet.Bind(TotalDurationGraph)
                .For(v => v.TintColor)
                .To(vm => vm.TotalTimeIsZero)
                .WithConversion(colorConverter);

                bindingSet.Bind(TotalDurationLabel)
                .For(v => v.TextColor)
                .To(vm => vm.TotalTimeIsZero)
                .WithConversion(colorConverter);

                // Bar chart

                if (ViewModel == null)
                {
                    throw new InvalidOperationException($"The {nameof(ViewModel)} value must be set for {nameof(ReportsHeaderView)} before defining bindings.");
                }

                ViewModel.WorkspaceHasBillableFeatureEnabled
                .Subscribe(ColorsLegendContainerView.Rx().IsVisible())
                .DisposedBy(disposeBag);

                ViewModel.StartDate
                .CombineLatest(
                    ViewModel.BarChartViewModel.DateFormat,
                    (startDate, format) => startDate.ToString(format.Short))
                .Subscribe(StartDateLabel.Rx().Text())
                .DisposedBy(disposeBag);

                ViewModel.EndDate
                .CombineLatest(
                    ViewModel.BarChartViewModel.DateFormat,
                    (endDate, format) => endDate.ToString(format.Short))
                .Subscribe(EndDateLabel.Rx().Text())
                .DisposedBy(disposeBag);

                ViewModel.BarChartViewModel.MaximumHoursPerBar
                .Select(hours => $"{hours} h")
                .Subscribe(MaximumHoursLabel.Rx().Text())
                .DisposedBy(disposeBag);

                ViewModel.BarChartViewModel.MaximumHoursPerBar
                .Select(hours => $"{hours/2} h")
                .Subscribe(HalfHoursLabel.Rx().Text())
                .DisposedBy(disposeBag);

                ViewModel.BarChartViewModel.HorizontalLegend
                .Where(legend => legend == null)
                .Subscribe((DateTimeOffset[] _) =>
                {
                    HorizontalLegendStackView.Subviews.ForEach(subview => subview.RemoveFromSuperview());
                    StartDateLabel.Hidden = false;
                    EndDateLabel.Hidden   = false;
                })
                .DisposedBy(disposeBag);

                ViewModel.BarChartViewModel.HorizontalLegend
                .Where(legend => legend != null)
                .CombineLatest(ViewModel.BarChartViewModel.DateFormat, createHorizontalLegendLabels)
                .Do(_ =>
                {
                    StartDateLabel.Hidden = true;
                    EndDateLabel.Hidden   = true;
                })
                .Subscribe(HorizontalLegendStackView.Rx().ArrangedViews())
                .DisposedBy(disposeBag);

                ViewModel.BarChartViewModel.Bars
                .Select(createBarViews)
                .Subscribe(BarsStackView.Rx().ArrangedViews())
                .DisposedBy(disposeBag);

                var spacingObservable = ViewModel.BarChartViewModel.Bars
                                        .CombineLatest(updateLayout, (bars, _) => bars)
                                        .Select(bars => BarsStackView.Frame.Width / bars.Length * barChartSpacingProportion);

                spacingObservable
                .Subscribe(BarsStackView.Rx().Spacing())
                .DisposedBy(disposeBag);

                spacingObservable
                .Subscribe(HorizontalLegendStackView.Rx().Spacing())
                .DisposedBy(disposeBag);

                ViewModel.IsLoadingObservable
                .Select(CommonFunctions.Invert)
                .Subscribe(BarChartContainerView.Rx().IsVisible())
                .DisposedBy(disposeBag);

                //Visibility
                bindingSet.Bind(EmptyStateView)
                .For(v => v.BindVisible())
                .To(vm => vm.ShowEmptyState);

                bindingSet.Apply();
            });
        }
示例#7
0
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            AddProjectBubbleLabel.Text = Resources.AddProjectBubbleText;

            prepareViews();
            prepareOnboarding();

            var source = new StartTimeEntryTableViewSource(SuggestionsTableView);

            SuggestionsTableView.Source = source;
            source.ToggleTasksCommand   = new MvxCommand <ProjectSuggestion>(toggleTaskSuggestions);

            var invertedVisibilityConverter = new MvxInvertedVisibilityValueConverter();
            var invertedBoolConverter       = new BoolToConstantValueConverter <bool>(false, true);
            var buttonColorConverter        = new BoolToConstantValueConverter <UIColor>(
                Color.StartTimeEntry.ActiveButton.ToNativeColor(),
                Color.StartTimeEntry.InactiveButton.ToNativeColor()
                );
            var durationCombiner = new DurationValueCombiner();

            var bindingSet = this.CreateBindingSet <StartTimeEntryViewController, StartTimeEntryViewModel>();

            //TableView
            bindingSet.Bind(source)
            .For(v => v.ObservableCollection)
            .To(vm => vm.Suggestions);

            bindingSet.Bind(source)
            .For(v => v.UseGrouping)
            .To(vm => vm.UseGrouping);

            bindingSet.Bind(source)
            .For(v => v.SelectSuggestionCommand)
            .To(vm => vm.SelectSuggestionCommand);

            bindingSet.Bind(source)
            .For(v => v.CreateCommand)
            .To(vm => vm.CreateCommand);

            bindingSet.Bind(source)
            .For(v => v.IsSuggestingProjects)
            .To(vm => vm.IsSuggestingProjects);

            bindingSet.Bind(source)
            .For(v => v.Text)
            .To(vm => vm.CurrentQuery);

            bindingSet.Bind(source)
            .For(v => v.SuggestCreation)
            .To(vm => vm.SuggestCreation);

            bindingSet.Bind(source)
            .For(v => v.ShouldShowNoTagsInfoMessage)
            .To(vm => vm.ShouldShowNoTagsInfoMessage);

            bindingSet.Bind(source)
            .For(v => v.ShouldShowNoProjectsInfoMessage)
            .To(vm => vm.ShouldShowNoProjectsInfoMessage);

            //Text
            bindingSet.Bind(TimeInput)
            .For(v => v.Duration)
            .To(vm => vm.DisplayedTime)
            .Mode(MvxBindingMode.OneWayToSource);

            bindingSet.Bind(TimeLabel)
            .For(v => v.Text)
            .ByCombining(durationCombiner,
                         vm => vm.DisplayedTime,
                         vm => vm.DisplayedTimeFormat);

            bindingSet.Bind(Placeholder)
            .To(vm => vm.PlaceholderText);

            //Buttons
            bindingSet.Bind(TagsButton)
            .For(v => v.TintColor)
            .To(vm => vm.IsSuggestingTags)
            .WithConversion(buttonColorConverter);

            bindingSet.Bind(BillableButton)
            .For(v => v.TintColor)
            .To(vm => vm.IsBillable)
            .WithConversion(buttonColorConverter);

            bindingSet.Bind(ProjectsButton)
            .For(v => v.TintColor)
            .To(vm => vm.IsSuggestingProjects)
            .WithConversion(buttonColorConverter);

            //Visibility
            bindingSet.Bind(BillableButtonWidthConstraint)
            .For(v => v.Constant)
            .To(vm => vm.IsBillableAvailable)
            .WithConversion(new BoolToConstantValueConverter <nfloat>(42, 0));

            //Commands
            bindingSet.Bind(DoneButton).To(vm => vm.DoneCommand);
            bindingSet.Bind(CloseButton).To(vm => vm.BackCommand);
            bindingSet.Bind(BillableButton).To(vm => vm.ToggleBillableCommand);
            bindingSet.Bind(StartDateButton).To(vm => vm.SetStartDateCommand);
            bindingSet.Bind(DateTimeButton).To(vm => vm.ChangeTimeCommand);
            bindingSet.Bind(TagsButton).To(vm => vm.ToggleTagSuggestionsCommand);
            bindingSet.Bind(ProjectsButton).To(vm => vm.ToggleProjectSuggestionsCommand);

            bindingSet.Apply();

            // Reactive
            ViewModel.TextFieldInfoObservable
            .Subscribe(onTextFieldInfo)
            .DisposedBy(DisposeBag);

            DescriptionTextView.Rx().AttributedText()
            .Select(attributedString => attributedString.Length == 0)
            .Subscribe(isDescriptionEmptySubject)
            .DisposedBy(DisposeBag);

            DescriptionTextView.Rx().AttributedText()
            .CombineLatest(DescriptionTextView.Rx().CursorPosition(), (text, _) => text)
            .Where(_ => !isUpdatingDescriptionField)
            .SubscribeOn(ThreadPoolScheduler.Instance)
            .Do(updatePlaceholder)
            .Select(text => text.AsImmutableSpans((int)DescriptionTextView.SelectedRange.Location))
            .ObserveOn(SynchronizationContext.Current)
            .Subscribe(async info => await ViewModel.OnTextFieldInfoFromView(info))
            .DisposedBy(DisposeBag);

            source.TableRenderCallback = () =>
            {
                ViewModel.StopSuggestionsRenderingStopwatch();
            };
        }
示例#8
0
        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();

            prepareViews();
            prepareOnboarding();
            setupTableViewHeader();

            var visibilityConverter       = new MvxVisibilityValueConverter();
            var projectTaskClientCombiner = new ProjectTaskClientValueCombiner(
                CurrentTimeEntryProjectTaskClientLabel.Font.CapHeight,
                Color.Main.CurrentTimeEntryClientColor.ToNativeColor(),
                true
                );
            var startTimeEntryButtonManualModeIconConverter = new BoolToConstantValueConverter <UIImage>(
                UIImage.FromBundle("manualIcon"),
                UIImage.FromBundle("playIcon")
                );
            var durationCombiner = new DurationValueCombiner();

            var bindingSet = this.CreateBindingSet <MainViewController, MainViewModel>();

            // Table view
            tableViewSource = new TimeEntriesLogViewSource(ViewModel.TimeEntries, TimeEntriesLogViewCell.Identifier);
            TimeEntriesLogTableView
            .Rx()
            .Bind(tableViewSource)
            .DisposedBy(disposeBag);

            this.Bind(tableViewSource.FirstCell, f =>
            {
                onFirstTimeEntryChanged(f);
                firstTimeEntryCell = f;
            });

            this.Bind(tableViewSource.ScrollOffset, onTableScroll);

            var continueTimeEntry = Observable.Merge(
                tableViewSource.ContinueTap,
                tableViewSource.SwipeToContinue
                );

            this.Bind(continueTimeEntry, ViewModel.ContinueTimeEntry);
            this.Bind(tableViewSource.SwipeToDelete, ViewModel.TimeEntriesViewModel.DelayDeleteTimeEntry);
            this.Bind(tableViewSource.ItemSelected, ViewModel.SelectTimeEntry);
            this.Bind(ViewModel.TimeEntriesViewModel.ShouldShowUndo, toggleUndoDeletion);

            tableViewSource.SwipeToContinue
            .VoidSubscribe(() =>
            {
                swipeRightStep.Dismiss();
            })
            .DisposedBy(disposeBag);

            tableViewSource.SwipeToDelete
            .VoidSubscribe(() =>
            {
                swipeLeftStep.Dismiss();
            })
            .DisposedBy(disposeBag);

            // Refresh Control
            var refreshControl = new RefreshControl(ViewModel.SyncProgressState, tableViewSource);

            this.Bind(refreshControl.Refresh, ViewModel.RefreshAction);
            TimeEntriesLogTableView.CustomRefreshControl = refreshControl;

            //Commands
            bindingSet.Bind(settingsButton).To(vm => vm.OpenSettingsCommand);
            bindingSet.Bind(StopTimeEntryButton).To(vm => vm.StopTimeEntryCommand);
            bindingSet.Bind(StartTimeEntryButton).To(vm => vm.StartTimeEntryCommand);
            bindingSet.Bind(EditTimeEntryButton).To(vm => vm.EditTimeEntryCommand);
            bindingSet.Bind(syncFailuresButton).To(vm => vm.OpenSyncFailuresCommand);

            bindingSet.Bind(CurrentTimeEntryCard)
            .For(v => v.BindTap())
            .To(vm => vm.EditTimeEntryCommand);

            bindingSet.Bind(suggestionsView)
            .For(v => v.SuggestionTappedCommad)
            .To(vm => vm.SuggestionsViewModel.StartTimeEntryCommand);

            bindingSet.Bind(StartTimeEntryButton)
            .For(v => v.BindLongPress())
            .To(vm => vm.AlternativeStartTimeEntryCommand);

            //Visibility
            var shouldWelcomeBack = ViewModel.ShouldShowWelcomeBack;

            this.Bind(ViewModel.ShouldShowEmptyState, visible => emptyStateView.Hidden = !visible);
            this.Bind(shouldWelcomeBack, WelcomeBackView.Rx().IsVisible());
            this.Bind(shouldWelcomeBack, spiderContainerView.Rx().IsVisible());
            this.Bind(shouldWelcomeBack, visible =>
            {
                if (visible)
                {
                    spiderBroView.Show();
                }
                else
                {
                    spiderBroView.Hide();
                }
            });

            //Text
            bindingSet.Bind(CurrentTimeEntryDescriptionLabel).To(vm => vm.CurrentTimeEntryDescription);

            bindingSet.Bind(CurrentTimeEntryElapsedTimeLabel)
            .ByCombining(durationCombiner,
                         vm => vm.CurrentTimeEntryElapsedTime,
                         vm => vm.CurrentTimeEntryElapsedTimeFormat);

            bindingSet.Bind(CurrentTimeEntryProjectTaskClientLabel)
            .For(v => v.AttributedText)
            .ByCombining(projectTaskClientCombiner,
                         v => v.CurrentTimeEntryProject,
                         v => v.CurrentTimeEntryTask,
                         v => v.CurrentTimeEntryClient,
                         v => v.CurrentTimeEntryProjectColor);

            //The start button
            bindingSet.Bind(StartTimeEntryButton)
            .For(v => v.BindImage())
            .To(vm => vm.IsInManualMode)
            .WithConversion(startTimeEntryButtonManualModeIconConverter);

            //The sync failures button
            bindingSet.Bind(syncFailuresButton)
            .For(v => v.BindVisibility())
            .To(vm => vm.NumberOfSyncFailures)
            .WithConversion(visibilityConverter);

            bindingSet.Apply();

            this.Bind(ViewModel.RatingViewModel.IsFeedbackSuccessViewShowing,
                      SendFeedbackSuccessView.Rx().AnimatedIsVisible());
            this.BindVoid(SendFeedbackSuccessView.Rx().Tap(), ViewModel.RatingViewModel.CloseFeedbackSuccessView);

            ViewModel.ShouldReloadTimeEntryLog
            .VoidSubscribe(reload)
            .DisposedBy(disposeBag);

            View.SetNeedsLayout();
            View.LayoutIfNeeded();

            NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.DidBecomeActiveNotification, onApplicationDidBecomeActive);
        }
示例#10
0
        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);
        }
        public override void AwakeFromNib()
        {
            base.AwakeFromNib();

            FadeView.FadeRight = true;

            TimeLabel.Font = TimeLabel.Font.GetMonospacedDigitFont();
            ContinueButton.TouchUpInside += onContinueButtonTap;

            this.DelayBind(() =>
            {
                var colorConverter              = new MvxRGBValueConverter();
                var visibilityConverter         = new MvxVisibilityValueConverter();
                var durationCombiner            = new DurationValueCombiner();
                var invertedVisibilityConverter = new MvxInvertedVisibilityValueConverter();
                var projectTaskClientCombiner   = new ProjectTaskClientValueCombiner(
                    ProjectTaskClientLabel.Font.CapHeight,
                    Color.TimeEntriesLog.ClientColor.ToNativeColor(),
                    true
                    );
                var descriptionTopDistanceValueConverter =
                    new BoolToConstantValueConverter <nfloat>(hasProjectDistance, noProjectDistance);

                var bindingSet = this.CreateBindingSet <TimeEntriesLogViewCell, TimeEntryViewModel>();

                //Text
                bindingSet.Bind(DescriptionLabel).To(vm => vm.Description);
                bindingSet.Bind(ProjectTaskClientLabel)
                .For(v => v.AttributedText)
                .ByCombining(projectTaskClientCombiner,
                             v => v.ProjectName,
                             v => v.TaskName,
                             v => v.ClientName,
                             v => v.ProjectColor);

                bindingSet.Bind(TimeLabel)
                .ByCombining(durationCombiner,
                             vm => vm.Duration,
                             vm => vm.DurationFormat);

                //Visibility
                bindingSet.Bind(DescriptionTopDistanceConstraint)
                .For(v => v.Constant)
                .To(vm => vm.HasProject)
                .WithConversion(descriptionTopDistanceValueConverter);

                bindingSet.Bind(ProjectTaskClientLabel)
                .For(v => v.BindVisibility())
                .To(vm => vm.HasProject)
                .WithConversion(visibilityConverter);

                bindingSet.Bind(AddDescriptionLabel)
                .For(v => v.BindVisibility())
                .To(vm => vm.HasDescription)
                .WithConversion(invertedVisibilityConverter);

                bindingSet.Bind(AddDescriptionTopDistanceConstraint)
                .For(v => v.Constant)
                .To(vm => vm.HasProject)
                .WithConversion(descriptionTopDistanceValueConverter);

                bindingSet.Bind(SyncErrorImageView)
                .For(v => v.BindVisibility())
                .To(vm => vm.CanSync)
                .WithConversion(invertedVisibilityConverter);

                bindingSet.Bind(UnsyncedImageView)
                .For(v => v.BindVisibility())
                .To(vm => vm.NeedsSync)
                .WithConversion(visibilityConverter);

                bindingSet.Bind(ContinueButton)
                .For(v => v.BindVisibility())
                .To(vm => vm.CanSync)
                .WithConversion(visibilityConverter);

                bindingSet.Bind(ContinueImageView)
                .For(v => v.BindVisibility())
                .To(vm => vm.CanSync)
                .WithConversion(visibilityConverter);

                bindingSet.Apply();
            });
        }