what is the difference between the two?
WPF's DockPanel:
RadDockPanel:
in which cases should i use RadDockPanel?
WPF's DockPanel:
/// <summary> /// DockPanel is used to size and position children inward from the edges of available space. /// /// A <see cref="System.Windows.Controls.Dock" /> enum (see <see cref="SetDock" /> and <see cref="GetDock" />) /// determines on which size a child is placed. Children are stacked in order from these edges until /// there is no more space; this happens when previous children have consumed all available space, or a child /// with Dock set to Fill is encountered. /// </summary> public class DockPanel : Panel { //------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------- #region Constructors /// <summary> /// Default DependencyObject constructor /// </summary> /// <remarks> /// Automatic determination of current Dispatcher. Use alternative constructor /// that accepts a Dispatcher for best performance. /// </remarks> public DockPanel() : base() { } #endregion //-------------------------------------------------------------------- // // Public Methods // //------------------------------------------------------------------- #region Public Methods /// <summary> /// Reads the attached property Dock from the given element. /// </summary> /// <param name="element">UIElement from which to read the attached property.</param> /// <returns>The property's value.</returns> /// <seealso cref="DockPanel.DockProperty" /> [AttachedPropertyBrowsableForChildren()] public static Dock GetDock(UIElement element) { if (element == null) { throw new ArgumentNullException("element"); } return (Dock) element.GetValue(DockProperty); } /// <summary> /// Writes the attached property Dock to the given element. /// </summary> /// <param name="element">UIElement to which to write the attached property.</param> /// <param name="dock">The property value to set</param> /// <seealso cref="DockPanel.DockProperty" /> public static void SetDock(UIElement element, Dock dock) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(DockProperty, dock); } private static void OnDockChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { UIElement uie = d as UIElement; //it may be anyting, like FlowDocument... bug 1237275 if(uie != null) { DockPanel p = VisualTreeHelper.GetParent(uie) as DockPanel; if(p != null) { p.InvalidateMeasure(); } } } #endregion //-------------------------------------------------------------------- // // Public Properties + Dependency Properties's // //-------------------------------------------------------------------- #region Public Properties /// <summary> /// This property controls whether the last child in the DockPanel should be stretched to fill any /// remaining available space. /// </summary> public bool LastChildFill { get { return (bool) GetValue(LastChildFillProperty); } set { SetValue(LastChildFillProperty, value); } } /// <summary> /// DependencyProperty for <see cref="LastChildFill" /> property. /// </summary> [CommonDependencyProperty] public static readonly DependencyProperty LastChildFillProperty = DependencyProperty.Register( "LastChildFill", typeof(bool), typeof(DockPanel), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsArrange)); /// <summary> /// DependencyProperty for Dock property. /// </summary> /// <seealso cref="DockPanel.GetDock" /> /// <seealso cref="DockPanel.SetDock" /> [CommonDependencyProperty] public static readonly DependencyProperty DockProperty = DependencyProperty.RegisterAttached( "Dock", typeof(Dock), typeof(DockPanel), new FrameworkPropertyMetadata( Dock.Left, new PropertyChangedCallback(OnDockChanged)), new ValidateValueCallback(IsValidDock)); #endregion //------------------------------------------------------------------- // // Protected Methods // //-------------------------------------------------------------------- #region Protected Methods /// <summary> /// Updates DesiredSize of the DockPanel. Called by parent UIElement. This is the first pass of layout. /// </summary> /// <remarks> /// Children are measured based on their sizing properties and <see cref="System.Windows.Controls.Dock" />. /// Each child is allowed to consume all of the space on the side on which it is docked; Left/Right docked /// children are granted all vertical space for their entire width, and Top/Bottom docked children are /// granted all horizontal space for their entire height. /// </remarks> /// <param name="constraint">Constraint size is an "upper limit" that the return value should not exceed.</param> /// <returns>The Panel's desired size.</returns> protected override Size MeasureOverride(Size constraint) { UIElementCollection children = InternalChildren; double parentWidth = 0; // Our current required width due to children thus far. double parentHeight = 0; // Our current required height due to children thus far. double accumulatedWidth = 0; // Total width consumed by children. double accumulatedHeight = 0; // Total height consumed by children. for (int i = 0, count = children.Count; i < count; ++i) { UIElement child = children[i]; Size childConstraint; // Contains the suggested input constraint for this child. Size childDesiredSize; // Contains the return size from child measure. if (child == null) { continue; } // Child constraint is the remaining size; this is total size minus size consumed by previous children. childConstraint = new Size(Math.Max(0.0, constraint.Width - accumulatedWidth), Math.Max(0.0, constraint.Height - accumulatedHeight)); // Measure child. child.Measure(childConstraint); childDesiredSize = child.DesiredSize; // Now, we adjust: // 1. Size consumed by children (accumulatedSize). This will be used when computing subsequent // children to determine how much space is remaining for them. // 2. Parent size implied by this child (parentSize) when added to the current children (accumulatedSize). // This is different from the size above in one respect: A Dock.Left child implies a height, but does // not actually consume any height for subsequent children. // If we accumulate size in a given dimension, the next child (or the end conditions after the child loop) // will deal with computing our minimum size (parentSize) due to that accumulation. // Therefore, we only need to compute our minimum size (parentSize) in dimensions that this child does // not accumulate: Width for Top/Bottom, Height for Left/Right. switch (DockPanel.GetDock(child)) { case Dock.Left: case Dock.Right: parentHeight = Math.Max(parentHeight, accumulatedHeight + childDesiredSize.Height); accumulatedWidth += childDesiredSize.Width; break; case Dock.Top: case Dock.Bottom: parentWidth = Math.Max(parentWidth, accumulatedWidth + childDesiredSize.Width); accumulatedHeight += childDesiredSize.Height; break; } } // Make sure the final accumulated size is reflected in parentSize. parentWidth = Math.Max(parentWidth, accumulatedWidth); parentHeight = Math.Max(parentHeight, accumulatedHeight); return (new Size(parentWidth, parentHeight)); } /// <summary> /// DockPanel computes a position and final size for each of its children based upon their /// <see cref="System.Windows.Controls.Dock" /> enum and sizing properties. /// </summary> /// <param name="arrangeSize">Size that DockPanel will assume to position children.</param> protected override Size ArrangeOverride(Size arrangeSize) { UIElementCollection children = InternalChildren; int totalChildrenCount = children.Count; int nonFillChildrenCount = totalChildrenCount - (LastChildFill ? 1 : 0); double accumulatedLeft = 0; double accumulatedTop = 0; double accumulatedRight = 0; double accumulatedBottom = 0; for (int i = 0; i < totalChildrenCount; ++i) { UIElement child = children[i]; if (child == null) { continue; } Size childDesiredSize = child.DesiredSize; Rect rcChild = new Rect( accumulatedLeft, accumulatedTop, Math.Max(0.0, arrangeSize.Width - (accumulatedLeft + accumulatedRight)), Math.Max(0.0, arrangeSize.Height - (accumulatedTop + accumulatedBottom)) ); if (i < nonFillChildrenCount) { switch (DockPanel.GetDock(child)) { case Dock.Left: accumulatedLeft += childDesiredSize.Width; rcChild.Width = childDesiredSize.Width; break; case Dock.Right: accumulatedRight += childDesiredSize.Width; rcChild.X = Math.Max(0.0, arrangeSize.Width - accumulatedRight); rcChild.Width = childDesiredSize.Width; break; case Dock.Top: accumulatedTop += childDesiredSize.Height; rcChild.Height = childDesiredSize.Height; break; case Dock.Bottom: accumulatedBottom += childDesiredSize.Height; rcChild.Y = Math.Max(0.0, arrangeSize.Height - accumulatedBottom); rcChild.Height = childDesiredSize.Height; break; } } child.Arrange(rcChild); } return (arrangeSize); } #endregion Protected Methods //------------------------------------------------------------------- // // Private Methods // //------------------------------------------------------------------- #region Private Methods internal static bool IsValidDock(object o) { Dock dock = (Dock)o; return ( dock == Dock.Left || dock == Dock.Top || dock == Dock.Right || dock == Dock.Bottom); } // // This property // 1. Finds the correct initial size for the _effectiveValues store on the current DependencyObject // 2. This is a performance optimization // internal override int EffectiveValuesInitialSize { get { return 9; } } #endregion Private Methods }RadDockPanel:
/// <summary> /// Defines an area where you can arrange child elements either horizontally or vertically, relative to each other. /// </summary> [DefaultProperty("LastChildFill")] public class RadDockPanel : Panel { /// <summary> /// Identifies the Dock attached property. /// </summary> public static readonly DependencyProperty DockProperty = DependencyProperty.RegisterAttached("Dock", typeof(Dock), typeof(RadDockPanel), new System.Windows.PropertyMetadata(Dock.Left, RadDockPanel.OnDockChanged)); /// <summary> /// Identifies the LastChildFill dependency property. /// </summary> public static readonly DependencyProperty LastChildFillProperty = DependencyProperty.Register("LastChildFill", typeof(bool), typeof(RadDockPanel), new System.Windows.PropertyMetadata(true, RadDockPanel.OnLastChildFillChanged)); /// <summary> /// Initializes a new instance of the <see cref="RadDockPanel"/> class. /// </summary> public RadDockPanel() { TelerikLicense.Verify(this); } /// <summary> /// Gets or sets a value that indicates whether the last child element within /// a DockPanel stretches to fill the remaining available space. This is a dependency property. /// </summary> public bool LastChildFill { get { return (bool)GetValue(LastChildFillProperty); } set { SetValue(LastChildFillProperty, value); } } /// <summary> /// Gets the value of the Dock attached property for a specified UIElement. /// </summary> /// <param name="element">The element from which the property value is read.</param> /// <returns>The Dock property value for the element.</returns> [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "Dock should be used on UIElements only.")] public static Dock GetDock(UIElement element) { if (element == null) { throw new ArgumentNullException("element"); } return (Dock)element.GetValue(DockProperty); } /// <summary> /// Sets the value of the Dock attached property to a specified element. /// </summary> [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "Dock should be used on UIElements only.")] public static void SetDock(UIElement element, Dock dock) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(DockProperty, dock); } internal static bool IsValidDock(object o) { Dock dock = (Dock)o; if (((dock != Dock.Left) && (dock != Dock.Top)) && (dock != Dock.Right)) { return dock == Dock.Bottom; } return true; } /// <summary> /// Provides the behavior for the "Arrange" pass of Silverlight layout. Classes can override this method to define their own arrange pass behavior. /// </summary> /// <param name="finalSize">The final area within the parent that this element should use to arrange itself and its children.</param> /// <returns>The actual size used.</returns> protected override Size ArrangeOverride(Size finalSize) { UIElementCollection internalChildren = Children; int count = internalChildren.Count; int num2 = count - (this.LastChildFill ? 1 : 0); double x = 0.0; double y = 0.0; double num5 = 0.0; double num6 = 0.0; for (int i = 0; i < count; i++) { UIElement element = internalChildren[i]; if (element != null) { Size desiredSize = element.DesiredSize; Rect finalRect = new Rect(x, y, Math.Max((double)0.0, (double)(finalSize.Width - (x + num5))), Math.Max((double)0.0, (double)(finalSize.Height - (y + num6)))); if (i < num2) { switch (GetDock(element)) { case Dock.Left: x += desiredSize.Width; finalRect.Width = desiredSize.Width; break; case Dock.Top: y += desiredSize.Height; finalRect.Height = desiredSize.Height; break; case Dock.Right: num5 += desiredSize.Width; finalRect.X = Math.Max((double)0.0, (double)(finalSize.Width - num5)); finalRect.Width = desiredSize.Width; break; case Dock.Bottom: num6 += desiredSize.Height; finalRect.Y = Math.Max((double)0.0, (double)(finalSize.Height - num6)); finalRect.Height = desiredSize.Height; break; } } element.Arrange(finalRect); } } return finalSize; } /// <summary> /// Provides the behavior for the "measure" pass of Silverlight layout. Classes can override this method to define their own measure pass behavior. /// </summary> /// <param name="availableSize">The available size that this element can give to child elements. Infinity can be specified as a value to indicate that the element will size to whatever content is available.</param> /// <returns> /// The size that this element determines it needs during layout, based on its calculations of child element sizes. /// </returns> protected override Size MeasureOverride(Size availableSize) { UIElementCollection internalChildren = Children; double num = 0.0; double num2 = 0.0; double num3 = 0.0; double num4 = 0.0; int num5 = 0; int count = internalChildren.Count; while (num5 < count) { UIElement element = internalChildren[num5]; if (element != null) { Size remainingSize = new Size(Math.Max((double)0.0, (double)(availableSize.Width - num3)), Math.Max((double)0.0, (double)(availableSize.Height - num4))); element.Measure(remainingSize); Size desiredSize = element.DesiredSize; switch (GetDock(element)) { case Dock.Left: case Dock.Right: num2 = Math.Max(num2, num4 + desiredSize.Height); num3 += desiredSize.Width; break; case Dock.Top: case Dock.Bottom: num = Math.Max(num, num3 + desiredSize.Width); num4 += desiredSize.Height; break; } } num5++; } num = Math.Max(num, num3); return new Size(num, Math.Max(num2, num4)); } private static void OnDockChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (!RadDockPanel.IsValidDock(e.NewValue)) { throw new ArgumentException("Invalid Dock value"); } FrameworkElement reference = d as FrameworkElement; if (reference != null) { RadDockPanel parent = reference.Parent as RadDockPanel; if (parent != null) { parent.InvalidateMeasure(); } } } private static void OnLastChildFillChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { RadDockPanel panel = d as RadDockPanel; if (panel != null) { panel.InvalidateArrange(); } } }in which cases should i use RadDockPanel?