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 Source to null doesn't work if the Source had a different value before #8787

Closed
AignerGames opened this issue Jul 17, 2022 · 11 comments · Fixed by #13614
Closed

Image Source to null doesn't work if the Source had a different value before #8787

AignerGames opened this issue Jul 17, 2022 · 11 comments · Fixed by #13614
Assignees
Labels
area-controls-image Image control fixed-in-7.0.81 Look for this fix in 7.0.81! fixed-in-7.0.92 Look for this fix in 7.0.92! fixed-in-7.0.100 fixed-in-7.0.101 fixed-in-8.0.0-preview.3.8149 Look for this fix in 8.0.0-preview.3.8149! p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint platform/android 🤖 platform/windows 🪟 t/bug Something isn't working

Comments

@AignerGames
Copy link

Description

I have a Image and the Source property is bound to a ImageSource property of my ViewModel class.

I have a button to take a image and then update the ImageSource (including PropertyChanged etc).
This works so far, the Image updates after I take a new image.

I added a delete button to delete the image and set my ImageSource property to null (including Propertychanged call etc.)
But I noticed that the Image doesn't change back to null / blank, the old image is still shown, no matter how often I set it to null or invoke the PropertyChanged event

I even tried to take a direct reference to the Image in my View code and noticed that even setting the property directly to null by code doesn't reset the image.

So there is no way to reset the Image source after a "real" image was shown.

Steps to Reproduce

1, Add a Image and set a "real" Image Source (Image should be visible)
2, Change the Image Source to null by code or binding (for example with a button click handler)
3, Confirm that the Image Source is null -> Old Image is still shown, even after the Source was set to null

Version with bug

6.0.408 (current)

Last version that worked well

Unknown/Other

Affected platforms

Android, Windows

Affected platform versions

Windows 10

Did you find any workaround?

Hide the image with a IsVisible Binding

Relevant log output

No response

@AignerGames AignerGames added s/needs-verification Indicates that this issue needs initial verification before further triage will happen t/bug Something isn't working labels Jul 17, 2022
@Dreamescaper
Copy link

Similar case - if MAUI fails to load the image with the new ImageSource (e.g. due to incorrect Url). It keeps showing the old image, while previously (XF or MAUI GA) it was hidden.

@Eilon Eilon added the area-image Image loading, sources, caching label Jul 18, 2022
@rmarinho rmarinho added area-controls-image Image control and removed s/needs-verification Indicates that this issue needs initial verification before further triage will happen labels Jul 20, 2022
@ghost ghost added the legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor label Jul 20, 2022
@rmarinho rmarinho added s/needs-repro Attach a solution or code which reproduces the issue and removed legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor labels Jul 20, 2022
@ghost
Copy link

ghost commented Jul 20, 2022

Hi @AignerGames. We have added the "s/needs-repro" label to this issue, which indicates that we require steps and sample code to reproduce the issue before we can take further action. Please try to create a minimal sample project/solution or code samples which reproduce the issue, ideally as a GitHub repo that we can clone. See more details about creating repros here: https://github.com/dotnet/maui/blob/main/.github/repro.md

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.

@rmarinho
Copy link
Member

Thank you so much for your bug report! Unfortunately, this report seems to be missing some details.

Ideally we would love to have a minimal, reproducible example that you upload to a GitHub repository and link us to. That should greatly speed up the process, thanks!

@ghost ghost added s/needs-attention Issue has more information and needs another look and removed s/needs-repro Attach a solution or code which reproduces the issue labels Jul 20, 2022
@AignerGames
Copy link
Author

This project can be used to see the issue in action:

See Bug #2 ImageSource Null, the file contains a custom NullConverter as a workaround because of this null ImageSource issue

@marcojak
Copy link

Same problem. Very annoying. I've seen there is a PR but it was closed while the team is focusing on something else.
I'm worried that with this approach, this PR will be forgotten and the bug will stay forever.

@andycambo
Copy link

Leaving a comment to also state that I've come across this issue.

You would expect setting an ImageSource to 'null' would remove the image.

@JkPersson
Copy link

Also seeing this problem.

We use it to display various error states, so obviously it very important for us to be able to clear the state when fixed.

@jerry08
Copy link

jerry08 commented Jan 1, 2023

I'm facing this problem too and it seems like this bug will remain for a while so I made a workaround for now. I created a custom handler for Image. Here's my code:

Handler:

using System;
using Microsoft.Maui;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Networking;
using System.ComponentModel;
using MyProject.Utils.Extensions;

#if IOS || MACCATALYST
using PlatformImage = UIKit.UIImageView;
#elif ANDROID
using PlatformImage = Android.Widget.ImageView;
#elif WINDOWS
using PlatformImage = Microsoft.UI.Xaml.Controls.Image;
#elif NETSTANDARD || !PLATFORM || (NET6_0_OR_GREATER && !IOS && !ANDROID)
using PlatformImage = System.Object;
#endif

namespace MyProject.Handlers;

public class CustomImageHandler : ImageHandler
{
    public Image? Image { get; set; }

    public override void SetVirtualView(IView view)
    {
        base.SetVirtualView(view);

        if (VirtualView is Image image)
        {
            Image = image;

            Connectivity.Current.ConnectivityChanged -= ConnectivityChanged;
            Connectivity.Current.ConnectivityChanged += ConnectivityChanged;

            Image.PropertyChanged -= PropertyChanged;
            Image.PropertyChanged += PropertyChanged;

            Image.BindingContextChanged -= BindingContextChanged;
            Image.BindingContextChanged += BindingContextChanged;
        }
    }

