Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image does not update after changing Image Uri #15

Open
Kas-code opened this issue Feb 7, 2024 · 2 comments
Open

Image does not update after changing Image Uri #15

Kas-code opened this issue Feb 7, 2024 · 2 comments

Comments

@Kas-code
Copy link

Kas-code commented Feb 7, 2024

Description

If we are using the UriImageSource then the image does not update when changing the Uri via a binding.
If we use a regular <Image> control from MAUI.Controls with a UriImageSource then changing the Uri does update the image, so this is a degradation from MAUI.

Steps to Reproduce

XAML:

 <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
   xmlns:ffimageloading="clr-namespace:FFImageLoading.Maui;assembly=FFImageLoading.Maui"
    x:Class="MyProject.MyPage">
     <StackLayout>
	 <ffimageloading:CachedImage
		 HeightRequest="100"
		 WidthRequest="100"
		 Margin="10"
		 RetryCount="3"
		 RetryDelay="250"
		 DownsampleToViewSize="true"
		 Aspect="AspectFill">
		 <ffimageloading:CachedImage.Source>
			 <UriImageSource Uri="{Binding ImageUrl}"
							 CacheValidity="3"
							 CachingEnabled="true"/>
		 </ffimageloading:CachedImage.Source>
	 </ffimageloading:CachedImage>
	 
	 <Button Margin="10" Text="Change Image" Command="{Binding ChangeImageCommand}">
         </Button>
	 
 </StackLayout>
 </ContentPage>

Code behind:

public partial class MyPage : ContentPage
{
    public MyPage()
    {
        InitializeComponent();
        BindingContext = new MyPageViewModel();
    }
}

View Model:

public class MyPageViewModel : ContentPage
{
        public MyPageViewModel()
        {
            ChangeImageCommand = new Command(ChangeImage);
        }

        String _imageUrl = "--Some Image Url--";

        public String ImageUrl
        {
            get => _imageUrl;
            set => SetProperty(ref _imageUrl, value);
        }
		
		private async void ChangeImage()
        {
            ImageUrl = "--A different Image Url--";
        }
}

Expected Behavior

When clicking the button to change the image Uri, the image should change.

Actual Behavior

The image does not change

Basic Information

  • Version with issue: 1.0.8
  • Last known good version: N/A
  • Platform: Android
@Kas-code
Copy link
Author

Kas-code commented Feb 7, 2024

If we use Source="{Binding ImageUrl}" then it works as expected, the issue only exists when using UriImageSource
Using Source is fine as a workaround for now.

@microspaze
Copy link
Owner

Currently it is impossible to get the same effect as MAUI Image binding UriImageSource. Because ImageSource is not a BindableObject, when its source changed the ffimageloading:CachedImage can not get the notification to update the image.

But why MAUI Image can?

It use a tricky implementation. When Image's source property has been set, it will add a new event handler to the ImageSource's SourceChanged event. Then when the ImageSource's source property changed, it will notify the Image to change image.

https://github.com/dotnet/maui/blob/main/src/Controls/src/Core/Image/Image.cs
https://github.com/dotnet/maui/blob/df4b84b8a3f95cd26b29bccf47a2b4760c0dd8d3/src/Controls/src/Core/ImageElement.cs#L8
https://github.com/dotnet/maui/blob/main/src/Controls/src/Core/ImageSource.cs#L12

static void OnImageSourceChanged(BindableObject bindable, object oldValue, object newValue)
{
	var newSource = (ImageSource)newValue;
	var image = (IImageElement)bindable;
	if (newSource != null && image != null)
		newSource.SourceChanged += image.OnImageSourceSourceChanged;
	ImageSourceChanged(bindable, newSource);
}

But why FFImageLoading can not do like this? Because the ImageSource's SourceChanged is INTERNAL.

internal event EventHandler SourceChanged
{
	add { _weakEventManager.AddEventHandler(value); }
	remove { _weakEventManager.RemoveEventHandler(value); }
}

The walkaround is JUST to bind your ImageUrl to CachedImage's Source property. It will help you do all the other things.

<ffimageloading:CachedImage
		 HeightRequest="100"
		 WidthRequest="100"
		 Margin="10"
		 RetryCount="3"
		 RetryDelay="250"
		 DownsampleToViewSize="true"
		 Aspect="AspectFill"
		 Source="{Binding ImageUrl}">
</ffimageloading:CachedImage>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants