protected void OnContentChanged(object oldContent, object newContent) #endif { if (_isLoaded) { // Due to the fact that the children fill their "ParentWindow" // property by copying the value of the "ParentWindow" property // of their parent, we need to temporarily set it to be equal // to "this" before calling "base.OnContentChanged", so that it // then gets passed to the children recursively: this.INTERNAL_ParentWindow = this; // Attach the child UI element: #if RECURSIVE_CONSTRUCTION_FIXED base.OnContentChanged(oldContent, newContent); #else UIElement newChild = newContent as UIElement; UIElement oldChild = oldContent as UIElement; INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(oldChild, this); RemoveVisualChild(oldChild); AddVisualChild(newChild); INTERNAL_VisualTreeManager.AttachVisualChildIfNotAlreadyAttached(newChild, this); #endif // We can now revert the "ParentWindow" to null (cf. comment above): this.INTERNAL_ParentWindow = null; // Reset the print area so that it becomes the window root control: #if OPENSILVER if (false) #elif BRIDGE if (!CSHTML5.Interop.IsRunningInTheSimulator) #endif { if (CSHTML5.Native.Html.Printing.PrintManager.IsDefaultPrintArea) { CSHTML5.Native.Html.Printing.PrintManager.ResetPrintArea(); } } Application.Current.TextMeasurementService.CreateMeasurementText(this); /* * // Invalidate when content changed * InvalidateMeasure(); * InvalidateArrange(); * * // At the first contentChanged, InvaliateMeasure/Arrange does not work because IsArrangeValid and IsMeasureValid is false. * if (CSHTML5.Interop.IsRunningInTheSimulator_WorkAround) * { * Debug.WriteLine("Delayed CalculateWindowLayout"); * // On the simulator, Window Bounds height is zero at the startup. * Task.Delay(500).ContinueWith(t => CalculateWindowLayout()); * } * else * CalculateWindowLayout();*/ // Disabled for CustomLayout } }
protected void OnContentChanged(object oldContent, object newContent) #endif { if (_isLoaded) { // Due to the fact that the children fill their "ParentWindow" // property by copying the value of the "ParentWindow" property // of their parent, we need to temporarily set it to be equal // to "this" before calling "base.OnContentChanged", so that it // then gets passed to the children recursively: this.INTERNAL_ParentWindow = this; // Attach the child UI element: #if RECURSIVE_CONSTRUCTION_FIXED base.OnContentChanged(oldContent, newContent); #else INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(oldContent as UIElement, this); INTERNAL_VisualTreeManager.AttachVisualChildIfNotAlreadyAttached(newContent as UIElement, this); #endif // We can now revert the "ParentWindow" to null (cf. comment above): this.INTERNAL_ParentWindow = null; // Reset the print area so that it becomes the window root control: if (!CSHTML5.Interop.IsRunningInTheSimulator) { if (CSHTML5.Native.Html.Printing.PrintManager.IsDefaultPrintArea) { CSHTML5.Native.Html.Printing.PrintManager.ResetPrintArea(); } } } }
internal virtual void OnChildrenReset() { if (this.INTERNAL_VisualChildrenInformation != null) { foreach (var childInfo in this.INTERNAL_VisualChildrenInformation.Select(kp => kp.Value).ToArray()) { INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(childInfo.INTERNAL_UIElement, this); } } if (!this.HasChildren) { return; } if (this._enableProgressiveRendering || this.INTERNAL_EnableProgressiveLoading) { this.ProgressivelyAttachChildren(this.Children); } else { for (int i = 0; i < this.Children.Count; ++i) { INTERNAL_VisualTreeManager.AttachVisualChildIfNotAlreadyAttached(this.Children[i], this, i); } } }
internal virtual void OnChildrenReset() { if (this.INTERNAL_VisualChildrenInformation != null) { foreach (var childInfo in this.INTERNAL_VisualChildrenInformation.Select(kp => kp.Value).ToArray()) { INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(childInfo.INTERNAL_UIElement, this); } } if (this.EnableProgressiveRendering) { this.ProgressivelyAttachChildren(this.Children); } else { for (int i = 0; i < this.Children.Count; ++i) { #if REWORKLOADED this.AddVisualChild(this.Children[i], i); #else INTERNAL_VisualTreeManager.AttachVisualChildIfNotAlreadyAttached(this.Children[i], this, i); #endif } } }
protected override void OnTextRemovedOverride(TextElement textElement) { if (INTERNAL_VisualTreeManager.IsElementInVisualTree(this.Paragraph)) { INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(textElement, this.Paragraph); } }
static void Content_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) { UIElement parent = (UIElement)d; UIElement oldChild = (UIElement)e.OldValue; UIElement newChild = (UIElement)e.NewValue; INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(oldChild, parent); INTERNAL_VisualTreeManager.AttachVisualChildIfNotAlreadyAttached(newChild, parent); }
internal void OnPanelChangedInternal() { if (this.ItemsHost != null) { #if WORKINPROGRESS // Panel is no longer ItemsHost this.ItemsHost.IsItemsHost = false; #endif // Detach old panel INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(this.ItemsHost, this); } if (this._templateCache != null) { // Create an instance of the Panel FrameworkElement visualTree = this._templateCache.INTERNAL_InstantiateFrameworkTemplate(null); Panel panel = visualTree as Panel; if (panel != null) { // Make sure that the panel contains no children if (panel.Children.Count > 0) { throw new InvalidOperationException("VisualTree of ItemsPanelTemplate must be a single element."); } this._itemsHost = panel; #if WORKINPROGRESS // set IsItemsHost flag panel.IsItemsHost = true; #endif } else { throw new InvalidOperationException(string.Format("VisualTree of ItemsPanelTemplate must contain a Panel. '{0}' is not a Panel.", visualTree.GetType())); } // attach the panel. #if REWORKLOADED this.AddVisualChild(panel); #else INTERNAL_VisualTreeManager.AttachVisualChildIfNotAlreadyAttached(panel, this); #endif // Attach children to panel if (this.Owner != null) { this.Owner.Refresh(); } } else { this._itemsHost = null; this.Owner.ItemContainerGenerator.INTERNAL_Clear(); } }
protected override void ApplySelectedIndex(int index) { base.ApplySelectedIndex(index); if (_useNativeComboBox) { SetSelectedIndexInNativeHtmlDom(this.SelectedIndex); } else { UIElement newSelectedContent; if (index == -1) { if (_contentPresenter != null) { _contentPresenter.Content = null; } newSelectedContent = null; } else if (this.Items != null && index < this.Items.Count) { var item = this.Items[index]; // If the item is a FrameworkElement, we detach it from its current parent (if any) so that we can later put it into the ContentPresenter: if (item is FrameworkElement) { // Detach it from the current parent: if (((FrameworkElement)item).INTERNAL_VisualParent is UIElement) { INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(((FrameworkElement)item), (UIElement)((FrameworkElement)item).INTERNAL_VisualParent); } } else if (item != null) { // Otherwise, we create a FrameworkElement out of the item: item = GenerateFrameworkElementToRenderTheItem(item); } newSelectedContent = (FrameworkElement)item; // Note: this can be null. // We put the selected content into the ContentPresenter: if (_contentPresenter != null) { _contentPresenter.Content = newSelectedContent; // Note: this can be null. } } else { throw new IndexOutOfRangeException(); } _selectedContent = newSelectedContent; } }
internal virtual void OnChildrenReplaced(UIElement oldChild, UIElement newChild, int index) { if (oldChild == newChild) { return; } INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(oldChild, this); INTERNAL_VisualTreeManager.AttachVisualChildIfNotAlreadyAttached(newChild, this, index); }
private void DetachChild() { if (object.ReferenceEquals(this, this.Child)) // if ContentTemplate is null and Content is not an UIElement { INTERNAL_HtmlDomManager.SetContentString(this, string.Empty, removeTextWrapping: true); } else { INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(this.Child, this); } this.Child = null; }
protected override void ApplySelectedIndex(int index) { base.ApplySelectedIndex(index); UIElement newSelectedContent; if (index == -1) { // index is sometimes at -1, for exemple when the app is starting // not en exception but we don't want to treat it as there is no item newSelectedContent = null; } else if (this.Items != null && index < this.Items.Count) { var item = this.Items[index]; // If the item is a FrameworkElement, we detach it from its current parent (if any) so that we can later put it into the ContentPresenter: if (item is FrameworkElement) { // Detach it from the current parent: if (((FrameworkElement)item).INTERNAL_VisualParent is UIElement) { INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(((FrameworkElement)item), (UIElement)((FrameworkElement)item).INTERNAL_VisualParent); } } else if (item != null) { // Otherwise, we create a FrameworkElement out of the item: item = GenerateFrameworkElementToRenderTheItem(item); } newSelectedContent = (FrameworkElement)item; // Note: this can be null. if (_textBox != null) { if (newSelectedContent is TextBlock) { TextBlock textblock = (TextBlock)newSelectedContent; _textBox.Text = textblock.Text; } } } else { throw new IndexOutOfRangeException(); } _selectedContent = newSelectedContent; }
internal virtual void ManageChildrenChanged(UIElementCollection oldChildren, UIElementCollection newChildren) { if (oldChildren != null) { // Detach old children only if they are not in the "newChildren" collection: foreach (UIElement child in oldChildren) //note: there is no setter for Children so the user cannot change the order of the elements in one step --> we cannot have the same children in another order (which would keep the former order with the way it is handled now) --> no problem here { #if PERFSTAT var t2 = Performance.now(); #endif if (newChildren == null || !newChildren.Contains(child)) { #if PERFSTAT Performance.Counter("Panel.ManageChildrenChanged 'Contains'", t2); #endif INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(child, this); } else { #if PERFSTAT Performance.Counter("Panel.ManageChildrenChanged 'Contains'", t2); #endif } } } if (newChildren != null) { // Note: we attach all the children (regardless of whether they are in the oldChildren collection or not) to make it work when the item is first added to the Visual Tree (at that moment, all the properties are refreshed by calling their "Changed" method). if (this.EnableProgressiveRendering) { this.ProgressivelyAttachChildren(newChildren); } else { foreach (UIElement child in newChildren) { #if REWORKLOADED this.AddVisualChild(child); #else INTERNAL_VisualTreeManager.AttachVisualChildIfNotAlreadyAttached(child, this); #endif } } } }
protected virtual void UpdateItemsPanel(ItemsPanelTemplate newTemplate) { if (!_disableDefaultRendering) { if (_placeWhereItemsPanelWillBeRendered != null //&& INTERNAL_VisualTreeManager.IsElementInVisualTree(_placeWhereItemsPanelWillBeRendered)) && _placeWhereItemsPanelWillBeRendered._isLoaded) //Note: we replaced "IsElementInVisualTree" with _isLoaded on on March 22, 2017 to fix an issue where a "Binding" on ListBox.ItemsSource caused the selection to not work properly. This change can be reverted the day that the implementation of the "IsElementInVisualTree" method becomes based on the "_isLoaded" property (at the time of writing, it was implemented by checking if the visual parent is null). { INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(this._renderedItemsPanel, _placeWhereItemsPanelWillBeRendered); if (newTemplate != null) { // Create an instance of the Panel: _renderedItemsPanel = newTemplate.INTERNAL_InstantiateFrameworkTemplate(); // Make sure the panel derives from the type "Panel": if (!(_renderedItemsPanel is Panel)) { throw new InvalidOperationException("ItemsControl.ItemsPanelTemplate must derive from Panel."); } // Make sure that the panel contains no children: if (((Panel)_renderedItemsPanel).Children != null && ((Panel)_renderedItemsPanel).Children.Count > 0) { throw new InvalidOperationException("Cannot explicitly modify Children collection of Panel used as ItemsPanel for ItemsControl. ItemsControl generates child elements for Panel."); } // Attach the panel: INTERNAL_VisualTreeManager.AttachVisualChildIfNotAlreadyAttached(_renderedItemsPanel, _placeWhereItemsPanelWillBeRendered); // Update the children: if (_actualItemsSource != null) { OnItemsChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); UpdateChildrenInVisualTree(_actualItemsSource, _actualItemsSource, forceUpdateAllChildren: true); } } else { // The ItemsPanel is null, so we display nothing (like in WPF): _renderedItemsPanel = null; _itemContainerGenerator.INTERNAL_Clear(); } } } }
//static void ContentTemplate_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) //{ // var contentControl = (ContentControl)d; // object newText = e.NewValue; // //todo: apply the new template to the content (if the content is set) // //if (INTERNAL_VisualTreeManager.IsElementInVisualTree(contentControl)) // // apply template //} /// <summary> /// Invoked when the value of the Content property changes. /// </summary> /// <param name="oldContent">The old value of the Content property.</param> /// <param name="newContent">The new value of the Content property.</param> protected virtual void OnContentChanged(object oldContent, object newContent) { if (!this.HasTemplate) { //----------------------------- // DETACH PREVIOUS CONTENT //----------------------------- if (oldContent is UIElement) { INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull((UIElement)oldContent, this); } if (_dataTemplateRenderedContent != null) { INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(_dataTemplateRenderedContent, this); } _dataTemplateRenderedContent = null; //----------------------------- // ATTACH NEW CONTENT //----------------------------- if (newContent is UIElement) { INTERNAL_VisualTreeManager.AttachVisualChildIfNotAlreadyAttached((UIElement)newContent, this); } else if (INTERNAL_VisualTreeManager.IsElementInVisualTree(this)) { if (ContentTemplate != null) { // Apply the data template: _dataTemplateRenderedContent = ContentTemplate.INTERNAL_InstantiateFrameworkTemplate(); _dataTemplateRenderedContent.DataContext = newContent; INTERNAL_VisualTreeManager.AttachVisualChildIfNotAlreadyAttached(_dataTemplateRenderedContent, this); } else if (newContent != null) { // Show the string: INTERNAL_HtmlDomManager.SetContentString(this, newContent.ToString(), removeTextWrapping: true); } } } }
public void CreateMeasurementText(UIElement parent) { // For TextBox if (associatedTextBox != null) { INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(associatedTextBox, parent); } associatedTextBox = new TextBox(); INTERNAL_VisualTreeManager.AttachVisualChildIfNotAlreadyAttached(associatedTextBox, parent); textBoxReference = associatedTextBox.INTERNAL_OuterDomElement; textBoxDivStyle = INTERNAL_HtmlDomManager.GetDomElementStyleForModification(textBoxReference); textBoxDivStyle.position = "absolute"; textBoxDivStyle.visibility = "hidden"; textBoxDivStyle.height = ""; textBoxDivStyle.width = ""; textBoxDivStyle.top = "0px"; textBoxDivStyle.borderWidth = "1"; measureTextBoxElementID = ((INTERNAL_HtmlDomElementReference)textBoxReference).UniqueIdentifier; // For TextBlock if (associatedTextBlock != null) { INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(associatedTextBlock, parent); } associatedTextBlock = new TextBlock(); INTERNAL_VisualTreeManager.AttachVisualChildIfNotAlreadyAttached(associatedTextBlock, parent); textBlockReference = associatedTextBlock.INTERNAL_OuterDomElement; textBlockDivStyle = INTERNAL_HtmlDomManager.GetDomElementStyleForModification(textBlockReference); textBlockDivStyle.position = "absolute"; textBlockDivStyle.visibility = "hidden"; textBlockDivStyle.height = ""; textBlockDivStyle.width = ""; textBlockDivStyle.top = "100px"; textBlockDivStyle.borderWidth = "1"; textBlockDivStyle.whiteSpace = "pre"; associatedTextBlock.Text = "A"; measureTextBlockElementID = ((INTERNAL_HtmlDomElementReference)textBlockReference).UniqueIdentifier; CSHTML5.Interop.ExecuteJavaScriptAsync(@"document.measureTextBlockElement=$0", textBlockReference); }
protected virtual bool TryRemoveChildItemFromVisualTree(object item) { if (!_disableDefaultRendering) { ////----------------------------- //// DETACH ITEM ////----------------------------- var containerIfAny = _itemContainerGenerator.ContainerFromItem(item); if (containerIfAny == null) { if (item is UIElement) { // It means that no DataTemplate was applied, so we just remove the element. UIElement itemAsUIElement = (UIElement)item; if (itemAsUIElement.INTERNAL_VisualParent != null) { INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(itemAsUIElement, (UIElement)itemAsUIElement.INTERNAL_VisualParent); return(true); } } } else if (containerIfAny is FrameworkElement) { FrameworkElement containerAsFrameworkElement = (FrameworkElement)containerIfAny; if ((UIElement)((FrameworkElement)containerIfAny).INTERNAL_VisualParent != null) { INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull((FrameworkElement)containerIfAny, (UIElement)((FrameworkElement)containerIfAny).INTERNAL_VisualParent); } if (INTERNAL_VisualTreeManager.IsElementInVisualTree(_renderedItemsPanel)) { return(_itemContainerGenerator.INTERNAL_TryUnregisterContainer(containerIfAny, item)); } } } return(false); }
private void MakeUIStructure() { //we go through the children and determine the rows, columns and positions in the grid: if (this.HasChildren) { int amountOfRows = 1; // = 1 for the remaining space int amountOfColumns = 1; // = 1 for the remaining space Dock lastChildDock = Dock.Left; //We only need it to know the amount of rows and columns and to know which row and column are the "remaining space" (sized at star) in the case where LastChildFill is true. //first pass: we count the amount of rows and columns. foreach (UIElement child in Children) { //get the Dock value of the child: Dock dock = DockPanel.GetDock(child); if (dock == Dock.Left || dock == Dock.Right) { ++amountOfColumns; } else { ++amountOfRows; } } if (LastChildFill) //if the last child fills the remaining space, we "remove" the row/column we "added" for this child. { lastChildDock = GetDock(Children[Children.Count - 1]); if (lastChildDock == Dock.Right || lastChildDock == Dock.Left) { --amountOfColumns; } else { --amountOfRows; } } //second pass: we determine the Grid.Row, Grid.Column, Grid.RowSpan and Grid.ColumnsSpan for each child. int amountOfRightPlaced = 0; int amountOfLeftPlaced = 0; int amountOfTopPlaced = 0; int amountOfBottomPlaced = 0; foreach (UIElement child in Children) { //get the Dock value of the child: Dock dock = DockPanel.GetDock(child); switch (dock) { case Dock.Left: Grid.SetRow(child, amountOfTopPlaced); Grid.SetColumn(child, amountOfLeftPlaced); Grid.SetRowSpan(child, amountOfRows - amountOfTopPlaced - amountOfBottomPlaced); Grid.SetColumnSpan(child, 1); ++amountOfLeftPlaced; break; case Dock.Top: Grid.SetRow(child, amountOfTopPlaced); Grid.SetColumn(child, amountOfLeftPlaced); Grid.SetRowSpan(child, 1); Grid.SetColumnSpan(child, amountOfColumns - amountOfLeftPlaced - amountOfRightPlaced); ++amountOfTopPlaced; break; case Dock.Right: Grid.SetRow(child, amountOfTopPlaced); Grid.SetColumn(child, amountOfColumns - amountOfRightPlaced - 1); Grid.SetRowSpan(child, amountOfRows - amountOfTopPlaced - amountOfBottomPlaced); Grid.SetColumnSpan(child, 1); ++amountOfRightPlaced; break; case Dock.Bottom: Grid.SetRow(child, amountOfRows - amountOfBottomPlaced - 1); Grid.SetColumn(child, amountOfLeftPlaced); Grid.SetRowSpan(child, 1); Grid.SetColumnSpan(child, amountOfColumns - amountOfLeftPlaced - amountOfRightPlaced); ++amountOfBottomPlaced; break; default: break; } } //we remove the grid because we will change its structure A LOT, and we want to avoid redrawing everything on each change: INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(_grid, this); ColumnDefinitionCollection columnsDefinitions = _grid.ColumnDefinitions; columnsDefinitions.Clear(); for (int i = 0; i < amountOfColumns; ++i) { columnsDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto }); } RowDefinitionCollection rowsDefinitions = _grid.RowDefinitions; rowsDefinitions.Clear(); for (int i = 0; i < amountOfRows; ++i) { rowsDefinitions.Add(new RowDefinition() { Height = GridLength.Auto }); } if (!LastChildFill) { columnsDefinitions.ElementAt(amountOfLeftPlaced).Width = new GridLength(1, GridUnitType.Star); rowsDefinitions.ElementAt(amountOfTopPlaced).Height = new GridLength(1, GridUnitType.Star); } else { //the position of the "remaining space" depends on the last child's dock: if (lastChildDock == Dock.Left) { columnsDefinitions.ElementAt(amountOfLeftPlaced - 1).Width = new GridLength(1, GridUnitType.Star); //minus 1 because the column index of the last child placed left is also the column index of the "remaining space". } else { columnsDefinitions.ElementAt(amountOfLeftPlaced).Width = new GridLength(1, GridUnitType.Star); } if (lastChildDock == Dock.Top) { rowsDefinitions.ElementAt(amountOfTopPlaced - 1).Height = new GridLength(1, GridUnitType.Star); //minus 1 because the column index of the last child placed left is also the column index of the "remaining space". } else { rowsDefinitions.ElementAt(amountOfTopPlaced).Height = new GridLength(1, GridUnitType.Star); //minus 1 because the column index of the last child placed left is also the column index of the "remaining space". } } //the changes on the grid's structure are over so we can put it back. INTERNAL_VisualTreeManager.AttachVisualChildIfNotAlreadyAttached(_grid, this); } }
static void ManageChildrenChanged(DependencyObject d, UIElementCollection oldChildren, UIElementCollection newChildren) { #if PERFSTAT var t1 = Performance.now(); #endif Panel parent = (Panel)d; if (parent is DockPanel) { ((DockPanel)parent).ManageChildrenChanged(oldChildren, newChildren); } else { bool isCSSGrid = Grid_InternalHelpers.isCSSGridSupported(); if (!isCSSGrid && parent is Grid) { ((Grid)parent).ManageChildrenChanged(oldChildren, newChildren); } else { if (oldChildren != null) { //// Put the list in a HashSet for performant lookup: //HashSet<UIElement> newChidrenHashSet = new HashSet<UIElement>(); //if (newChildren != null) //{ // foreach (UIElement child in newChildren) // newChidrenHashSet.Add(child); //} //// Detach old children only if they are not in the "newChildren" collection: //foreach (UIElement child in oldChildren) //{ // if (newChildren == null || !newChidrenHashSet.Contains(child)) //todo: verify that in the produced JavaScript, "newChidrenHashSet.Contains" has still a O(1) complexity. // { // INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(child, parent); // } //} //todo: use HashSet version. // Detach old children only if they are not in the "newChildren" collection: foreach (UIElement child in oldChildren) //note: there is no setter for Children so the user cannot change the order of the elements in one step --> we cannot have the same children in another order (which would keep the former order with the way it is handled now) --> no problem here { #if PERFSTAT var t2 = Performance.now(); #endif if (newChildren == null || !newChildren.Contains(child)) { #if PERFSTAT Performance.Counter("Panel.ManageChildrenChanged 'Contains'", t2); #endif INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(child, parent); } else { #if PERFSTAT Performance.Counter("Panel.ManageChildrenChanged 'Contains'", t2); #endif } } } if (newChildren != null) { foreach (UIElement child in newChildren) { // Note: we do this for all items (regardless of whether they are in the oldChildren collection or not) to make it work when the item is first added to the Visual Tree (at that moment, all the properties are refreshed by calling their "Changed" method). INTERNAL_VisualTreeManager.AttachVisualChildIfNotAlreadyAttached(child, parent); } } if (parent is Grid) { ((Grid)parent).LocallyManageChildrenChanged(); } } } }
internal virtual void OnChildrenRemoved(UIElement oldChild, int index) { INTERNAL_VisualTreeManager.DetachVisualChildIfNotNull(oldChild, this); }