/// <summary> /// Anchor a dockable pane (<see cref="DockablePane"/>) to a border of an other dockable pane /// </summary> /// <param name="paneToAnchor">Pane to anchor</param> /// <param name="relativePane">Pane relative</param> /// <param name="anchor"></param> public void Anchor(DockablePane paneToAnchor, DockablePane relativePane, AnchorStyle anchor) { //ensure that content property is not empty EnsureContentNotEmpty(); if (anchor == AnchorStyle.None) anchor = AnchorStyle.Right; //get a refernce to the resizingpanel container of relativePane ResizingPanel relativePaneContainer = LogicalTreeHelper.GetParent(relativePane) as ResizingPanel; Orientation requestedOrientation = (anchor == AnchorStyle.Bottom || anchor == AnchorStyle.Top) ? Orientation.Vertical : Orientation.Horizontal; if (relativePaneContainer == null) { Debug.Assert(relativePane.Parent == this); relativePaneContainer = new ResizingPanel(); relativePaneContainer.Orientation = requestedOrientation; this.Content = relativePaneContainer; relativePaneContainer.Children.Add(relativePane); } Debug.Assert(relativePaneContainer != null, "By now we can't have a pane without a resizing panel containing it"); #region Create and setup container panel if (relativePaneContainer != null) { //check if orientation is right if (relativePaneContainer.Orientation != requestedOrientation) { //if the existing panel is not oriented as we want //create a new one ResizingPanel newPanel = new ResizingPanel(); newPanel.Orientation = requestedOrientation; if (newPanel.Orientation == Orientation.Horizontal) ResizingPanel.SetResizeHeight(newPanel, ResizingPanel.GetResizeHeight(relativePane)); else ResizingPanel.SetResizeWidth(newPanel, ResizingPanel.GetResizeWidth(relativePane)); //replace relative pane in its' container panel //with this new panel int indexofRelativePane = relativePaneContainer.Children.IndexOf(relativePane); relativePaneContainer.Children.Remove(relativePane); relativePaneContainer.Children.Insert(indexofRelativePane, newPanel); //now we have a panel correctly placed in the tree newPanel.Children.Add(relativePane); newPanel.InsertChildRelativeTo( paneToAnchor, relativePane, anchor == AnchorStyle.Right || anchor == AnchorStyle.Bottom); relativePaneContainer = newPanel; } else { if (anchor == AnchorStyle.Left || anchor == AnchorStyle.Top) { //add new child before first (prepend) relativePaneContainer.InsertChildRelativeTo(paneToAnchor, relativePane, false); } else { //add new child after last (append) relativePaneContainer.InsertChildRelativeTo(paneToAnchor, relativePane, true); } } relativePaneContainer.InvalidateMeasure(); } #endregion //than set the new anchor style for the pane paneToAnchor.Anchor = relativePane.Anchor; if (anchor == AnchorStyle.Left || anchor == AnchorStyle.Right) { double w = Math.Min( ResizingPanel.GetEffectiveSize(relativePane).Width / 2.0, ResizingPanel.GetEffectiveSize(paneToAnchor).Width); ResizingPanel.SetResizeWidth(paneToAnchor, new GridLength(w, GridUnitType.Pixel)); ResizingPanel.SetResizeHeight(paneToAnchor, new GridLength(1.0, GridUnitType.Star)); } else { double h = Math.Min( ResizingPanel.GetEffectiveSize(relativePane).Height / 2.0, ResizingPanel.GetEffectiveSize(paneToAnchor).Height); ResizingPanel.SetResizeWidth(paneToAnchor, new GridLength(1.0, GridUnitType.Star)); ResizingPanel.SetResizeHeight(paneToAnchor, new GridLength(h, GridUnitType.Pixel)); } //refresh contents state foreach (DockableContent draggedContent in paneToAnchor.Items) { draggedContent.SetStateToDock(); } if (relativePaneContainer != null) relativePaneContainer.AdjustPanelSizes(); //paneToAnchor.Focus(); }
/// <summary> /// Anchor a dockable pane to a border /// </summary> /// <param name="paneToAnchor"></param> /// <param name="anchor"></param> public void Anchor(DockablePane paneToAnchor, AnchorStyle anchor) { //ensure that content property is not empty EnsureContentNotEmpty(); if (Content == null) return; //remove the pane from its original children collection FrameworkElement parentElement = paneToAnchor.Parent as FrameworkElement; if (anchor == AnchorStyle.None) anchor = AnchorStyle.Right; //Change anchor border according to FlowDirection if (FlowDirection == FlowDirection.RightToLeft) { if (anchor == AnchorStyle.Right) anchor = AnchorStyle.Left; else if (anchor == AnchorStyle.Left) anchor = AnchorStyle.Right; } //parentElement should be a DockingManager or a ResizingPanel if (parentElement is ContentControl) { ((ContentControl)parentElement).Content = null; } //and insert in the top level panel if exist ResizingPanel toplevelPanel = Content as ResizingPanel; if (toplevelPanel != null && toplevelPanel.Children.Count == 0) { Content = null; toplevelPanel = null; } Orientation requestedOrientation = (anchor == AnchorStyle.Bottom || anchor == AnchorStyle.Top) ? Orientation.Vertical : Orientation.Horizontal; //if toplevel panel contains only one child then just override the orientation //as requested if (toplevelPanel != null && toplevelPanel.Children.Count == 1) toplevelPanel.Orientation = requestedOrientation; if (toplevelPanel == null || toplevelPanel.Orientation != requestedOrientation) { //if toplevel panel doesn't exist or it has not the correct orientation //we have to create a new one and set it as content of docking manager toplevelPanel = new ResizingPanel(); toplevelPanel.Orientation = requestedOrientation; FrameworkElement contentElement = Content as FrameworkElement; _allowRefreshContents = false; Content = null; if (anchor == AnchorStyle.Left || anchor == AnchorStyle.Top) { toplevelPanel.Children.Add(paneToAnchor); toplevelPanel.InsertChildRelativeTo(contentElement, paneToAnchor, true); } else { toplevelPanel.Children.Add(paneToAnchor); toplevelPanel.InsertChildRelativeTo(contentElement, paneToAnchor, false); } _allowRefreshContents = true; Content = toplevelPanel; } else { //here we have a docking manager content with the right orientation //so we have only to insert new child at correct position if (anchor == AnchorStyle.Left || anchor == AnchorStyle.Top) { //add new child before first one (prepend) toplevelPanel.InsertChildRelativeTo(paneToAnchor, toplevelPanel.Children[0] as FrameworkElement, false); } else { //add new child after last one (append) toplevelPanel.InsertChildRelativeTo(paneToAnchor, toplevelPanel.Children[toplevelPanel.Children.Count - 1] as FrameworkElement, true); } } //Refresh anchor style DockablePane paneToAnchorAsDockablePane = paneToAnchor as DockablePane; if (paneToAnchorAsDockablePane != null) { paneToAnchorAsDockablePane.Anchor = anchor; } if (anchor == AnchorStyle.Left || anchor == AnchorStyle.Right) { double w = Math.Min( ActualWidth / 2.0, ResizingPanel.GetEffectiveSize(paneToAnchor).Width); ResizingPanel.SetResizeWidth(paneToAnchor, new GridLength(w, GridUnitType.Pixel)); ResizingPanel.SetResizeHeight(paneToAnchor, new GridLength(1.0, GridUnitType.Star)); } else { double h = Math.Min( ActualHeight / 2.0, ResizingPanel.GetEffectiveSize(paneToAnchor).Height); ResizingPanel.SetResizeWidth(paneToAnchor, new GridLength(1.0, GridUnitType.Star)); ResizingPanel.SetResizeHeight(paneToAnchor, new GridLength(h, GridUnitType.Pixel)); } //refresh contents state paneToAnchor.Items.OfType<DockableContent>().ForEach(dc => { dc.SetStateToDock(); }); //paneToAnchor.Focus(); toplevelPanel.InvalidateMeasure(); }