Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I ended up with two ways to do this. Both ways use a class that wraps the image and implements <code>INotifyPropertyChanged</code>:</p> <pre><code>class ImageSourceWrapper : ObservableObject { private ImageSource _image; public ImageSource Image { get { return _image; } set { if (value != _image) { _image = value; RaiseOnPropertyChanged("Image"); } } } public ImageSourceWrapper(ImageSource image) { Image = image; } } </code></pre> <h2>First Approach</h2> <p>Once I have this, I can have my markup extension return an <code>ImageSourceWrapper</code> object and bind to it, like so</p> <pre><code>&lt;Image Source="{Binding Source={my:ImageProvider ImageName=myImageName}, Path=Image}" /&gt; </code></pre> <p>I didn't really like this way, since it's pretty messy and involves having to know the <code>ImageSourceWrapper</code> class rather than working simply with <code>ImageSource</code>. Then I came up with the second approach.</p> <h2>Second Approach</h2> <p>In this approach I still use the <code>ImageSourceWrapper</code> class, but instead of having my markup extension return an <code>ImageSourceWrapper</code> object, I return a binding object which I set up to be bound to an <code>ImageSourceWrapper</code> object.</p> <p>The markup extension looks something like this:</p> <pre><code>private ImageSourceWrapper _imageSourceWrapper; public override object ProvideValue(IServiceProvider serviceProvider) { // Get the object and the property to be bound. IProvideValueTarget service = IProvideValueTarget)provider.GetService(typeof(IProvideValueTarget)); DependencyObject targetObject = service.TargetObject as DependencyObject; DependencyProperty targetProperty = service.TargetProperty as DependencyProperty; // Set up the binding with the default image. _imageSourceWrapper = new ImageSourceWrapper(DefaultImage); Binding binding = new Binding("Image"); binding.Source = _imageSourceWrapper; BindingOperations.SetBinding(targetObject, targetProperty, binding); // Retrieve the actual image asynchronously. GetImageAsync(); return binding.ProvideValue(serviceProvider); } private void GetImageAsync() { // Get the image asynchronously. // Freeze the image so it could be accessed from all threads regardless // of which thread it was created on. newImage.Freeze(); // Got the image - update the _imageSourceWrapper object. _imageSourceWrapper = newImage; } </code></pre> <p>Then I can use it in XAML like this</p> <pre><code>&lt;Image Source="{my:ImageProvider ImageName=myImageName}" /&gt; </code></pre> <p>This way the default image is displayed first, and once the requested image is retrieved, it will be displayed instead.</p> <p><em>Sorry if the code here isn't entirely correct, I'm not near the code at the moment. Hopefully this is enough at the moment to express the main idea.</em></p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload