AnimatedStackPanel concurrency: insert/delete items faster than animation happens

Views for WPF Forum

Posted 6 months ago by Igor Bondarev
Version: 23.1.3
Platform: .NET 6.0
Environment: Windows 10 (64-bit)
Avatar

When items are quickly added or removed from AnimatedStackPanel, and there is "await" between adding and removing, UI elements of individual items stop being interactive.

AnimatedStackPanel is used as ItemsPanelTemplate of ItemsControl. ItemsControl's ItemsSource is bound to ObservableCollection, items of which are inserted and removed by one frequently. Source code for sample app and the video of how the problem reproduces are here:

https://drive.google.com/drive/folders/1FJWi0Lq0Xfs9pzdaFSfnNLiM-SFnIe1w?usp=sharing

In this test app single ObservableCollection is used for 2 ItemsControls, the only difference between which is that the first one uses AnimatedStackPanel, when the second one doesn't:

<ItemsControl Grid.Row="1" Grid.Column="0"
              ItemsSource="{Binding Path=Items}"
              ItemTemplate="{StaticResource ItemTemplate}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <views1:AnimatedStackPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

<ItemsControl Grid.Row="1" Grid.Column="1"
              ItemsSource="{Binding Path=Items}"
              ItemTemplate="{StaticResource ItemTemplate}" />

So, the first one misbehaves while the second one is always fine.

ItemTemplate is a textbox which has a trigger on MouseOver which makes background yellow - this is how we can keep track of whether the UI is "interactive" or not. "Replace" button removes one item from the collection and then creates the new one and inserts it to where the removed item was. "Set Random" button sets random value to the item of the collection, so we can see whether the UI is redrawn. "Quick Replace All" button performs "Replace" for each item in cycle.

Sometimes it reproduces after the first click on "Quick Replace All", sometimes - not. In the video I clicked several times quickly. It also can reproduce when clicking individual "Replace" buttons one by one manually, especially when in reverse order. The problem doesn't reproduce if there is no "await" between remove and insert, or if the delay between remove and insert is longer than duration of animation.

Initially found on .NET 7, but on .NET 6 it's the same.

Comments (2)

Posted 6 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Igor,

Thank you for the sample and video.  I am able to reproduce the problem scenarion with the sample you provided. 

I noticed that if you remove the await Task calls between the items being removed and added, then the problem doesn't seem to occur.  You hinted to this too in your opening sentence. 

I've tried a number of things here but have been unable to get it to stop occurring, other than removing the Task calls.  Is it possible for you to alter your viewmodel logic to do whatever async Task calls you need to do completely prior to changing the Items collection?  When I tried that scenario in your sample (putting in the async Task call only before the Items collection changes), it didn't seem to run into the issue.


Actipro Software Support

Posted 6 months ago by Igor Bondarev
Avatar

Hi,

I think it's possible although complicated, but currently I fixed the problem in our app by temporarily setting ItemsControl.ItemsPanel to a usual StackPanel while inserts/removes are happening. Creating another ObservableCollection in memory and setting the whole collection at the very end would also help.

This issue is not urgent, I posted this after I already found a workaround.

The latest build of this product (v24.1.2) was released 4 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.