#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: Вы проверяли, настроены ли горизонтальное выравнивание / вертикальное выравнивание и ширина / высота, как я упоминал? Если вы наблюдаете панель сетки, она изменяет свое содержимое при изменении размера окна.