I have a WPF markup extension in charge of retrieving images by name, returning a BitmapImage object.
<Image Source="{my:ImageProvider ImageName=myImageName}"></Image>
Since retrieving an image is an operation that can possibly take a few seconds, I’d like to show a default image and display the requested image once it’s ready.
What I tried to do is something like this, but as this may change the BitmapImage object, it won’t update the UI (sample code):
BitmapImage img;
public override object ProvideValue(IServiceProvider serviceProvider)
{
img = new BitmapImage(new Uri(@"D:\defaultImage.png", UriKind.Absolute));
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.RunWorkerAsync();
return img;
}
void bw_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
System.Threading.Thread.Sleep(5000);
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
img.UriSource = new Uri(@"D:\actualImage.png", UriKind.Absolute);
}
Is there a way I can update the UI to use the modified BitmapImage (something like INotifyPropertyChanged) or is there a different approach to achieve this?
I ended up with two ways to do this. Both ways use a class that wraps the image and implements
INotifyPropertyChanged:First Approach
Once I have this, I can have my markup extension return an
ImageSourceWrapperobject and bind to it, like soI didn’t really like this way, since it’s pretty messy and involves having to know the
ImageSourceWrapperclass rather than working simply withImageSource. Then I came up with the second approach.Second Approach
In this approach I still use the
ImageSourceWrapperclass, but instead of having my markup extension return anImageSourceWrapperobject, I return a binding object which I set up to be bound to anImageSourceWrapperobject.The markup extension looks something like this:
Then I can use it in XAML like this
This way the default image is displayed first, and once the requested image is retrieved, it will be displayed instead.
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.