Ejemplo n.º 1
0
        public CombinablePropertyViewModel(TargetPlatform platform, IPropertyInfo property, IEnumerable <IObjectEditor> editors)
            : base(platform, property, editors)
        {
            this.predefinedValues = property as IHavePredefinedValues <TValue>;
            if (this.predefinedValues == null)
            {
                throw new ArgumentException("Property does not have predefined values", nameof(property));
            }
            if (this.predefinedValues.IsValueCombinable && !this.predefinedValues.IsConstrainedToPredefined)
            {
                throw new NotSupportedException("Properties with combinable values can not be unconstrained currently");
            }

            this.coerce    = property as ICoerce <IReadOnlyList <TValue> >;
            this.validator = property as IValidator <IReadOnlyList <TValue> >;

            var choices = new List <FlaggableChoiceViewModel <TValue> > (this.predefinedValues.PredefinedValues.Count);

            foreach (var kvp in this.predefinedValues.PredefinedValues)
            {
                var choiceVm = new FlaggableChoiceViewModel <TValue> (kvp.Key, kvp.Value);
                choiceVm.PropertyChanged += OnChoiceVmPropertyChanged;
                choices.Add(choiceVm);
            }

            Choices = choices;
            RequestCurrentValueUpdate();
        }
Ejemplo n.º 2
0
        private async Task PushValuesAsync(FlaggableChoiceViewModel <TValue> changedChoice)
        {
            SetError(null);

            using (await AsyncWork.RequestAsyncWork(this)) {
                try {
                    // Snapshot current choices so we don't catch updates mid-push for multi-editors
                    var currentChoices = Choices.ToDictionary(c => c, c => c.IsFlagged);

                    foreach (IObjectEditor editor in Editors)
                    {
                        ValueInfo <IReadOnlyList <TValue> > value = await editor.GetValueAsync <IReadOnlyList <TValue> > (Property, Variation);

                        HashSet <TValue> current;
                        if (value.Value == null || value.Source == ValueSource.Unset)
                        {
                            current = new HashSet <TValue> ();
                        }
                        else
                        {
                            current = new HashSet <TValue> (value.Value);
                        }

                        foreach (var choice in currentChoices)
                        {
                            if (!choice.Value.HasValue)
                            {
                                continue;
                            }

                            if (choice.Value.Value)
                            {
                                current.Add(choice.Key.Value);
                            }
                            else
                            {
                                current.Remove(choice.Key.Value);
                            }
                        }

                        IReadOnlyList <TValue> values = current.ToArray();
                        if (this.validator != null)
                        {
                            if (!this.validator.IsValid(values))
                            {
                                // Some combinables simply don't have a valid "none", but if we're going from indeterminate we still need to
                                // update the value, so we'll flip the changed value to true in that case so we don't go right back to indeterminate
                                if (values.Count == 0)
                                {
                                    changedChoice.IsFlagged = true;
                                    // We're explicitly triggering a change and need the update here so we need to update our snapshot.
                                    currentChoices = Choices.ToDictionary(c => c, c => c.IsFlagged);
                                }

                                continue;
                            }
                        }

                        if (this.coerce != null)
                        {
                            values = this.coerce.CoerceValue(values);
                        }

                        await editor.SetValueAsync(Property, new ValueInfo <IReadOnlyList <TValue> > {
                            Source = ValueSource.Local,
                            Value  = values
                        });
                    }
                } catch (Exception ex) {
                    if (ex is AggregateException aggregate)
                    {
                        aggregate = aggregate.Flatten();
                        ex        = aggregate.InnerExceptions[0];
                    }

                    SetError(ex.ToString());
                }
            }
        }