Sep 1, 2011

Forcing WPF Controls to Update

One of the nice things about WPF is how easy it makes implementing MVVM. You can easily decouple the view from the logic that affects the view. Every application I write needs to disable and enable certain controls. Recently I was working on an application that plays back data files.


The figure at the left shows both the user interface and an example plot. The program opens a data file.  Then when the user hits play, a separate thread starts playing back the data in the second window. Everything worked perfectly in WPF using MVVM until the end of the data file was reached.

I know from my WinForm experience that updating the UI from a separate thread is a no-no (OK the official term is cross-threading violation). No problem, there are multiple ways I can get things to happen on the correct thread.  I decided in this case to move from my home-rolled thread to the BackgroundWorker class that .NET provides.  I set up the thread start method as the DoWork event handler and hooked up a ProgressChanged event handler. Finally, I set the property WorkerReportsProgress to true.

Now when all the data is read from the file, I just call the ProgressChanged method. The final key was determining which method to call to make the form properly update. Application.Current.MainWindow.UpdateLayout() or  the related InvalidateVisual() methods seemed like good candidates. Turns out they didn't work. Since the buttons implement ICommand, indirectly through the RelayCommand pattern I needed to get the form to check for a change in the underlying state. Luckily I did eventually discover just such an animal . All the progress changed handler had to do was make a single call to:


About Me

My photo
Tod Gentille (@todgentille) is now a Curriculum Director for Pluralsight. He's been programming professionally since well before you were born and was a software consultant for most of his career. He's also a father, husband, drummer, and windsurfer. He wants to be a guitar player but he just hasn't got the chops for it.