Страницы

Поиск по вопросам

понедельник, 30 декабря 2019 г.

Квадратные ячейки Grid

#c_sharp #wpf


Как сделать чтобы ячейки Grid были всегда квадратные?
    


Ответы

Ответ 1



Немного другое идеологически решение — декоратор, размер которого не ограничен, но который заставляет свой дочерний элемент сохранять нужную пропорцию сторон. Код украден отсюда. 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; } } Имея это, можно писать что-то такое И получать результат:

Ответ 2



Width="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight}"

Комментариев нет:

Отправить комментарий