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); }
// 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)); }