/// <summary> /// Called when the <see cref="Children"/> collection changes. /// </summary> /// <param name="sender">The event sender.</param> /// <param name="e">The event args.</param> private void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e) { List <Control> controls; // TODO: Handle Replace. switch (e.Action) { case NotifyCollectionChangedAction.Add: controls = e.NewItems.OfType <Control>().ToList(); SetLogicalParent(controls); AddVisualChildren(e.NewItems.OfType <Visual>()); LogicalChildren.InsertRange(e.NewStartingIndex, controls); break; case NotifyCollectionChangedAction.Remove: controls = e.OldItems.OfType <Control>().ToList(); ClearLogicalParent(e.OldItems.OfType <Control>()); LogicalChildren.RemoveAll(controls); RemoveVisualChildren(e.OldItems.OfType <Visual>()); break; case NotifyCollectionChangedAction.Reset: controls = e.OldItems.OfType <Control>().ToList(); ClearLogicalParent(controls); LogicalChildren.Clear(); ClearVisualChildren(); AddVisualChildren(_children); break; } InvalidateMeasure(); }
/// <summary> /// Called when containers are recycled for the <see cref="ItemsControl"/> by its /// <see cref="ItemContainerGenerator"/>. /// </summary> /// <param name="e">The details of the containers.</param> protected virtual void OnContainersRecycled(ItemContainerEventArgs e) { var toRemove = new List <ILogical>(); foreach (var container in e.Containers) { // If the item is its own container, then it will be removed from the logical tree // when it is removed from the Items collection. if (container?.ContainerControl != container?.Item) { toRemove.Add(container.ContainerControl); } } LogicalChildren.RemoveAll(toRemove); }
/// <summary> /// Given a collection of items, removes those that are controls to from logical children. /// </summary> /// <param name="items">The items.</param> private void RemoveControlItemsFromLogicalChildren(IEnumerable items) { var toRemove = new List <ILogical>(); if (items != null) { foreach (var i in items) { var control = i as IControl; if (control != null) { toRemove.Add(control); } } } LogicalChildren.RemoveAll(toRemove); }
/// <summary> /// Called when the <see cref="Children"/> collection changes. /// </summary> /// <param name="sender">The event sender.</param> /// <param name="e">The event args.</param> protected virtual void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e) { List <Control> controls; switch (e.Action) { case NotifyCollectionChangedAction.Add: controls = e.NewItems.OfType <Control>().ToList(); LogicalChildren.InsertRange(e.NewStartingIndex, controls); VisualChildren.InsertRange(e.NewStartingIndex, e.NewItems.OfType <Visual>()); break; case NotifyCollectionChangedAction.Move: LogicalChildren.MoveRange(e.OldStartingIndex, e.OldItems.Count, e.NewStartingIndex); VisualChildren.MoveRange(e.OldStartingIndex, e.OldItems.Count, e.NewStartingIndex); break; case NotifyCollectionChangedAction.Remove: controls = e.OldItems.OfType <Control>().ToList(); LogicalChildren.RemoveAll(controls); VisualChildren.RemoveAll(e.OldItems.OfType <Visual>()); break; case NotifyCollectionChangedAction.Replace: for (var i = 0; i < e.OldItems.Count; ++i) { var index = i + e.OldStartingIndex; var child = (IControl)e.NewItems[i]; LogicalChildren[index] = child; VisualChildren[index] = child; } break; case NotifyCollectionChangedAction.Reset: throw new NotSupportedException(); } InvalidateMeasure(); }