Question

I'm trying to update a BitmapImage in the UI from a BackgroundWorker thread. I know enough about background workers to generally set them up, and how to use an ObservableCollection to update a list from a BackgroundWorker, but I'm struggling getting the image to update.

When I set

So far it looks like this:

XAML:

<Image Source="{Binding ImageSource}" />

ViewModel:

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private BitmapImage ImageSource_;
    public BitmapImage ImageSource
    {
        get { return ImageSource_; }
        set { ImageSource_= value; NotifyPropertyChanged("ImageSource"); }
    }

    private BackgroundWorker UpdateImageBGW = new BackgroundWorker();

    public ViewModel()
    {
        // this works fine
        ImageSource = UpdateImage();

        UpdateImageBGW.DoWork += new DoWorkEventHandler(UpdateImage_DoWork);
        UpdateImageBGW.RunWorkerAsync();
    }

    private void UpdateImage_DoWork(object sender, DoWorkEventArgs e)
    {
        // this gets called fine and grabs the updated image, but setting it to
        // ImageSource never updates the UI
        ImageSource = UpdateImage();
    }
}
Was it helpful?

Solution

The problem is you are trying to update a UI element from a background thread. You cannot interact with elements created on the UI thread from any other thread because of security reasons. If you want to update the UI from a background thread, do something like this:

Dispatcher.Invoke((Action)delegate() { /*update UI thread here*/ });

This method will create the bridge that allows you to talk to the UI thread. Check out this stackoverflow thread that has more example.

Best of Luck

OTHER TIPS

use ObservableCollection like this:

 public partial class MainWindow : Window
{
    private ObservableCollection<int> myVar;

    public ObservableCollection<int> MyProperty
    {
        get { return myVar; }
        set { myVar = value; }
    }

    BackgroundWorker bw;
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
        MyProperty = new ObservableCollection<int>();
        bw = new BackgroundWorker();
        bw.DoWork += bw_DoWork;
        bw.RunWorkerAsync();
    }

    void bw_DoWork(object sender, DoWorkEventArgs e)
    {
       for(int i = 0; i < 10;i++)
       {
           MyProperty.Add(i);
       }
    }
}

and xaml:

<ListBox HorizontalAlignment="Left" ItemsSource="{Binding MyProperty}" Height="224" Margin="93,50,0,0" VerticalAlignment="Top" Width="321"/>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top