dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.22k stars 1.75k forks source link

CollectionView dont update automatically #8534

Open Suleman218 opened 2 years ago

Suleman218 commented 2 years ago

Description

I have a collection view with mvvm binding of ObserveableCollection, The issue is when page is appear and i click on a button to load data , the collection view doesn't update ui , i need to tap on screen then view updated, But if data is loaded on the time of page appearing by using OnAppearing cycle then every thing works fine

Steps to Reproduce

  1. Create A CollectoinView and bind item source using MVVM
  2. Write a command that load data from server/any data source and then add that data into ObserveableCollectoin which is binded with collection view item source.
  3. Create a button and bind that commad with that button. Click on button after page appearing.

https://github.com/dotnet/maui/files/9046945/Issue8534.zip

Version with bug

6.0 Release Candidate 2 or older

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android 12.0

Did you find any workaround?

No response

Relevant log output

No response

jsuarezruiz commented 2 years ago

Tried to reproduce without success.

Issue8534.zip Screenshot_1656936863

Could you attach a small sample where reproduce the issue?, are replacing the ObserveableCollection, adding items, etc?

ghost commented 2 years ago

Hi @Suleman218. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

Suleman218 commented 2 years ago

Test.zip Although the working sample you have sent to me is working fine but I'm following CommunityToolkit.Mvvm approach. I have attached my project.

You can see in file MainPage.cs I'm not loading the data on UI on app-startup rather I am loading it on button click event. When I click on "LoadData" button then it shows a blank screen but loads the data in observable collection. If you swipe up / down on blank screen, then data appear on the UI and you will be able to see it. But still missing some UI renderings (spinner etc.). This whole app works fine if I load the data on UI on app-startup (using OnAppearing override method, you can uncomment line 21 in MainPage.cs file to see this working), but doesn't work if I try to do the same on button click. @jsuarezruiz .

Thanks, Will wait for you response.

Core121 commented 2 years ago

I'm also having this issue while using the CommunityToolkit.Mvvm approach and would be willing to provide examples if the example above is not enough.

cdavidyoung commented 2 years ago

I think I am having the same issue. I am binding a WidthRequest of a XAML Label :

WidthRequest="{Binding MessageWidth}"

and changing MessageWidth when the window is resized. Of course, I am using the INotifyPropertyChanged and all that entails. In Xamarin this would be sufficient to cause that Label text to resize. However, in Maui I have to switch to another app and then back to the Maui app to get the Label to redraw its text.

Is this a bug or is there something else I have to do to get the app to redraw?

AdamBebko commented 1 year ago

I am also encountering this issue. The CollectionView doesn't update until I tap on the screen. I am using Community MVVM with an [ObservableProperty] ObservableCollection

Not sure if it's related but setting Auto on my grid heights doesn't resize to fit the size of the CollectionView either, although it DOES work for ListView.

symbiogenesis commented 1 year ago

I think this same thing is happening on Windows

rfpinto92 commented 1 year ago

I have the same issue: public ObservableCollection object { get; set; } = new();

homeyf commented 1 year ago

Verified this issue with Visual Studio Enterprise 17.6.0 Preview 7.0. Can repro on android platform with above project. Issue8534.zip demo2

jpc5812 commented 1 year ago

I am having the same issue on VS 17.6.0 with Android and Windows. If the bound ObservableCollection is a primitive type, i.e.
ObservableCollection items; the CollectionView renders property changes immediately. If the ObservableCollection has an object type, then property changes only render after navigating away from the page and back again.

jpc5812 commented 1 year ago

Sorry, I meant ObservableCollection\<string> items.

joaquin-avelon commented 1 year ago

Hi, just encountered this problem also (on Android). I've found a workaround. Not the most elegant thing, but it works.

So I change objects in my observable collection and the CollectionView did not update, until I clicked on it. What I've done to work around this, is calling ScrollTo(0) on the CollectionView after changing the data in the collection. It seems that this triggers a refresh.

Hope it can help you!

jsuarezruiz commented 1 year ago

