M
M
Michael2018-07-23 08:40:37
WPF
Michael, 2018-07-23 08:40:37

How to add a button in a ListBox to the beginning or end of the list?

It is necessary to make it so that in the edit mode at the beginning or end of the list there is a button for adding a new entry.
Something like this f1fFy.png
at the moment there is such a code

<ListBox ItemsSource="{Binding Items}">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid/> 
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
        </ListBox>

An attempt to add a button programmatically (via Items.Add(button...)) on the fly naturally ends with an error - Operation is not valid while ItemsSource is in use
How to be?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
R
Roman, 2018-07-23
@pig_master

When a collection is bided to an ItemsControl, a CollectionView is created (for IEnumerable, for IList - ListCollectionView), which can additionally sort or filter the collection. The items visible on the screen are taken from this CollectionView, not from the original collection.
The ListCollectionView has a NewItemPlaceholderPosition property that can be used to add a fake item to the beginning or end.

// CollectionView можно получить двумя способами:
// 1. Просто получить дефолтный вариант для коллекции
var collectionView = (ListCollectionView)CollectionViewSource.GetDefaultView(Items);
// 2. Создать свой, тогда именно этот созданный collectionView надо передавать для биндинга в ItemsSource.
var collectionView = new ListCollectionView(Models);

// После, можно добавить фейковый элемент
collectionView.NewItemPlaceholderPosition = NewItemPlaceholderPosition.AtBeginning;

After that, the CollectionView.NewItemPlaceholder element will appear in the ListBox, which can be separately styled using the DataTemplateSelector.
DataTemplateSelector
public sealed class NewItemTemplateSelector : DataTemplateSelector
{
   public DataTemplate ItemTemplate { get; set; }
   public DataTemplate NewItemPlaceholderTemplate { get; set; }

   public override DataTemplate SelectTemplate(object item, DependencyObject container)
   {
      if (item == CollectionView.NewItemPlaceholder)
         return NewItemPlaceholderTemplate;

      return ItemTemplate;
   }
}

<ListBox.ItemTemplateSelector>
    <t:NewItemTemplateSelector>
        <t:NewItemTemplateSelector.ItemTemplate>
            <DataTemplate>
                <!-- Шаблон обычного элемента -->
            </DataTemplate>
        </t:NewItemTemplateSelector.ItemTemplate>
        <t:NewItemTemplateSelector.NewItemPlaceholderTemplate>
            <DataTemplate>
                <!-- Шаблон CollectionView.NewItemPlaceholder -->
                <Button Content="+" />
            </DataTemplate>
        </t:NewItemTemplateSelector.NewItemPlaceholderTemplate>
    </t:NewItemTemplateSelector>
</ListBox.ItemTemplateSelector>

V
Vyacheslav Zolotov, 2018-07-23
@SZolotov

Use DataTemplateSelector. Well, read about binding collections to controls and other related things.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question