DataTemplateSelector dont change when row in observable collection is deleted

BitSmithy 2,206 Reputation points
2020-09-29T21:07:15.403+00:00

I use DataTemplateSelector for changing apperance of the first row in a ListView.
So first row has one DataTemplate and next rows other DataTemplate.
To ListView is attached an ObservableCollection.
Now I delete first row (zero indexed row) from the collection, and second row becames first row.
I that moment DataTemplate of the row should change. But it doesnt change.
When I move row in ObservableCollection (using function ObservableColecction.Move(oldIndex, newIndex)) all works OK.

DataTemplateSelector

public class PeriodDataDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate FirstDataPeriod { get; set; }
    public DataTemplate OtherDataPeriod { get; set; }

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        DataTemplate _returnTemplate = new DataTemplate();
        var itemsControl = ItemsControl.ItemsControlFromItemContainer(container);
        _returnTemplate = (itemsControl.IndexFromContainer(container) == 0) ? FirstDataPeriod : OtherDataPeriod;
        return _returnTemplate;
    }
}

ItemTemplateSelector i ListView

                <ListView.ItemTemplateSelector>
                    <local:PeriodDataDataTemplateSelector FirstDataPeriod = "{StaticResource FirstDataPeriod}"
                            OtherDataPeriod ="{StaticResource OtherDataPeriod}"/>
                </ListView.ItemTemplateSelector>
Developer technologies Universal Windows Platform (UWP)
0 comments No comments
{count} votes

Accepted answer
  1. Yan Gu - MSFT 2,676 Reputation points
    2020-09-30T06:00:20.077+00:00

    Hello,

    Welcome to Microsoft Q&A.

    If you want the first row’s data template changes after you delete the first row from the collection, the SelectTemplateCore method in your PeriodDataDataTemplateSelector class needs to be called to apply the DataTemplate for the new first row.
    When you use ObservableCollection.Move(oldIndex, newIndex), it will call the SelectTemplateCore method automatically, while deleting row will not automatically call the SelectTemplateCore method automatically.

    You could actively call SelectTemplateCore method after deleting a row, like this:

    Contacts.MyContacts.RemoveAt(0);  
    listView.ItemTemplateSelector = MyDataTemplateSelector;  
    

    Or you could just use ObservableColecction.Move() function instead.


    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Daniele 1,996 Reputation points
    2020-09-30T06:48:29.18+00:00

    I think this is happening because when the second row becomes the first row, there is no event that tells to ListView that have to calculate again DataTemplate for this row.

    You can try this way: I suppose you have a ObservableCollection in your view model, for example an ObservableCollection<string>. Attach the following event handler to CollectionChanged:

    _observableCollection.CollectionChanged += async (sender, args) =>
    {
        if (args.Action == NotifyCollectionChangedAction.Remove && args.OldStartingIndex == 0)
        {
            var list = (ObservableCollection<string>) sender;
            if (list.Count > 0)
            {
                // It needs to replace first element scheduling on Dispatcher otherwise you 
                // get System.InvalidOperationException with message "Cannot change ObservableCollection during a CollectionChanged event."
                await CoreApplication.MainView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                {
                    list[0] = list[0];
                });
            }
        }
    };
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.