Как сделать чтобы ячейки Grid были всегда квадратные?
Ответ
Немного другое идеологически решение — декоратор, размер которого не ограничен, но который заставляет свой дочерний элемент сохранять нужную пропорцию сторон.
Код украден отсюда
public class AspectRatioDecorator : Decorator
{
#region dp double AspectRatio with validator ValidateAspectRatio
public static readonly DependencyProperty AspectRatioProperty =
DependencyProperty.Register(
"AspectRatio",
typeof(double),
typeof(AspectRatioDecorator),
new FrameworkPropertyMetadata(
1.0,
FrameworkPropertyMetadataOptions.AffectsMeasure),
ValidateAspectRatio);
public double AspectRatio
{
get { return (double)GetValue(AspectRatioProperty); }
set { SetValue(AspectRatioProperty, value); }
}
static bool ValidateAspectRatio(object value)
{
if (!(value is double))
return false;
var aspectRatio = (double)value;
return aspectRatio > 0 &&
!double.IsInfinity(aspectRatio) &&
!double.IsNaN(aspectRatio);
}
#endregion
#region dp HorizontalAlignment HorizontalChildAlignment
public HorizontalAlignment HorizontalChildAlignment
{
get { return (HorizontalAlignment)GetValue(HorizontalChildAlignmentProperty); }
set { SetValue(HorizontalChildAlignmentProperty, value); }
}
public static readonly DependencyProperty HorizontalChildAlignmentProperty =
DependencyProperty.Register(
"HorizontalChildAlignment",
typeof(HorizontalAlignment),
typeof(AspectRatioDecorator),
new FrameworkPropertyMetadata(
HorizontalAlignment.Center,
FrameworkPropertyMetadataOptions.AffectsArrange),
ValidateHorizontalChildAlignment);
static bool ValidateHorizontalChildAlignment(object value)
{
if (!(value is HorizontalAlignment))
return false;
var horizontalAlignment = (HorizontalAlignment)value;
return horizontalAlignment != HorizontalAlignment.Stretch;
}
#endregion
#region dp VerticalAlignment VerticalChildAlignment
public VerticalAlignment VerticalChildAlignment
{
get { return (VerticalAlignment)GetValue(VerticalChildAlignmentProperty); }
set { SetValue(VerticalChildAlignmentProperty, value); }
}
public static readonly DependencyProperty VerticalChildAlignmentProperty =
DependencyProperty.Register(
"VerticalChildAlignment",
typeof(VerticalAlignment),
typeof(AspectRatioDecorator),
new FrameworkPropertyMetadata(
VerticalAlignment.Top,
FrameworkPropertyMetadataOptions.AffectsArrange),
ValidateVerticalChildAlignment);
static bool ValidateVerticalChildAlignment(object value)
{
if (!(value is VerticalAlignment))
return false;
var verticalAlignment = (VerticalAlignment)value;
return verticalAlignment != VerticalAlignment.Stretch;
}
#endregion
protected override Size MeasureOverride(Size constraint)
{
if (Child == null) // we have no child, so we need no space
return new Size(0, 0);
constraint = SizeToRatio(constraint, false);
Child.Measure(constraint);
if (double.IsInfinity(constraint.Width) || double.IsInfinity(constraint.Height))
return SizeToRatio(Child.DesiredSize, true);
return constraint;
}
public Size SizeToRatio(Size size, bool expand)
{
double ratio = AspectRatio;
double height = size.Width / ratio;
double width = size.Height * ratio;
if (expand)
{
width = Math.Max(width, size.Width);
height = Math.Max(height, size.Height);
}
else
{
width = Math.Min(width, size.Width);
height = Math.Min(height, size.Height);
}
return new Size(width, height);
}
protected override Size ArrangeOverride(Size arrangeSize)
{
if (Child == null)
return arrangeSize;
var constrainedSize = arrangeSize;
var fwChild = Child as FrameworkElement;
if (fwChild != null)
{
constrainedSize.Height = Math.Min(constrainedSize.Height, fwChild.MaxHeight);
constrainedSize.Width = Math.Min(constrainedSize.Width, fwChild.MaxWidth);
}
var newSize = SizeToRatio(constrainedSize, false);
double widthDelta = arrangeSize.Width - newSize.Width;
double heightDelta = arrangeSize.Height - newSize.Height;
double top = 0;
double left = 0;
if (!double.IsNaN(widthDelta) && !double.IsInfinity(widthDelta))
switch (HorizontalChildAlignment)
{
case HorizontalAlignment.Left:
break;
case HorizontalAlignment.Center:
left = widthDelta / 2;
break;
case HorizontalAlignment.Right:
left = widthDelta;
break;
};
if (!double.IsNaN(heightDelta) && !double.IsInfinity(heightDelta))
switch (VerticalChildAlignment)
{
case VerticalAlignment.Top:
break;
case VerticalAlignment.Center:
top = heightDelta / 2;
break;
case VerticalAlignment.Bottom:
top = heightDelta;
break;
};
var finalRect = new Rect(new Point(left, top), newSize);
Child.Arrange(finalRect);
return arrangeSize;
}
}
Имея это, можно писать что-то такое
И получать результат:
Комментариев нет:
Отправить комментарий