使用ItemsControl并将WrapPanel设置为ItemsPanel,我试图实现此图像中所示的内容:
XAML看起来像这样(经过修改使其更简单):
<ItemsControl ItemsSource="{Binding Animals}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Margin="5">
<Image Source="{Binding ImageUrl}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
基础ViewModel如下所示:
public class Zoo
{
public ObservableCollection<Animal> Animals { get; set; } = new ObservableCollection<Animal>();
public ICommand AddAnimal() => new DelegateCommand(() => Animals.Add(new Animal()));
}
public class Animal
{
public string ImageUrl { get; set; }
}
ItemsControl的DataContext设置为Zoo的一个实例,并填充了4个动物。
问题: 如何添加一个看起来像其他元素的“静态”子元素,是WrapPanel的子元素,并与其他子元素包装?具体来说,我希望最后一个元素是一个添加按钮(上图中显示的绿色加号),它绑定到动物园的AddAnimal Command属性。
要求:
我想过:
其他信息:我使用:WPF,PRISM,C#6.0,.NET 4.0 Client Profile和MVVM模式。
对这个问题的任何想法?
解决方案:
@ kyriacos_k的答案为我解决了两个小修改:
最后这对我有用:
<ItemsControl>
<ItemsControl.Resources>
<CollectionViewSource x:Key="AnimalCollection" Source="{Binding Animals}"/>
<behaviors:BindingProxy x:Key="Proxy" DataContext="{Binding}"/>
<DataTemplate DataType="{x:Type local:Animal}">
<Border Margin="5">
<Image Source="{Binding ImageUrl}" />
</Border>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding Source={StaticResource AnimalCollection}}"/>
<Border Margin="5">
<Button Command="{Binding DataContext.AddAnimal, Source={StaticResource Proxy}}">
<Image Source="SourceToPlusSign"/>
</Button>
</Border>
</CompositeCollection>
</ItemsControl.ItemsSource>
</ItemsControl>
BindingProxy的代码在这里(直接从Binding Visibility for DataGridColumn in WPF抓取):
public class BindingProxy : Freezable
{
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
public object DataContext
{
get { return GetValue(DataContextProperty); }
set { SetValue(DataContextProperty, value); }
}
public static readonly DependencyProperty DataContextProperty =
DependencyProperty.Register("DataContext", typeof(object),
typeof(BindingProxy));
}
答案 0 :(得分:8)
您可以使用CompositeCollection
<ItemsControl>
<ItemsControl.Resources>
<CollectionViewSource x:Key="AnimalCollection" Source="{Binding Animals}"/>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Margin="5">
<Image Source="{Binding ImageUrl}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding Source={StaticResource AnimalCollection}}"/>
<Border Margin="5">
<Button Command="{Binding AddAnimal}">
<Image Source="YourAddButtonSource"/>
</Button>
</Border>
</CompositeCollection>
</ItemsControl.ItemsSource>
</ItemsControl>
当然,如果您希望首先显示添加按钮,只需将Border
(包含Button
)的顺序与CollectionContainer
中的CompositeCollection
进行交换标签
答案 1 :(得分:0)
看看CompositeCollection。它允许您向ItemsSource
绑定添加其他项目:
<Window.Resources>
<CollectionViewSource x:Key="AnimalViewSource" Source="{Binding Animals}"/>
</Window.Resources>
<ItemsControl>
<ItemsControl.ItemsSource>
<CompositeCollection>
<local:Animal ImageUrl="somepath/plussign.png" />
<CollectionContainer Collection="{Binding Source={StaticResource AnimalViewSource}}"/>
</CompositeCollection>
</ItemsControl.ItemsSource>
... ItemsPanel, ItemsTemplate, etc. follow here ...
</ItemsControl>