public void Refresh() { if (Parent == null) { throw new InvalidOperationException("The node to refresh can be a root node."); } if (CombinedNodes.Any(x => x != null)) { var parent = (CombinedObservableNode)Parent; parent.NotifyPropertyChanging(Name); NotifyNodeUpdating(); if (AreCombinable(CombinedNodes)) { ClearCommands(); foreach (var child in Children.Cast <ObservableNode>().ToList()) { RemoveChild(child); } foreach (var modelNode in CombinedNodes.OfType <ObservableModelNode>()) { modelNode.ForceSetValue(modelNode.Value); } Initialize(); } NotifyNodeUpdated(); parent.NotifyPropertyChanged(Name); } }
public void Refresh() { if (Parent == null) { throw new InvalidOperationException("The node to refresh can be a root node."); } if (CombinedNodes.Any(x => x != null)) { var parent = (CombinedObservableNode)Parent; parent.NotifyPropertyChanging(Name); OnPropertyChanging(nameof(HasMultipleValues), nameof(IsPrimitive), nameof(HasList), nameof(HasDictionary)); if (AreCombinable(CombinedNodes)) { ClearCommands(); // Destroy all children and remove them Children.SelectDeep(x => x.Children).ForEach(x => x.Destroy()); foreach (var child in Children.Cast <ObservableNode>().ToList()) { RemoveChild(child); } Initialize(); } OnPropertyChanged(nameof(HasMultipleValues), nameof(IsPrimitive), nameof(HasList), nameof(HasDictionary)); parent.NotifyPropertyChanged(Name); } }
// TODO: do not remove from parent if we can avoid it public void Refresh() { if (Parent == null) { throw new InvalidOperationException("The node to refresh can be a root node."); } OnPropertyChanging("TypedValue", "HasMultipleValues", "IsPrimitive", "HasList", "HasDictionary"); if (CombinedNodes.Any(x => x != null)) { var parent = (CombinedObservableNode)Parent; parent.RemoveChild(this); if (AreCombinable(CombinedNodes)) { ClearCommands(); foreach (var child in Children.ToList()) { RemoveChild(child); } foreach (var modelNode in CombinedNodes.OfType <ObservableModelNode>()) { modelNode.Refresh(); } Initialize(true); } parent.AddChild(this); } OnPropertyChanged("TypedValue", "HasMultipleValues", "IsPrimitive", "HasList", "HasDictionary"); }
internal void Initialize() { var commandGroups = new Dictionary <string, List <ModelNodeCommandWrapper> >(); foreach (var node in combinedNodes) { foreach (var command in node.Commands) { var list = commandGroups.GetOrCreateValue(command.Name); list.Add((ModelNodeCommandWrapper)command); } } foreach (var commandGroup in commandGroups) { var mode = commandGroup.Value.First().CombineMode; if (commandGroup.Value.Any(x => x.CombineMode != mode)) { throw new InvalidOperationException(string.Format("Inconsistent combine mode among command {0}", commandGroup.Key)); } var shouldCombine = mode != CombineMode.DoNotCombine && (mode == CombineMode.AlwaysCombine || commandGroup.Value.Count == combinedNodes.Count); if (shouldCombine) { var command = new CombinedNodeCommandWrapper(ServiceProvider, commandGroup.Key, Path, Owner.Identifier, commandGroup.Value); AddCommand(command); } } if (!HasList || HasDictionary) { var commonChildren = GetCommonChildren(); GenerateChildren(commonChildren); } else { var allChildren = GetAllChildrenByValue(); if (allChildren != null) { // TODO: Disable list children for now - they need to be improved a lot (resulting combinaison is very random, especially for list of ints //GenerateListChildren(allChildren); } } foreach (var key in AssociatedData.Keys.ToList()) { RemoveAssociatedData(key); } // TODO: we add associatedData added to SingleObservableNode this way, but it's a bit dangerous. Maybe we should check that all combined nodes have this data entry, and all with the same value. foreach (var singleData in CombinedNodes.SelectMany(x => x.AssociatedData).Where(x => !AssociatedData.ContainsKey(x.Key))) { AddAssociatedData(singleData.Key, singleData.Value); } FinalizeChildrenInitialization(); CheckDynamicMemberConsistency(); }
/// <inheritdoc/> public override void Destroy() { foreach (var node in CombinedNodes.Where(x => !x.IsDestroyed)) { node.Destroy(); } base.Destroy(); }
public override void Dispose() { foreach (var node in CombinedNodes.Where(x => !x.IsDisposed)) { node.Dispose(); } base.Dispose(); }
protected CombinedObservableNode(ObservableViewModel ownerViewModel, string name, IEnumerable <SingleObservableNode> combinedNodes, Index index) : base(ownerViewModel, index) { // ReSharper disable once DoNotCallOverridableMethodsInConstructor DependentProperties.Add(nameof(Value), new[] { nameof(HasMultipleValues), nameof(IsPrimitive), nameof(HasList), nameof(HasDictionary) }); this.combinedNodes = new List <SingleObservableNode>(combinedNodes); Name = name; DisplayName = this.combinedNodes.First().DisplayName; combinedNodeInitialValues = new List <object>(); distinctCombinedNodeInitialValues = new HashSet <object>(); bool isReadOnly = false; bool isVisible = false; bool nullOrder = false; foreach (var node in this.combinedNodes) { if (node.IsDisposed) { throw new InvalidOperationException("One of the combined node is already disposed."); } if (node.IsReadOnly) { isReadOnly = true; } if (node.IsVisible) { isVisible = true; } if (node.Order == null) { nullOrder = true; } if (order == node.Order || (!nullOrder && order == null)) { order = node.Order; } combinedNodeInitialValues.Add(node.Value); distinctCombinedNodeInitialValues.Add(node.Value); } IsReadOnly = isReadOnly; IsVisible = isVisible; ResetInitialValues = new AnonymousCommand(ServiceProvider, () => { using (Owner.BeginCombinedAction(Owner.FormatCombinedUpdateMessage(this, null), Path)) { CombinedNodes.Zip(combinedNodeInitialValues).ForEach(x => x.Item1.Value = x.Item2); Refresh(); } }); }
private bool ComputeHasMultipleValues() { if (IsPrimitive) { return(CombinedNodes.Any(x => !Equals(x.Value, CombinedNodes.First().Value))); } return(!AreAllValuesOfTheSameType(CombinedNodes.Select(x => x.Value))); }
protected CombinedObservableNode(ObservableViewModel ownerViewModel, string name, IEnumerable <SingleObservableNode> combinedNodes, object index) : base(ownerViewModel, index) { this.combinedNodes = new List <SingleObservableNode>(combinedNodes); Name = name; DisplayName = this.combinedNodes.First().DisplayName; combinedNodeInitialValues = new List <object>(); distinctCombinedNodeInitialValues = new HashSet <object>(); bool isReadOnly = false; bool isVisible = false; bool nullOrder = false; foreach (var node in this.combinedNodes) { if (node.IsReadOnly) { isReadOnly = true; } if (node.IsVisible) { isVisible = true; } if (node.Order == null) { nullOrder = true; } if (order == node.Order || (!nullOrder && order == null)) { order = node.Order; } combinedNodeInitialValues.Add(node.Value); distinctCombinedNodeInitialValues.Add(node.Value); node.PropertyChanged += NodePropertyChanged; } IsReadOnly = isReadOnly; IsVisible = isVisible; ResetInitialValues = new AnonymousCommand(ServiceProvider, () => { Owner.BeginCombinedAction(); CombinedNodes.Zip(combinedNodeInitialValues).ForEach(x => x.Item1.Value = x.Item2); Refresh(); Owner.EndCombinedAction(Owner.FormatCombinedUpdateMessage(this, null), Path, null); }); }
protected CombinedNodeViewModel(GraphViewModel ownerViewModel, string name, IEnumerable <SingleNodeViewModel> combinedNodes, Index index) : base(ownerViewModel, index) { // ReSharper disable once DoNotCallOverridableMethodsInConstructor DependentProperties.Add(nameof(Value), new[] { nameof(HasMultipleValues), nameof(IsPrimitive), nameof(HasCollection), nameof(HasDictionary) }); this.combinedNodes = new List <SingleNodeViewModel>(combinedNodes); Name = name; DisplayName = this.combinedNodes.First().DisplayName; combinedNodeInitialValues = new List <object>(); distinctCombinedNodeInitialValues = new HashSet <object>(); bool isReadOnly = false; bool isVisible = false; bool nullOrder = false; foreach (var node in this.combinedNodes) { if (node.IsDestroyed) { throw new InvalidOperationException("One of the combined node is already disposed."); } if (node.IsReadOnly) { isReadOnly = true; } if (node.IsVisible) { isVisible = true; } if (node.Order == null) { nullOrder = true; } if (order == node.Order || (!nullOrder && order == null)) { order = node.Order; } // Note: sometimes member info could be different for the same member if we select objects of types that inherit from another // This will just affect the view order, so it shouldn't be a problem. if (memberInfo == null) { memberInfo = node.MemberInfo; } combinedNodeInitialValues.Add(node.Value); distinctCombinedNodeInitialValues.Add(node.Value); } IsReadOnly = isReadOnly; IsVisible = isVisible; ResetInitialValues = new AnonymousCommand(ServiceProvider, () => { using (Owner.BeginCombinedAction(Owner.FormatCombinedUpdateMessage(this, null), Path)) { CombinedNodes.Zip(combinedNodeInitialValues).ForEach(x => x.Item1.Value = x.Item2); Refresh(); } }); }