Как мы можем установить Wrap-point для WrapPanel?
У меня есть ItemsControl, и я хочу, чтобы данные вводились в два столбца. Когда пользователь изменяет размер до ширины, меньшей второго столбца, элементы второго столбца должны переноситься в первый столбец. Что-то вроде UniformGrid, но с упаковкой.
Мне удалось использовать WrapPanel для этого. Но я вынужден манипулировать и жестко кодировать ItemWidth и MaxWidth WrapPanel, чтобы добиться двух столбцов и обтекания. Это не очень хорошая практика.
Можно ли в любом случае установить максимальное количество столбцов или другими словами, чтобы мы могли решить, в какой момент WrapPanel должен начать перенос?
Некоторый просмотр в Интернете показал, что WrapGrid в Windows 8 Metro обладает этим свойством. У кого-нибудь есть такая реализация в WPF?
1 ответ
На codeproject.com есть статья UniformWrapPanel, которую я изменил, чтобы элементы на панели переноса имели одинаковую ширину и соответствовали ширине окна. Вы должны легко иметь возможность изменить этот код, чтобы иметь максимальное количество столбцов. Попробуйте изменить код рядом
var itemsPerRow = (int) (totalWidth/ItemWidth);
чтобы указать максимальное количество столбцов.
Вот код:
public enum ItemSize
{
None,
Uniform,
UniformStretchToFit
}
public class UniformWrapPanel : WrapPanel
{
public static readonly DependencyProperty ItemSizeProperty =
DependencyProperty.Register(
"ItemSize",
typeof (ItemSize),
typeof (UniformWrapPanel),
new FrameworkPropertyMetadata(
default(ItemSize),
FrameworkPropertyMetadataOptions.AffectsMeasure,
ItemSizeChanged));
private static void ItemSizeChanged(
DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var uniformWrapPanel = sender as UniformWrapPanel;
if (uniformWrapPanel != null)
{
if (uniformWrapPanel.Orientation == Orientation.Horizontal)
{
uniformWrapPanel.ItemWidth = double.NaN;
}
else
{
uniformWrapPanel.ItemHeight = double.NaN;
}
}
}
public ItemSize ItemSize
{
get { return (ItemSize) GetValue(ItemSizeProperty); }
set { SetValue(ItemSizeProperty, value); }
}
protected override Size MeasureOverride(Size availableSize)
{
var mode = ItemSize;
if (Children.Count > 0 && mode != ItemSize.None)
{
bool stretchToFit = mode == ItemSize.UniformStretchToFit;
if (Orientation == Orientation.Horizontal)
{
double totalWidth = availableSize.Width;
ItemWidth = 0.0;
foreach (UIElement el in Children)
{
el.Measure(availableSize);
Size next = el.DesiredSize;
if (!(Double.IsInfinity(next.Width) || Double.IsNaN(next.Width)))
{
ItemWidth = Math.Max(next.Width, ItemWidth);
}
}
if (stretchToFit)
{
if (!double.IsNaN(ItemWidth) && !double.IsInfinity(ItemWidth) && ItemWidth > 0)
{
var itemsPerRow = (int) (totalWidth/ItemWidth);
if (itemsPerRow > 0)
{
ItemWidth = totalWidth/itemsPerRow;
}
}
}
}
else
{
double totalHeight = availableSize.Height;
ItemHeight = 0.0;
foreach (UIElement el in Children)
{
el.Measure(availableSize);
Size next = el.DesiredSize;
if (!(Double.IsInfinity(next.Height) || Double.IsNaN(next.Height)))
{
ItemHeight = Math.Max(next.Height, ItemHeight);
}
}
if (stretchToFit)
{
if (!double.IsNaN(ItemHeight) && !double.IsInfinity(ItemHeight) && ItemHeight > 0)
{
var itemsPerColumn = (int) (totalHeight/ItemHeight);
if (itemsPerColumn > 0)
{
ItemHeight = totalHeight/itemsPerColumn;
}
}
}
}
}
return base.MeasureOverride(availableSize);
}
}