我已经尝试了一段时间,似乎无法在不使用网格的情况下复制此模型。我已经尝试制作一些简单的自定义面板和一个wrappanel,在n个像素或n个有效的项目之后创建一个新列;但是,我无法找到错开每一栏的方法。
这是我正在尝试做的事情的图像:
我制作的解决方案使用的网格错开了列,但我需要的是一个仅使用列的面板,并且像listview一样流畅,如果添加,移动或删除项目其他项目相应地移动(基于索引)。
答案 0 :(得分:2)
因为您希望Panel有点像“生活”列表,所以解决方案需要2个步骤。首先实现一个能够按照您想要的方式排列项目的面板。第二步添加一个处理列表更改的管理器。幸运的是,这一切都很简单。这个管理器已经存在,它的ItemsControl。只需将ObserableCollection输入到ItemsControl。
<ItemsControl Margin="10" ItemsSource="{Binding YoursItemsObserableCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<local:StaggeredPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<DataTemplate.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="18"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</DataTemplate.Resources>
<Grid>
<Ellipse Fill="Silver" Width="40" Height="40"/>
<StackPanel>
<TextBlock Margin="3,3,3,0" Text="{Binding Path=Name}"/>
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
class StaggeredPanel : Panel
{
protected override Size MeasureOverride (Size availableSize)
{
foreach (var childo in InternalChildren)
{
FrameworkElement child = childo as FrameworkElement;
if (child != null)
{
var childMaxSize = new Size (double.PositiveInfinity, availableSize.Height);
child.Measure (childMaxSize);
}
}
return availableSize;
}
protected override Size ArrangeOverride (Size finalSize)
{
double x = 0;
double y = 0;
bool shift = true;
double shiftOffset;
if (InternalChildren.Count > 0)
{
FrameworkElement offsetChild = InternalChildren[0] as FrameworkElement;
shiftOffset = offsetChild.DesiredSize.Height / 2;
for (int i = 0; i < InternalChildren.Count; i++)
{
FrameworkElement child = InternalChildren[i] as FrameworkElement;
if (child != null)
{
double finalY = y;
if (shift)
{
finalY += shiftOffset;
}
shift = !shift;
child.Arrange (new Rect (new Point (x, finalY), child.DesiredSize));
x += child.DesiredSize.Width;
double nextWidth = 0;
if (i + 1 < InternalChildren.Count)
{
FrameworkElement nextChild = InternalChildren[i + 1] as FrameworkElement;
nextWidth = child.DesiredSize.Width;
}
if (x + nextWidth > finalSize.Width)
{
shift = true;
x = 0;
y += child.DesiredSize.Height;
}
}
}
}
return finalSize; // Returns the final Arranged size
}
}