    private void BindingContextChanged(object? sender, EventArgs e)
        => ReloadImage();

    private void PropertyChanged(object? sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(Image.Source) && Image?.Source is null)
            Image?.SetNullImage();
    }

    private void ConnectivityChanged(object? sender, ConnectivityChangedEventArgs e)
    {
        if (e.NetworkAccess == NetworkAccess.Internet)
            ReloadImage();
    }

    public void ReloadImage()
    {
        Image?.SetNullImage();
        SourceLoader.UpdateImageSourceAsync();
    }
}

Image Extension:

using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;

namespace MyProject.Utils.Extensions;

public static class ImageEx
{
    public static void SetNullImage(this Image image)
    {
        if (image.Handler is ImageHandler handler)
            handler.SourceLoader.SetNullImage();
    }
}

ImageSourcePartLoader extension:
using System;
using System.Reflection;
using Microsoft.Maui.Platform;

#if IOS || MACCATALYST
using PlatformImage = UIKit.UIImage;
#elif ANDROID
using PlatformImage = Android.Graphics.Drawables.Drawable;
#elif WINDOWS
using PlatformImage = Microsoft.UI.Xaml.Media.ImageSource;
#elif TIZEN
using PlatformImage = Microsoft.Maui.Platform.MauiImageSource;
#elif NETSTANDARD || !PLATFORM || (NET6_0_OR_GREATER && !IOS && !ANDROID && !TIZEN)
using PlatformImage = System.Object;
#endif

namespace MyProject.Utils.Extensions;

public static class ImageSourcePartLoaderEx
{
    public static void SetNullImage(this ImageSourcePartLoader sourceLoader)
    {
        var sourceLoaderType = sourceLoader.GetType();

        var setImageProp = sourceLoaderType.GetProperty("SetImage",
            BindingFlags.NonPublic | BindingFlags.Instance);
        var setImageM = (Action<PlatformImage?>?)setImageProp?.GetValue(sourceLoader);

        var sourceManager = sourceLoaderType.GetProperty("SourceManager",
            BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(sourceLoader);
        var completeLoadM = sourceManager?.GetType()
            .GetMethod("CompleteLoad", new[] { typeof(IDisposable) });

        setImageM?.Invoke(null);
        completeLoadM?.Invoke(sourceManager, new object?[] { null });
    }
}

Register the handler in MauiProgram:

.ConfigureMauiHandlers(handlers =>
    {
        handlers.AddHandler<Image, CustomImageHandler>();
    })

@Greg-Bates-Trimble
Copy link

Any update on this please?

@Greg-Bates-Trimble
Copy link

My workaround for now has been to use a transparent image. Instead of setting ImageSource to null, replace with the name of the transparent image.

@jerry08
Copy link

jerry08 commented Jan 16, 2023

If the image source fails (e.g. invalid url or no internet), the previous image source will remain (that's if you're changing the image source from one to another). This is especially evident when using a CollectionView or ListView because these controls reuse cells when scrolling. Using those controls requires setting the source to null in order to not reuse images if the source fails to load. Setting the image as transparent will introduce bugs. (I tested it before.)
If you're loading the image from a byte array or stream, then setting the image as transparent will do just fine.

@samhouts samhouts added the p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint label Mar 2, 2023
hartez added a commit that referenced this issue Mar 15, 2023
* Blank image when Source set to null or on image loading error
Fixes #8787

* Auto-format source code

* Null check cleanup

* Fix test

---------

Co-authored-by: GitHub Actions Autoformatter <autoformat@example.com>
PureWeen pushed a commit that referenced this issue Mar 16, 2023
#13989)

* Blank image when Source set to null or on image loading error
Fixes #8787

* Auto-format source code

* Null check cleanup

* Fix test

---------

Co-authored-by: E.Z. Hart <hartez@gmail.com>
Co-authored-by: GitHub Actions Autoformatter <autoformat@example.com>
@samhouts samhouts added this to the .NET 8 Planning milestone Mar 17, 2023
rmarinho pushed a commit that referenced this issue Mar 21, 2023
…image loading error (#14071)

* Blank image when Source set to null or on image loading error Fixes #8787

* Auto-format source code

* Null check cleanup

* Fix test

---------

Co-authored-by: E.Z. Hart <hartez@gmail.com>
Co-authored-by: GitHub Actions Autoformatter <autoformat@example.com>
@samhouts samhouts added fixed-in-7.0.81 Look for this fix in 7.0.81! fixed-in-8.0.0-preview.3.8149 Look for this fix in 8.0.0-preview.3.8149! labels Apr 12, 2023
@ghost ghost locked as resolved and limited conversation to collaborators May 12, 2023
@samhouts samhouts added the fixed-in-7.0.92 Look for this fix in 7.0.92! label Jul 11, 2023
@Eilon Eilon removed the area-image Image loading, sources, caching label May 10, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-controls-image Image control fixed-in-7.0.81 Look for this fix in 7.0.81! fixed-in-7.0.92 Look for this fix in 7.0.92! fixed-in-7.0.100 fixed-in-7.0.101 fixed-in-8.0.0-preview.3.8149 Look for this fix in 8.0.0-preview.3.8149! p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint platform/android 🤖 platform/windows 🪟 t/bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.