I am having the same issue on VS 17.6.0 with Android and Windows. If the bound ObservableCollection is a primitive type, i.e. ObservableCollection items; the CollectionView renders property changes immediately. If the ObservableCollection has an object type, then property changes only render after navigating away from the page and back again.

Could you attach a sample where reproduce the issue?

Tried Issue8534.zip with 7.0.302 and cannot reproduce the issue. repro-cv-items

jeff-eats-pubsubs commented 1 year ago

ScrollTo(0)

@joaquin-avelon 🤯 THANK YOU! I was using ScrollTo(myCollection.Last()) in the CollectionChanged function to no avail. This is beautiful. Thank you once again

stefanpirkl commented 1 year ago

Same issue here on .Net 8 Preview 5 (and below).

Occasionally, changed items get updated if they're currently off screen. NEVER if they're currently visible.

Proposed workarounds aren't working for me.

This issue has been open for over a year, will it get fixed at all?

symbiogenesis commented 1 year ago

I created a workaround via these extension methods:

public static void ForceCollectionChanged<T>(this Collection<T> collection)
    where T : new()
{
    // TODO: Remove this whenever MAUI updates the collection correctly. https://github.com/dotnet/maui/issues/8534
    var tempRecord = new T();

    collection.ForceCollectionChanged(tempRecord);
}

public static void ForceCollectionChanged<T>(this Collection<T> collection, T tempRecord)
{
    // TODO: Remove this whenever MAUI updates the collection correctly. https://github.com/dotnet/maui/issues/8534
    collection.Add(tempRecord);
    _ = collection.Remove(tempRecord);
}
stefanpirkl commented 1 year ago

I created a workaround via these extension methods:

Thanks for that. Didn't work in my case, unfortunately.

michaelrinderle commented 1 year ago

ScrollTo(0)

@joaquin-avelon Thank you so much! I wish I saw this earlier to work around this bug.

I was able to reference my xaml control in my viewmodel from my code behind and use the ScrollTo(0) method to refresh my CollectionView! Not idea but beats the CollectionView not working.

I can confirm this is an Android issue...

AncientLust commented 8 months ago

Same thing on Windows application

NETools commented 8 months ago

Will this be fixed anytime soon? Still occuring, and its not like its a convenient bug.

Core121 commented 8 months ago

We rewrote our entire app in flutter because it was less effort than working around this issue and the many others we ran into with MAUI.

NETools commented 8 months ago

@Core121 Woah, didn't expect this to be a bug this severe. What's the reason microsoft has not fixed this? Or do they want to delegate such tasks to the community (= free labor)?

NETools commented 8 months ago

Thank God, using ObservableCollection solved my issue (-:

danielhuggins commented 7 months ago

Here is the solution i ended up going with:


    public async void SelectLastUploadedFile(FileData file)
    {
        // See https://github.com/dotnet/maui/issues/8534
        // No idea why this works, nor why it is necessary.
        await Task.Delay(100);
        SelectedFile = file;
        DoubleTapCommand.Execute(null);
        FileCollectionView.SelectedItem = null;
        FileCollectionView.SelectedItems = null;
        FileCollectionView.SelectionMode = SelectionMode.Multiple;
        FileCollectionView.SelectedItems = new List<object> { };
        FileCollectionView.SelectedItems = new List<object> { file };
        FileCollectionView.SelectedItems = FileCollectionView.SelectedItems.Take(1).ToList();
        FileCollectionView.SelectedItems = new List<object> { file };
        FileCollectionView.SelectedItems = FileCollectionView.SelectedItems.Take(1).ToList();
        FileCollectionView.SelectedItems = new List<object> { file };
        FileCollectionView.SelectionMode = SelectionMode.Single;
        FileCollectionView.SelectedItems = null;
        FileCollectionView.SelectedItem = file;
    }

It does the job.

GiovanniFox commented 7 months ago

Binding in a collectionview is working fine in my code, but remember to:

  1. use an ObservableCollection
  2. the type of object used in the collection must inherit from ObservableObject and each bindable property must be an ObservableProperty