mirror of
https://github.com/crskycode/GARbro.git
synced 2024-11-26 23:24:00 +08:00
GridLayout widget implementation.
Grid that addes ChildMargin to its children
This commit is contained in:
parent
8231af20c4
commit
93c4911bfa
107
GridLayout.cs
Normal file
107
GridLayout.cs
Normal file
@ -0,0 +1,107 @@
|
||||
// http://daniel-albuschat.blogspot.ru/2011/07/gridlayout-for-wpf-escape-margin-hell.html
|
||||
//
|
||||
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace GridLayoutTest
|
||||
{
|
||||
// The GridLayout is a special Panel that can be used exactly like the Grid Panel, except that it
|
||||
// defines a new property ChildMargin. ChildMargin's left, top, right and bottom margins will be applied
|
||||
// to all children in a way that the children will have a vertical space of ChildMargin.Top+ChildMargin.Bottom
|
||||
// and a horizontal space of ChildMargin.Left+ChildMargin.Right between them.
|
||||
// However, there is no margin for the borders of the internal widget, so that the GridLayout itself can be
|
||||
// aligned to another element without a margin.
|
||||
// It's best to have a look at TestWindow, which effectively tests all possible alignments of children.
|
||||
|
||||
public class GridLayout : Grid
|
||||
{
|
||||
public static readonly DependencyProperty ChildMarginProperty = DependencyProperty.Register(
|
||||
"ChildMargin",
|
||||
typeof(Thickness),
|
||||
typeof(GridLayout),
|
||||
new FrameworkPropertyMetadata(new Thickness (5))
|
||||
{
|
||||
AffectsArrange = true,
|
||||
AffectsMeasure = true
|
||||
});
|
||||
// The child margin defines a margin that will be automatically applied to all children of this Grid.
|
||||
// However, the children at the edges will have the respective margins remove. E.g. the leftmost children will have
|
||||
// a Margin.Left of 0 and the children in the first row will have a Margin.Top of 0.
|
||||
// The margins that are not set to 0 are set to half the ChildMargin's value, since it's neighbour will also apply it,
|
||||
// effectively doubling it.
|
||||
|
||||
public Thickness ChildMargin
|
||||
{
|
||||
get { return (Thickness)GetValue(ChildMarginProperty); }
|
||||
set
|
||||
{
|
||||
SetValue(ChildMarginProperty, value);
|
||||
UpdateChildMargins();
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateChildMargin first finds out what's the rightmost column and bottom row and then applies
|
||||
// the correct margins to all children.
|
||||
|
||||
public void UpdateChildMargins()
|
||||
{
|
||||
int maxColumn = 0;
|
||||
int maxRow = 0;
|
||||
foreach (UIElement element in InternalChildren)
|
||||
{
|
||||
int row = GetRow(element);
|
||||
int rowSpan = GetRowSpan(element);
|
||||
int column = GetColumn(element);
|
||||
int columnSpan = GetColumnSpan(element);
|
||||
|
||||
if (row + rowSpan > maxRow)
|
||||
maxRow = row + rowSpan;
|
||||
if (column + columnSpan> maxColumn)
|
||||
maxColumn = column + columnSpan;
|
||||
}
|
||||
foreach (UIElement element in InternalChildren)
|
||||
{
|
||||
FrameworkElement fe = element as FrameworkElement;
|
||||
if (null != fe)
|
||||
{
|
||||
int row = GetRow(fe);
|
||||
int rowSpan = GetRowSpan(fe);
|
||||
int column = GetColumn(fe);
|
||||
int columnSpan = GetColumnSpan(fe);
|
||||
double factorLeft = 0.5;
|
||||
double factorTop = 0.5;
|
||||
double factorRight = 0.5;
|
||||
double factorBottom = 0.5;
|
||||
// Top row - no top margin
|
||||
if (row == 0)
|
||||
factorTop = 0;
|
||||
// Bottom row - no bottom margin
|
||||
if (row + rowSpan >= maxRow)
|
||||
factorBottom = 0;
|
||||
// Leftmost column = no left margin
|
||||
if (column == 0)
|
||||
factorLeft = 0;
|
||||
// Rightmost column - no right margin
|
||||
if (column + columnSpan >= maxColumn)
|
||||
factorRight = 0;
|
||||
fe.Margin = new Thickness (ChildMargin.Left * factorLeft,
|
||||
ChildMargin.Top * factorTop,
|
||||
ChildMargin.Right * factorRight,
|
||||
ChildMargin.Bottom * factorBottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We change all children's margins in MeasureOverride, since this is called right before
|
||||
// the layouting takes place. I was first skeptical to do this here, because I thought changing
|
||||
// the margin will trigger a LayoutUpdate, which in turn would lead to an endless recursion,
|
||||
// but apparantly WPF takes care of this.
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
UpdateChildMargins();
|
||||
return base.MeasureOverride(availableSize);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user