Если записи имеют (или могут быть) фиксированную ширину, это легко: просто замените вашу ListBox.ItemsPanel на WrapPanel и установите ширину ListBox, которая будет чуть более чем в 3 раза больше ширины элементов:
<DataTemplate DataType="{x:Type my:CustomItem}">
<Border Width="100" ...>
...
</Border>
</DataTemplate>
...
<ListBox ... Width="320">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
...
</ListBox>
Если вам нужно разделить доступную ширину на три, и вы знаете, что все ваши элементы имеют одинаковую высоту (или если вы в порядке, все строки имеют максимальную высоту для любого элемента), оченьпростое решение с использованием UniformGrid без указания высоты:
<ListBox ... >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Width="3" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
...
</ListBox>
Если вы хотите разделить доступную ширину на 3, чтобы получить ширину элемента, но сложить элементы как можно ближе по вертикали, это возможно, но сложно в чистом видеXAML.(Я бы не рекомендовал делать это в чистом XAML, но если вы хотите сделать это таким образом, вы можете создать скрытую сетку с тремя столбцами звездного размера и столбцом фиксированной ширины, а затем использовать привязку к ActualWidth первогостолбец скрытой сетки.)
Более простым способом является создание простой настраиваемой панели, которая действует как UniformGrid по горизонтали, а StackPanel по вертикали.Это очень простой подкласс Panel:
- MeasureOverride вычисляет желаемую ширину как 3 * максимальная ширина любого дочернего элемента
- MeasureOverride вычисляет желаемую высоту как сумму (max (высота каждой группы из 3))
- ArrangeOverride размещает дочерних элементов 3 в строке, каждый DesiredWidth / 3 справа от предыдущего, а следующий ряд - max (высота) вниз от текущей строки
Очевидно, что если вы разрабатываете пользовательскую панель, вы не станете жестко кодировать «3» - вы сделаете ее свойством, возможно, DependencyProperty, чтобы вы могли легко изменить его и, при необходимости, повторно использовать панель в другом месте.