bwoogie
bwoogie

Reputation: 4427

Update Listview after async method

I have an ObservableCollection that holds the items for a ListView.

ObservableCollection<MyListItem> Items { get; set; }

During item creation an image path is pulled from cache.

public class MyListItem {
    public string Image { get; set; }
    public MyListItem(string url) {
    ...
        setImage(url);
    }

    private async void setImage(string url) {
        Image = await MyCachingLib.GetUrlAsync(url);
    }
}

However, if the image isn't already in cache, we download it from the internet. This takes too long and the UI seems to have already updated by the time Image is set.

How can I update my ListView each time an Item is done fetching an image?

I tested to make sure its not my caching library with this:

private async void setTitle(string title) {
   await Task.Delay(2000); //pretend to get data from the web
   Title = title;
}

...And the title doesn't update with the delay.

Upvotes: 0

Views: 409

Answers (2)

iSpain17
iSpain17

Reputation: 3053

Another way is to make your class derive from BindableObject, so that you can do this:

public class MyListItem : BindableObject {
    public string Image { get; set; }
    public MyListItem(string url) {
    ...
        setImage(url);
    }

    private async void setImage(string url) {
        Image = await MyCachingLib.GetUrlAsync(url);
        OnPropertyChanged(nameof(Image));
    }
}

The added line will do just what you want, signal that Image was updated without having to implement a full property.

Upvotes: 0

lawiluk
lawiluk

Reputation: 599

Make your MyListItem implement INotifyPropertyChanged. With that approach, changes will be propagated to the UI.

public class MyListItem : BaseModel
{
    private string image;
    public string Image
    {
        get => image;
        set
        {
            image = value;
            OnPropertyChanged(nameof(Image));
        }
    }

    public MyListItem(string url)
    {
        ...
        setImage(url);
    }


    private async void setImage(string url)
    {
        Image = await MyCachingLib.GetUrlAsync(url);
    }
}

public abstract class BaseModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        changed?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

I've done it with BaseModel but you can freely put INotifyImplementation in your model.

In your Xaml/UI file, just bind to Image. It should work ;-)

Upvotes: 1

Related Questions