3

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();
    }
}

2 Answers 2

0

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

Sign up to request clarification or add additional context in comments.

1 Comment

This worked perfectly, thanks. I actually understand how Dispatchers work now. Application.Current.Dispatcher.Invoke(() => ImageSource = UpdateImage());
0

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"/>

1 Comment

I mentioned it briefly in the original post, but I know how to use ObservableCollection for updating a list. Is it possible to use them for updating just the Image Source binding, since it only needs a single object and not a list/collection?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.