AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
25.34k stars 2.2k forks source link

When binding a Object that implements INotifyCollectionChanged to a ItemsControl, update the object doesn't trigger view updating #15607

Closed cdytoby closed 4 months ago

cdytoby commented 4 months ago

Describe the bug

To Reproduce

DumbRenamer.zip

This is my project (just started not long ago, to experiment things)

Just build and run the project: DumbRenamer.AvaloniaApp.Desktop

In file MainViewModel.cs, line 64, in the method FileInputViewOnCollectionChanged(), you can put a break point there, and this break point gets triggered.

Expected behavior

The ItemsControl displays the items correctly

Avalonia version

11.0.10

OS

Windows

Additional context

I need a better ObservableCollection, so I found a third party one, they have their own solutions and I'd like to use it. https://github.com/Cysharp/ObservableCollections

To my understanding of MVVM, as long as INotifyCollectionChanged is correctly fired, view should be updated. (experience from WPF)

(I could use Avalonia ones but I don't want avalonia package involved when design view model. And the Avalonia.Collection namespace is in the Avalonia main package, it's not a independent package.)

stevemonaco commented 4 months ago

INCC needs to be on the UI thread. Using their ObservableList<T> works fine. It's only an issue with the INotifyCollectionChangedSynchronizedView<T>. Their WPF sample shows using BindingOperations.EnableCollectionSynchronization, so not being on the UI thread seems to be a possible scenario. I would have expected an exception or log message on Verbose, but I don't seem to get either.

cdytoby commented 4 months ago

I saw it, but I don't need to synchronize across thread (at least not right now), so I thought this is optional. ObservableList<T> don't have INCC, so INotifyCollectionChangedSynchronizedView<T> is the only option here if I want to keep using this.

timunie commented 4 months ago

Can you please file a minimum sample? I'll not explore a random file renamer as that could be harmful to my machine.

cdytoby commented 4 months ago

Hi, this name "DumbRenamer" is a project I just started, despite the solution name, there is not much code, and not much going on, that's why I upload it, and it's without any dll or built binary.

But I understand your concern. Here are the some sample code files in a zip (.cs file and .axaml files are not directly allowed somehow)

Code.zip

PS: CommunityToolkit.Mvvm package and ObservableCollections package from "https://github.com/Cysharp/ObservableCollections" are required.

timunie commented 4 months ago

You need the Dispather if you update things from a Task.

private async Task ChangeValue()
{
    await Task.Delay(1000);
    Dispatcher.UiThread.Post(() => { TestInt = 10 });
    ExecutePreview();
}