c# – 使用WrapPanel作为ItemsPanel的ItemsControl – 组合“静
使用带有WrapPanel设置为ItemsPanel的ItemsControl,我试图实现此图像中说明的内容:
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个Animals. 问题: 要求: > add-button-element必须与WrapPanel的其他子项一起包装. 我考虑过: >使用将Animals集合复制到新集合的转换器,向副本添加一个虚拟Animal,并将其返回到ItemsControl的ItemsSource绑定.然后我可以将最后一个元素设置为添加按钮.但是,这不是一个选项,因为一些拖放逻辑需要能够通过ItemsControl的ItemsSource属性处理原始的ObservableCollection. 附加信息:我使用:WPF,PRISM,C#6.0,.NET 4.0 Client Profile和MVVM模式. 有关这个问题的任何想法? 解: @ kyriacos_k的答案为我解决了两个小修改: >如果DataTemplate是通过ItemsControl.ItemTemplate属性设置的,那么它不起作用,即Add-button会拾取DataTemplate并显示错误.我想这是设计的,因为MSDN声明:“ItemsControl使用CompositeCollection中的数据根据??其ItemTemplate生成其内容”,来源:https://msdn.microsoft.com/en-us/library/system.windows.data.compositecollection%28v=vs.110%29.aspx) 最后这对我有用: <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)); } 解决方法
您可以使用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)的顺序与CompositeCollection标记中的CollectionContainer进行交换. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |