Ответ 1
Если вы установите Orientation
на Vertical
, вы также должны установить высоту рендеринга. Например, WrapPanel
, Height="150"
.
Мне нужно перечислить элементы (все одинакового размера) по вертикали (с помощью ScrollViewer). Я хочу, чтобы элементы распространялись через столбцы x, если контейнер достаточно велик, чтобы отображать x столбцов
Я сначала попробовал, чтобы:
<ScrollViewer>
<toolkit:WrapPanel Orientation="Horizontal" ItemHeight="30" ItemWidth="100">
<Button Content="1" />
<Button Content="2" />
<Button Content="3" />
<Button Content="4" />
<Button Content="5" />
</toolkit:WrapPanel>
</ScrollViewer>
Результат. WrapPanel работает так, как я хочу, но мои объекты упорядочены с "слева направо" (не вертикально
Затем я попытался установить ориентацию WrapPanel на " Вертикальный":
Результат. Мои элементы упорядочены по вертикали, но не распределены по нескольким столбцам.
Вот как я хочу, чтобы объекты отображались:
Мне бы очень хотелось избежать необходимости писать код, контролирующий размер элемента управления для создания/удаления столбцов в зависимости от его размера.
Если вы установите Orientation
на Vertical
, вы также должны установить высоту рендеринга. Например, WrapPanel
, Height="150"
.
Наконец-то получил что-то, что работает, но ему нужен код. Я согласен со всеми вами, когда вы говорите, что нам нужно изменить размер WrapPanel, чтобы это сработало. Вот мое решение:
<ScrollViewer x:Name="scroll1" SizeChanged="ScrollViewer_SizeChanged" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<toolkit:WrapPanel x:Name="wp1" Orientation="Vertical" VerticalAlignment="Top" HorizontalAlignment="Left" ItemHeight="30" ItemWidth="250" >
<Button Content="1" />
<Button Content="2" />
<Button Content="3" />
<Button Content="4" />
<Button Content="5" />
<Button Content="6" />
<Button Content="7" />
<Button Content="8" />
</toolkit:WrapPanel>
</ScrollViewer>
Вот код CodeBehind:
private void ScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
{
// Stupid magical number because ViewPortHeight is sometimes not accurate
Double MAGICALNUMBER = 2;
// Ensure ViewPortSize is not 0
if (scroll1.ViewportWidth <= MAGICALNUMBER || scroll1.ViewportHeight <= MAGICALNUMBER)
return;
Size contentSize = new Size(scroll1.ViewportWidth - MAGICALNUMBER, scroll1.ViewportHeight - MAGICALNUMBER);
Size itemSize = new Size(wp1.ItemWidth, wp1.ItemHeight);
Size newSize = CalculateSizeBasedOnContent(contentSize, wp1.Children.Count, itemSize);
wp1.Width = newSize.Width;
wp1.Height = newSize.Height;
}
private Size CalculateSizeBasedOnContent(Size containerSize, int itemsCount, Size itemSize)
{
int iPossibleColumns = (int)Math.Floor(containerSize.Width / itemSize.Width);
int iPossibleRows = (int)Math.Floor(containerSize.Height / itemSize.Height);
// If all items can fit in first column without scrolling (or if container is narrow than the itemWidth)
if (itemsCount <= iPossibleRows || containerSize.Width < itemSize.Width)
return new Size(itemSize.Width, (itemsCount * itemSize.Height));
// If all items can fit in columns without scrollbar
if (iPossibleColumns * iPossibleRows > itemsCount)
{
int columnsNeededForDisplay = (int)Math.Ceiling((itemsCount/(Double) iPossibleRows));
return new Size(columnsNeededForDisplay * itemSize.Width, containerSize.Height);
}
// Here scrolling is needed even after spreading in columns
int itemsPerColumn = (int)Math.Ceiling(wp1.Children.Count / (Double)iPossibleColumns);
return new Size(containerSize.Width, itemsPerColumn * itemSize.Height);
}
Такое поведение невозможно при использовании WrapPanel
без определения его Height
Один из вариантов, который вы можете использовать, - это Grid
, где в OnLoaded
и OnSizeChanged
он вычисляет, сколько столбцов будет соответствовать, затем задает определения Row/Column для Grid и Grid.Row
/Grid.Column
каждого объекта в коде. Это не очень, но это должно быть довольно просто собрать и работать.
Другой вариант - создать собственную пользовательскую панель, которая упорядочивает элементы, как вы хотите. Возможно, вы даже сможете найти что-то доступное в Интернете, которое уже делает это
Единственный способ сделать это с помощью WrapPanel
- это явно установить Height
.
Похоже, вы хотите, чтобы элементы были равномерно распределены по столбцам с левым столбцом, имеющим не более одного элемента, чем столбец справа. Если это то, что вы ищете, вам нужно создать свою собственную панель. Посмотрите этот, чтобы узнать, как начать работу. Вам понадобятся свойства зависимости ItemWidth и ItemHeight и подсчитайте, сколько столбцов вы можете использовать с помощью ItemWidth и доступной ширины.