Example E4618
Visible to All Users

WPF LayoutControl - Change the LayoutGroup's Size Proportionally

This example demonstrates how to extend the LayoutControl and LayoutGroup behavior to support proportional resizing. The created LayoutItemSize property allows you to specify relative (star *) values.

Note

This custom solution may not support all possible usage scenarios and configurations. If proportional resizing is required, we recommend that you use controls that support this functionality out of the box (DockLayoutManager with layout groups and items or a standard Grid).

Files to Review

Documentation

Does this example address your development requirements/objectives?

(you will be redirected to DevExpress.com to submit your response)

Example Code

LayoutControl/DXSample/ExtraLayoutControl.cs(vb)
C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using DevExpress.Xpf.LayoutControl; namespace DXSample { public class ExtraLayoutControl : DevExpress.Xpf.LayoutControl.LayoutControl { protected override Size OnMeasure(Size constraint) { if (constraint.Width == 0 && constraint.Height == 0) return base.OnMeasure(constraint); Size maxConstraint = new Size(Double.PositiveInfinity, Double.PositiveInfinity); Size defaultConstraint = constraint; constraint = base.OnMeasure(constraint); if (Double.IsInfinity(defaultConstraint.Width) && Orientation == Orientation.Horizontal) defaultConstraint.Width = constraint.Width; if (Double.IsInfinity(defaultConstraint.Height) && Orientation == Orientation.Vertical) defaultConstraint.Height = constraint.Height; double starCount = 0; #region Create GroupLists List<ExtraLayoutGroup> listPixel = new List<ExtraLayoutGroup>(); List<ExtraLayoutGroup> listStar = new List<ExtraLayoutGroup>(); foreach (UIElement child in Children) { if (child is ExtraLayoutGroup) { if (((ExtraLayoutGroup)child).LayoutItemSize.Value > 0) switch (((ExtraLayoutGroup)child).LayoutItemSize.GridUnitType) { case GridUnitType.Pixel: listPixel.Add((ExtraLayoutGroup)child); break; case GridUnitType.Star: listStar.Add((ExtraLayoutGroup)child); starCount += ((ExtraLayoutGroup)child).LayoutItemSize.Value; break; } } } if (listPixel.Count == 0 && listStar.Count == 0) return constraint; #endregion #region Resize Pixeled foreach (ExtraLayoutGroup group in listPixel) { if (Orientation == Orientation.Horizontal) group.Width = group.LayoutItemSize.Value; else group.Height = group.LayoutItemSize.Value; group.InvalidateMeasure(); group.Measure((Orientation == Orientation.Horizontal) ? new Size(group.LayoutItemSize.Value, maxConstraint.Height) : new Size(maxConstraint.Width, group.LayoutItemSize.Value)); } #endregion constraint = base.OnMeasure(defaultConstraint); if (starCount == 0) return constraint; double starSize = 0; #region Calc StarSize Double usedSize = (Orientation == Orientation.Horizontal) ? constraint.Width : constraint.Height; foreach (ExtraLayoutGroup group in listStar) usedSize -= (Orientation == Orientation.Horizontal) ? group.DesiredSize.Width : group.DesiredSize.Height; Double availableSize = ((Orientation == Orientation.Horizontal) ? defaultConstraint.Width : defaultConstraint.Height) - usedSize; starSize = availableSize / starCount; #endregion #region Resize Starred foreach (ExtraLayoutGroup group in listStar) { if (Orientation == Orientation.Horizontal) group.Width = group.LayoutItemSize.Value * starSize; else group.Height = group.LayoutItemSize.Value * starSize; group.InvalidateMeasure(); group.Measure((Orientation == Orientation.Horizontal) ? new Size(group.Width, maxConstraint.Height) : new Size(maxConstraint.Width, group.Height)); } #endregion return base.OnMeasure(constraint); } } }
LayoutControl/DXSample/ExtraLayoutGroup.cs(vb)
C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using DevExpress.Xpf.LayoutControl; using System.Windows.Controls; namespace DXSample { public class ExtraLayoutGroup : LayoutGroup { public GridLength LayoutItemSize { get { return (GridLength)GetValue(LayoutItemSizeProperty); } set { SetValue(LayoutItemSizeProperty, value); } } public static readonly DependencyProperty LayoutItemSizeProperty = DependencyProperty.Register("LayoutItemSize", typeof(GridLength), typeof(ExtraLayoutGroup), new PropertyMetadata(new GridLength(0, GridUnitType.Star))); protected override Size OnMeasure(Size constraint) { if (constraint.Width == 0 && constraint.Height == 0) return base.OnMeasure(constraint); Size maxConstraint = new Size(Double.PositiveInfinity, Double.PositiveInfinity); Size defaultConstraint = constraint; constraint = base.OnMeasure(constraint); Size minConstraint = new Size(Math.Min(defaultConstraint.Width, constraint.Width), Math.Min(defaultConstraint.Height, constraint.Height)); double starCount = 0; #region Create GroupLists List<ExtraLayoutGroup> listPixel = new List<ExtraLayoutGroup>(); List<ExtraLayoutGroup> listStar = new List<ExtraLayoutGroup>(); foreach (UIElement child in Children) { if (child is ExtraLayoutGroup) { ExtraLayoutGroup group = (ExtraLayoutGroup)child; if (Parent is ExtraLayoutControl) { switch (((ExtraLayoutControl)Parent).Orientation) { case Orientation.Horizontal: ((FrameworkElement)child).HorizontalAlignment = HorizontalAlignment.Stretch; break; case Orientation.Vertical: ((FrameworkElement)child).VerticalAlignment = VerticalAlignment.Stretch; break; } } if (Parent is ExtraLayoutGroup) { switch (((ExtraLayoutGroup)Parent).Orientation) { case Orientation.Horizontal: ((FrameworkElement)child).HorizontalAlignment = HorizontalAlignment.Stretch; break; case Orientation.Vertical: ((FrameworkElement)child).VerticalAlignment = VerticalAlignment.Stretch; break; } } if (group.LayoutItemSize.Value > 0) switch (group.LayoutItemSize.GridUnitType) { case GridUnitType.Pixel: listPixel.Add((ExtraLayoutGroup)child); break; case GridUnitType.Star: listStar.Add((ExtraLayoutGroup)child); starCount += ((ExtraLayoutGroup)child).LayoutItemSize.Value; break; } } } if (listPixel.Count == 0 && listStar.Count == 0) return constraint; #endregion #region Resize Pixeled foreach (ExtraLayoutGroup group in listPixel) { if (Orientation == Orientation.Horizontal) group.Width = group.LayoutItemSize.Value; else group.Height = group.LayoutItemSize.Value; group.InvalidateMeasure(); group.Measure(minConstraint); } #endregion constraint = base.OnMeasure(minConstraint); minConstraint.Width = Math.Min(minConstraint.Width, constraint.Width); minConstraint.Height = Math.Min(minConstraint.Height, constraint.Height); if (starCount == 0) return minConstraint; double starSize = 0; #region Calc StarSize Double usedSize = (Orientation == Orientation.Horizontal) ? constraint.Width : constraint.Height; foreach (ExtraLayoutGroup group in listStar) usedSize -= (Orientation == Orientation.Horizontal) ? group.DesiredSize.Width : group.DesiredSize.Height; Double availableSize = ((Orientation == Orientation.Horizontal) ? minConstraint.Width : minConstraint.Height) - usedSize; starSize = availableSize / starCount; #endregion #region Resize Starred foreach (ExtraLayoutGroup group in listStar) { if (Orientation == Orientation.Horizontal) group.Width = group.LayoutItemSize.Value * starSize; else group.Height = group.LayoutItemSize.Value * starSize; group.InvalidateMeasure(); group.Measure((Orientation == Orientation.Horizontal) ? new Size(group.Width, minConstraint.Height) : new Size(minConstraint.Width, group.Height)); } #endregion return base.OnMeasure(minConstraint); } } }
LayoutControl/MainWindow.xaml
XAML
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:dxlc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol" xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking" xmlns:DXSample="clr-namespace:DXSample" xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors" x:Class="LayoutControl.MainWindow" Title="MainWindow" Height="356" Width="636"> <Grid> <Border BorderBrush="Black" BorderThickness="1" Margin="10"> <DXSample:ExtraLayoutControl Orientation="Horizontal" UseLayoutRounding="True"> <DXSample:ExtraLayoutGroup Orientation="Vertical" LayoutItemSize="2*"> <DXSample:ExtraLayoutGroup Header="LayoutGroup" View="Tabs" LayoutItemSize="1*"/> <DXSample:ExtraLayoutGroup Header="LayoutGroup" View="GroupBox" LayoutItemSize="30"/> <DXSample:ExtraLayoutGroup Header="LayoutGroup" View="GroupBox" LayoutItemSize="4*"/> </DXSample:ExtraLayoutGroup> <DXSample:ExtraLayoutGroup Orientation="Horizontal" LayoutItemSize="1*"> <DXSample:ExtraLayoutGroup Header="LayoutGroup" View="Tabs" Orientation="Vertical"> <DXSample:ExtraLayoutGroup Header="LayoutGroup" View="Group"/> <DXSample:ExtraLayoutGroup Header="LayoutGroup" View="Group"/> </DXSample:ExtraLayoutGroup> <dxlc:LayoutGroup Header="LayoutGroup" View="Tabs"/> </DXSample:ExtraLayoutGroup> <DXSample:ExtraLayoutGroup Header="LayoutGroup" View="GroupBox" LayoutItemSize="30"/> </DXSample:ExtraLayoutControl> </Border> </Grid> </Window>

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.