public static ValueChangedRich <DomainT> BindRead <WidgetT, ViewT, DomainT>(this IReadOnlyValueView <WidgetT, ViewT> view, IReadOnlyValue <DomainT> domain, Func <DomainT, ViewT> convertFromDomain)
        {
            ValueChangedRich <DomainT> handler = (sender, oldValue, newValue, rawErrors, isUserAction) => {
                var errors           = rawErrors.ToList();
                var allErrors        = new HashSet <string>(errors);
                var value            = RunConvertingExceptionToFailure(convertFromDomain, newValue);
                var selfInvalidation = sender == view && errors.Any();

                if (!value.Success)
                {
                    allErrors.Add(value.ErrorMessage);
                }

                Logger.Debug(typeof(ValueViewExtensions), "BindRead handler called with value after conversion={0} errors={1} senderIsSelf={2} selfInvalidation={3}", value, sender == view, allErrors.PrettyToString(), selfInvalidation);

                if (!selfInvalidation)
                {
                    //don't overwrite errorneus entry if entry origins from self so that user sees wrong value
                    view.Value = value.Result;
                }

                view.SetErrors(allErrors, isUserAction);
            };

            domain.Changed += handler;
            return(handler);
        }
Example #2
0
        // REVIEW: valuetuple
        public static Tuple <ValueChangedRich <bool>, Action> BindAction <WidgetT, T>(this IActionView <WidgetT> view, IActionModel <T> domain)
        {
            ValueChangedRich <bool> domainHandler = (sender, oldValue, newValue, errors, isUserAction) => {
                Logger.Debug(typeof(ActionViewExtensions), "BindAction: changing view to {0} and {1}", newValue, errors.PrettyToString());
                view.Enabled        = newValue;
                view.DisabledReason = new HashSet <string>(errors);
            };

            domain.EnabledChanged += domainHandler;

            Action viewHandler = async() => {
                Logger.Debug(typeof(ActionViewExtensions), "BindAction: triggering enabled?={0} action {1} from view {2}", domain.Enabled, domain, view);
                if (!domain.Enabled)
                {
                    return;
                }

                view.State          = ActionViewState.CreateOperationRunning();
                view.Enabled        = false;
                view.DisabledReason = new HashSet <string> {
                    I18n.Translate("Please wait while operation is running...")
                };
                try {
                    await domain.Trigger();

                    view.State = ActionViewState.CreateIdleOrSuccess();
                } catch (Exception ex) {
                    Logger.Error(typeof(ActionViewExtensions), "Bound action failed to execute {0}", ex);
                    view.State = ActionViewState.CreateOperationFailed(ex);
                    //should be handled by domain.ActionExecuted subscribers
                } finally {
                    view.Enabled        = domain.Enabled;
                    view.DisabledReason = new HashSet <string>(domain.DisabledReasons);
                }
            };

            view.Triggered += viewHandler;
            return(new Tuple <ValueChangedRich <bool>, Action>(domainHandler, viewHandler));
        }