Масштабирование пользовательской панели WPF по размеру окна

#c# #wpf

#c# #wpf

Вопрос:

У меня есть пользовательская панель WPF, которая упорядочивает свои дочерние элементы по спирали в соответствии с моими требованиями. Проблема, с которой я сталкиваюсь, связана с масштабированием элементов при изменении размера окна — на данный момент оно не масштабируется. Кто-нибудь может предложить решение? Спасибо — Бен

Пользовательская панель

 public class TagPanel : Panel
{
    protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize)
    {
        Size resultSize = new Size(0, 0);

        foreach (UIElement child in Children)
        {
            child.Measure(availableSize);

            resultSize.Width = Math.Max(resultSize.Width, child.DesiredSize.Width);
            resultSize.Height = Math.Max(resultSize.Height, child.DesiredSize.Height);

        }

        resultSize.Width = double.IsPositiveInfinity(availableSize.Width) ?
            resultSize.Width : availableSize.Width;

        resultSize.Height = double.IsPositiveInfinity(availableSize.Height) ?
            resultSize.Height : availableSize.Height;

        return resultSize;

    }

    protected class InnerPos
    {
        public UIElement Element { get; set; }
        public Size Size { get; set; }
    }

    private Point GetSpiralPosition(double theta, Size windowSize)
    {
        double a = 5.0;
        double n = 1.0;

        double r = a * (Math.Pow(theta, 1.0 / n));

        double x = r * Math.Cos(theta);
        double y = r * Math.Sin(theta);

        x  = windowSize.Width / 2.0;
        y  = windowSize.Height / 2.0;

        return new Point(x,y);

    }

    private Rect CreateRectangleCenteredAtPoint(Point pt, double width, double height)
    {
        return new Rect(new Point(pt.X - (width / 2.0), pt.Y - (height / 2.0)),
            new Size(width, height));

    }

    protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)
    {
        //double startPos = 0.0;

        List<InnerPos> positions = new List<InnerPos>();

        foreach (UIElement ch in Children)
        {
            // If this is the first time
            // we've seen this child, add our transforms

            //if (ch.RenderTransform as TransformGroup == null)
            //{
            //    ch.RenderTransformOrigin = new Point(0, 0.5);
            //    TransformGroup group = new TransformGroup();
            //    ch.RenderTransform = group;
            //    group.Children.Add(new ScaleTransform());
            //    group.Children.Add(new TranslateTransform());

            //}

            positions.Add(new InnerPos()
            {
                Element = ch,
                Size = ch.DesiredSize

            });
        }

        //double currentTopMax
        List<Rect> alreadyUsedPositions = new List<Rect>();

        foreach (InnerPos child in positions.OrderByDescending(i => i.Size.Width))
        {

            for (double theta = 0.0; theta < 100.0; theta  = 0.1)
            {
                Point spiralPos = GetSpiralPosition(theta, finalSize);
                Rect centeredRect = CreateRectangleCenteredAtPoint(spiralPos,
                    child.Element.DesiredSize.Width,
                    child.Element.DesiredSize.Height);

                bool posIsOk = true;
                foreach (Rect existing in alreadyUsedPositions)
                {
                    bool positionClashes = existing.IntersectsWith(centeredRect);
                    if (positionClashes == true)
                    {
                        posIsOk = false;
                        break;
                    }
                }

                if (posIsOk)
                {
                    alreadyUsedPositions.Add(centeredRect);

                    child.Element.Arrange(centeredRect);
                    break;
                }


            }

        }

        return finalSize;

    }
}
  

Ответ №1:

Для HorizontalAlignment и VerticalAlignment Panel установлено значение Stretch , а для Width / Height — значение Auto ( double.NaN )?

Похоже, что вы передаете finalSize into GetSpiralPosition() , то есть функцию, в которой происходит вся настоящая работа. Не видя кода этой функции, трудно сказать больше, но я предполагаю, что вы правильно вычисляете finalSize .

Вы выполнили отладку, чтобы узнать, Arrange вызывается ли с обновленным размером при изменении размера окна? Это можно протестировать двумя способами: во-первых, поместить точку трассировки вместо точки останова. Дамп finalSize в окно вывода и посмотрите, изменится ли оно при изменении размера окна. Во-вторых, добавьте обработчик в window для SizeChanged . Поместите точку останова в обработчик. Когда будет достигнута точка останова, установите точку останова в методе упорядочивания пользовательской панели и затем запустите.

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

1. Привет, Джош, спасибо за твой ответ — пожалуйста, ознакомьтесь с обновленным кодом, чтобы получить более четкое представление. Спасибо

2. Проблема в том, что при изменении размера окна arrange не вызывается с новым размером, можете ли вы помочь с этим?

3. @Ben: Вы проверяли, настроены ли горизонтальное выравнивание / вертикальное выравнивание и ширина / высота, как я упоминал? Если вы наблюдаете панель сетки, она изменяет свое содержимое при изменении размера окна.