你可以有一个
ICollectionView
或
ObservableCollection<T>
属性并绑定
ItemsSource
AN的性质
ItemsControl
对这个财产。然后将显示集合中的所有项(视图)。但是,它通常将它们显示在
StackPanel
因为这是
项目控制
. 据我所知,您希望项目放在屏幕上的任何位置。这可以通过使用
Canvas
作为
项目控制
的
ItemsPanel
,然后绑定
Canvas.Left
和
Canvas.Top
属性到视图模型中的属性。当然,每个项目都需要
Left
和
Top
当时的财产(也可能是
Width
和
Height
财产)。
public class ItemViewModel
{
public double Left { get; set; }
public double Top { get; set; }
public double Width { get; set; }
public double Height { get; set; }
// whatever you need...
}
public class CollectionViewModel
{
public ObservableCollection<ItemViewModel> Collection { get; }
// some code which fills the Collection with items
}
你的XAML:
<ItemsControl ItemsSource="{Binding Collection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:ItemViewModel}">
<Rectangle Width="{Binding Width}" Height="{Binding Height}"
Canvas.Left="{Binding Left}" Canvas.Top="{Binding Top}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
最后一步,您可能需要
左
和
顶部
属性相对于
帆布
使项目保持在相对位置,如果
帆布
变化。这是更多的工作:
<DataTemplate DataType="{x:Type local:ItemViewModel}">
<Rectangle Width="{Binding Width}" Height="{Binding Height}">
<!-- Make the left position of the item depend on the ActualWidth of the Canvas,
the relative Left position (between 0 and 1) from the ItemViewModel, and the ActualWidth
of the item itself. This is needed because the Canvas.Left property defines the
position of the left side, not the center. Therefore, we calculate the position of
the center this way:
(Canvas.ActualWidth * ItemViewModel.Left) - (Item.ActualWidth / 2)
-->
<Canvas.Left>
<MultiBinding>
<MultiBinding.Converter>
<converters:ExpressionConverter Expression="{}({0} * {1}) - ({2} / 2)"/>
</MultiBinding.Converter>
<Binding Path="ActualWidth" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Canvas}}"/>
<Binding Path="Left"/>
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}"/>
</MultiBinding>
</Canvas.Left>
<!-- the top position of the items is determined the same way as the left position
which is described above -->
<Canvas.Top>
<MultiBinding>
<MultiBinding.Converter>
<converters:ExpressionConverter Expression="{}({0} * {1}) - ({2} / 2)"/>
</MultiBinding.Converter>
<Binding Path="ActualHeight" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Canvas}}"/>
<Binding Path="Top"/>
<Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}"/>
</MultiBinding>
</Canvas.Top>
</Rectangle>
</DataTemplate>
代码的描述已在XAML注释中。但是,我应该注意,我已经使用了
ExpressionConverter
从
Kent Boogart's Converter collection
. 我从我的一个应用程序中复制并粘贴了上面的代码,因此其中可能存在一些不一致之处,因为可以根据您的场景快速调整属性。不过,我认为,这一原则应该是明确的。祝你好运!