Binding ItemsControl
to an ObservableCollection<T>
places an extra {NewItemPlaceholder}
in the control at runtime. How can I remove it?
NB I have seen posts related to this problem but those are limited to DataGrid
where you can set CanUserAddRows
or IsReadOnly
properties to get rid of this item. ItemsControl
doesn't have any such property.
XAML
Here's my ItemsControl
( MyPoints
is ObservableCollection<T>
in the underlying ViewModel):
<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>
This displays an extra point at 0,0. Live Property Explorer shows that this point is bound to the {NewItemPlaceholder}
object.
MSDN writes the following:
When a
CollectionView
that implementsIEditableCollectionView
hasNewItemPlaceholderPosition
set toAtBeginning
orAtEnd
, theNewItemPlaceholder
is added to the collection. TheNewItemPlaceholder
always appears in the collection; it does not participate in grouping, sorting, or filtering.
Link: MSDN
Hopefully if you set the NewItemPlaceholderPosition
to something else, the placeholder will disappear from the collection.
Edit:
If your ObservableCollection<T>
is being binded to somewhere else as well (eg: to a DataGrid
, you have to set the CanUserAddRows
to false), you have to deal with that other item. It would add a new NewItemPlaceholder
to your collection.
Finally finally!
After spending a day, the solution turned out to be simple (although not ideal). ItemTemplateSelector
allows me to select a template based on the item type, so I can create a simple selector to get rid of the extra item:
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;
}
}
MyDataTemplate
and EmptyDataTemplate
should be defined in the Resources
section of your ItemsControl
. EmptyDataTemplate
doesn't need to have any content.
@KAI's guess (see accepted answer) was correct. My ObservableCollection<T>
was bound to a DataGrid
which was causing this problem. I'll still keep my answer here as it provides a solution for other related situations.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.