BindableProperty of ImageSource type raises PropertyChanged twice in custom Views

DanielLDanielL PLInsider ✭✭✭✭
edited October 2015 in Xamarin.Forms

In custom views, when using ImageSource bindable properties, the PropertyChanged is raised twice! It can lead to major performance issues in custom controls using images.

Output:
!!! HomeViewModel PropertyChanged: ShowImage, value: http://ed66d424bbb74367b326a5d9900185c4.com
!!! View PropertyChanged: Image, Image hash: 289996192, value: http://ed66d424bbb74367b326a5d9900185c4.com/
!!! View PropertyChanged: Image, Image hash: 671983716, value: http://ed66d424bbb74367b326a5d9900185c4.com/

Is it a bug? Or am I missing something?

Code:

public class App : Application
{
  public App()
  {
    var viewModel = new HomeViewModel();

    var myView = new MyView();
    myView.SetBinding<HomeViewModel>(MyView.ImageProperty, v => v.ShowImage);

    MainPage = new ContentPage {
      BindingContext = viewModel,
      Content = myView 
    };

    viewModel.Reload();
  }

  public class MyView : View
  {
    public MyView()
    {
      PropertyChanged += (sender, e) => {
        if (e.PropertyName == MyView.ImageProperty.PropertyName)
          Console.WriteLine(string.Format("!!! View PropertyChanged: {0}, Image hash: {1}, value: {2}", 
            e.PropertyName, Image.GetHashCode(), ((UriImageSource)Image).Uri));
      };
    }

    public static readonly BindableProperty ImageProperty = BindableProperty.Create<MyView, ImageSource>(w => w.Image, null);

    public ImageSource Image
    {
      get
      {
        return (ImageSource)GetValue(ImageProperty);
      }
      set
      {
        SetValue(ImageProperty, value);
      }
    }
  }

  public class HomeViewModel : INotifyPropertyChanged
  {
    public HomeViewModel()
    {
      PropertyChanged += (sender, e) => {
        if (e.PropertyName == "ShowImage")
          Console.WriteLine(string.Format("!!! HomeViewModel PropertyChanged: {0}, value: {1}", 
            e.PropertyName, ShowImage));
      };
    }

    public void Reload()
    {
      ShowImage = "http://" + Guid.NewGuid().ToString("N") + ".com";
    }

    string showImage;
    public string ShowImage
    {
      get
      {
        return showImage;
      }
      set
      {
        showImage = value;
        OnPropertyChanged("ShowImage");
      }
    }

    #region INotifyPropertyChanged implementation

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion

    public void OnPropertyChanged(string propertyName)
    {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null) 
        handler(this, new PropertyChangedEventArgs(propertyName));
    }
  }

  protected override void OnStart()
  {
    // Handle when your app starts
  }

  protected override void OnSleep()
  {
    // Handle when your app sleeps
  }

  protected override void OnResume()
  {
    // Handle when your app resumes
  }
}

Best Answers

Answers

  • DanielLDanielL PLInsider ✭✭✭✭

    Anyone?

  • DanielLDanielL PLInsider ✭✭✭✭
    edited October 2015

    @DavidStrickland0 Thanks for the info! I'm not alone! :) In my opinion, it should be filled as a bug or at least documented somewhere. On some simple things, performance hit is negligible. But ImageSource is mostly used with images. Redrawing something twice can lead to visible UI slowness and memory usage problems.

  • threadythready CAMember ✭✭✭
    edited December 2015

    I'm getting this problem with the latest version of Xamarin Forms (just updated)

Sign In or Register to comment.