Monday 27 August 2012

Update TextBox using AppendText method in real time for WPF Applications

A few days ago I was working on an application that imports several different MS Dynamics CRM 2011 solutions to various environments and I had designed a simple form that contained a big text box which would be updating with progress and a couple of buttons. The problem that I had was that all the progress information would get updated at the end of the import process, which was completely useless as I wanted the progress information to be displayed in real time. 

After a lot of searching I hit upon the issue, which, without going into too much detail is related to threads. In essence, the GUI is waiting for the result of an operation and until that operation finishes it's blocked, which means that nothing is displayed. You probably have seen this when a window becomes non responsive while the application is processing a long(-ish) running process. The way around this problem is by using the Dispatcher.

The code below shows a simple example of how this is accomplished, where Import_Click is the event for a button named Import (xaml not displayed for simplicity).

The key is the WriteMessage method, which uses the dispatcher to invoke the AppendText method for the passed-in MessageBox using a lambda expression, the rest of the code is, hopefully, fairly self-explanatory.

 public partial class MainWindow : Window
 {
     private readonly BackgroundWorker import = new BackgroundWorker();
 
     public MainWindow()
     {
         InitializeComponent();
         import.DoWork += new DoWorkEventHandler(import_DoWork);
     }
     
     private void import_DoWork(object sender, DoWorkEventArgs e)
     {
         Import();
     }
     
     private void Import_Click(object sender, RoutedEventArgs e)
     {
         import.RunWorkerAsync();
     }
     
     public void Import()
     {
             WriteMessage(MessagetTextBox,string.Format("Import started @ {0}.{1}", DateTime.Now,Environment.NewLine));
             
             //DOSTUFFHERE
             
             WriteMessage(MessagetTextBox,string.Format("Import finished @ {0}.{1}", DateTime.Now,Environment.NewLine));
     }
     
     private void WriteMessage(TextBox MessageBox, string Message)
     {
         Dispatcher.Invoke((Action)(() => MessageBox.AppendText(Message)));
     }
 
 }

2 comments:

  1. Do you have an example where you pass arguments to import()?

    ReplyDelete
  2. Do you have an example where you pass arguments to import()?

    ReplyDelete