/// <summary> /// Initializes a new instance of the <see cref="GraphNodeViewModel"/> class. /// </summary> /// <param name="ownerViewModel">The <see cref="GraphViewModel"/> that owns the new <see cref="GraphNodeViewModel"/>.</param> /// <param name="baseName">The base name of this node. Can be null if <see cref="index"/> is not. If so a name will be automatically generated from the index.</param> /// <param name="isPrimitive">Indicate whether this node should be considered as a primitive node.</param> /// <param name="sourceNode">The model node bound to the new <see cref="GraphNodeViewModel"/>.</param> /// <param name="graphNodePath">The <see cref="GraphNodePath"/> corresponding to the given <see cref="sourceNode"/>.</param> /// <param name="index">The index of this content in the model node, when this node represent an item of a collection. <see cref="Index.Empty"/> must be passed otherwise</param> protected GraphNodeViewModel(GraphViewModel ownerViewModel, string baseName, bool isPrimitive, IContentNode sourceNode, GraphNodePath graphNodePath, Index index) : base(ownerViewModel, baseName, index) { if (sourceNode == null) { throw new ArgumentNullException(nameof(sourceNode)); } if (baseName == null && index == null) { throw new ArgumentException("baseName and index can't be both null."); } this.isPrimitive = isPrimitive; SourceNode = sourceNode; // By default we will always combine items of list of primitive items. CombineMode = !index.IsEmpty && isPrimitive ? CombineMode.AlwaysCombine : CombineMode.CombineOnlyForAll; SourceNodePath = graphNodePath; // Override display name if available var memberDescriptor = GetMemberDescriptor() as MemberDescriptorBase; if (memberDescriptor != null) { if (index.IsEmpty) { var displayAttribute = TypeDescriptorFactory.Default.AttributeRegistry.GetAttribute <DisplayAttribute>(memberDescriptor.MemberInfo); if (!string.IsNullOrEmpty(displayAttribute?.Name)) { DisplayName = displayAttribute.Name; } IsReadOnly = !memberDescriptor.HasSet; } } }
protected NodeViewModel(GraphViewModel ownerViewModel, Index index) : base(ownerViewModel.ServiceProvider) { DependentProperties.Add(nameof(Path), new[] { nameof(DisplayPath) }); Owner = ownerViewModel; Index = index; Guid = Guid.NewGuid(); IsVisible = true; IsReadOnly = false; }
/// <summary> /// Initializes a new instance of the <see cref="SingleNodeViewModel"/> class. /// </summary> /// <param name="ownerViewModel">The <see cref="GraphViewModel"/> that owns the new <see cref="SingleNodeViewModel"/>.</param> /// <param name="baseName">The base name of this node. Can be null if <see cref="index"/> is not. If so a name will be automatically generated from the index.</param> /// <param name="index">The index of this content in the model node, when this node represent an item of a collection. <see cref="Index.Empty"/> must be passed otherwise</param> protected SingleNodeViewModel(GraphViewModel ownerViewModel, string baseName, Index index) : base(ownerViewModel, index) { if (baseName == null && index == null) { throw new ArgumentException("baseName and index can't be both null."); } CombineMode = CombineMode.CombineOnlyForAll; SetName(baseName); }
protected VirtualNodeViewModel(GraphViewModel owner, string name, bool isPrimitive, int?order, Index index, Func <object> getter, Action <object> setter) : base(owner, name, index) { if (getter == null) { throw new ArgumentNullException(nameof(getter)); } Getter = getter; Setter = setter; Order = order; IsPrimitive = isPrimitive; Name = name; }
public CombinedActionsContext(GraphViewModel owner, string actionName, string nodePath) { if (owner == null) { throw new ArgumentNullException(nameof(owner)); } var service = owner.ServiceProvider.TryGet <IUndoRedoService>(); if (service != null) { transaction = service.CreateTransaction(); service.SetName(transaction, actionName); } this.owner = owner; this.nodePath = nodePath; }
public static GraphViewModel CombineViewModels(IViewModelServiceProvider serviceProvider, IReadOnlyCollection <GraphViewModel> viewModels) { if (serviceProvider == null) { throw new ArgumentNullException(nameof(serviceProvider)); } if (viewModels == null) { throw new ArgumentNullException(nameof(viewModels)); } var combinedViewModel = new GraphViewModel(serviceProvider); var rootNodes = new List <GraphNodeViewModel>(); foreach (var viewModel in viewModels) { if (!(viewModel.RootNode is SingleNodeViewModel)) { throw new ArgumentException(@"The view models to combine must contains SingleNodeViewModel.", nameof(viewModels)); } viewModel.Parent = combinedViewModel; combinedViewModel.children.Add(viewModel); var rootNode = (GraphNodeViewModel)viewModel.RootNode; rootNodes.Add(rootNode); } if (rootNodes.Count < 2) { throw new ArgumentException(@"Called CombineViewModels with a collection of view models that is either empty or containt just a single item.", nameof(viewModels)); } // Find best match for the root node type var rootNodeType = rootNodes.First().Root.Type; if (rootNodes.Skip(1).Any(x => x.Type != rootNodeType)) { rootNodeType = typeof(object); } var service = serviceProvider.Get <GraphViewModelService>(); var rootCombinedNode = service.CombinedNodeViewModelFactory(combinedViewModel, "Root", rootNodeType, rootNodes, Index.Empty); combinedViewModel.RootNode = rootCombinedNode; rootCombinedNode.Initialize(); return(combinedViewModel); }
private static CombinedNodeViewModel DefaultCreateCombinedNode(GraphViewModel ownerViewModel, string baseName, Type contentType, IEnumerable <SingleNodeViewModel> combinedNodes, Index index) { return(CombinedNodeViewModel.Create(ownerViewModel, baseName, contentType, combinedNodes, index)); }
private static GraphNodeViewModel DefaultCreateNode(GraphViewModel viewModel, string baseName, bool isPrimitive, IContentNode modelNode, GraphNodePath graphNodePath, Type contentType, Index index) { return(GraphNodeViewModel.Create(viewModel, baseName, isPrimitive, modelNode, graphNodePath, contentType, index)); }
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(); } }); }
internal static CombinedNodeViewModel Create(GraphViewModel ownerViewModel, string name, Type contentType, IEnumerable <SingleNodeViewModel> combinedNodes, Index index) { var node = (CombinedNodeViewModel)Activator.CreateInstance(typeof(CombinedNodeViewModel <>).MakeGenericType(contentType), ownerViewModel, name, combinedNodes, index); return(node); }
/// <summary> /// Create an <see cref="GraphNodeViewModel{T}"/> that matches the given content type. /// </summary> /// <param name="ownerViewModel">The <see cref="GraphViewModel"/> that owns the new <see cref="GraphNodeViewModel"/>.</param> /// <param name="baseName">The base name of this node. Can be null if <see cref="index"/> is not. If so a name will be automatically generated from the index.</param> /// <param name="isPrimitive">Indicate whether this node should be considered as a primitive node.</param> /// <param name="sourceNode">The model node bound to the new <see cref="GraphNodeViewModel"/>.</param> /// <param name="graphNodePath">The <see cref="GraphNodePath"/> corresponding to the given node.</param> /// <param name="contentType">The type of content contained by the new <see cref="GraphNodeViewModel"/>.</param> /// <param name="index">The index of this content in the model node, when this node represent an item of a collection. <see cref="Index.Empty"/> must be passed otherwise</param> /// <returns>A new instance of <see cref="GraphNodeViewModel{T}"/> instanced with the given content type as generic argument.</returns> internal static GraphNodeViewModel Create(GraphViewModel ownerViewModel, string baseName, bool isPrimitive, IContentNode sourceNode, GraphNodePath graphNodePath, Type contentType, Index index) { var node = (GraphNodeViewModel)Activator.CreateInstance(typeof(GraphNodeViewModel <>).MakeGenericType(contentType), ownerViewModel, baseName, isPrimitive, sourceNode, graphNodePath, index); return(node); }
public GraphViewModelNodeValueChanged(GraphViewModel viewModel, string nodePath) { ViewModel = viewModel; NodePath = nodePath; }