将 Itemscontrol 绑定到 ObservableCollection:额外生成的项目

Binding Itemscontrol to ObservableCollection: extra generated item

ItemsControl 绑定到 ObservableCollection<T> 会在运行时在控件中放置一个额外的 {NewItemPlaceholder}。我怎样才能删除它?

N.B. 我见过 posts related to this problem 但这些仅限于 DataGrid ,您可以在其中设置 CanUserAddRowsIsReadOnly 属性去掉这个项目。 ItemsControl 没有任何这样的 属性。

XAML

这是我的 ItemsControlMyPoints 在底层 ViewModel 中是 ObservableCollection<T>):

<ItemsControl ItemsSource="{Binding MyPoints}">
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <Canvas />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>

  <ItemsControl.ItemContainerStyle>
    <Style TargetType="FrameworkElement">
      <Setter Property="Canvas.Left" Value="{Binding Path=X}" />
      <Setter Property="Canvas.Top" Value="{Binding Path=Y}" />
    </Style>
  </ItemsControl.ItemContainerStyle>

  <ItemsControl.ItemTemplate>
    <DataTemplate DataType="{x:Type vm:PointVM}">
      <Ellipse Width="10" Height="10" Fill="#88FF2222" />
    </DataTemplate>       
  </ItemsControl.ItemTemplate>
</ItemsControl>

这会在 0,0 处显示一个额外的点。 Live 属性 Explorer 显示此点已绑定到 {NewItemPlaceholder} 对象。

MSDN 写道:

When a CollectionView that implements IEditableCollectionView has NewItemPlaceholderPosition set to AtBeginning or AtEnd, the NewItemPlaceholder is added to the collection. The NewItemPlaceholder always appears in the collection; it does not participate in grouping, sorting, or filtering.

Link: MSDN

希望如果您将 NewItemPlaceholderPosition 设置为其他内容,占位符将从 collection 中消失。

编辑:

如果你的 ObservableCollection<T> 也被绑定到其他地方(例如:绑定到 DataGrid,你必须将 CanUserAddRows 设置为 false),你必须处理那其他项目。它会添加一个新的 NewItemPlaceholder 到你的 collection.

终于终于!

花了一天时间,解决方案很简单(虽然不理想)。 ItemTemplateSelector 允许我 select 基于项目类型的模板,因此我可以创建一个简单的 select 或者删除额外的项目:

public class PointItemTemplateSelector : DataTemplateSelector
{
  public override DataTemplate SelectTemplate(object item, DependencyObject container)
  {
    if (item == CollectionView.NewItemPlaceholder)
      return (container as FrameworkElement).TryFindResource("EmptyDataTemplate") as DataTemplate;
    else
      return (container as FrameworkElement).TryFindResource("MyDataTemplate") as DataTemplate;
  }
}

MyDataTemplateEmptyDataTemplate 应该在 ItemsControlResources 部分定义。 EmptyDataTemplate不需要有任何内容。

编辑

@KAI 的猜测(参见接受的答案)是正确的。我的 ObservableCollection<T> 绑定到导致此问题的 DataGrid。我仍然会在这里保留我的答案,因为它为其他相关情况提供了解决方案。