2
\$\begingroup\$

Is this an acceptable approach to update WPF MainWindow from an async task, using events thrown from a public static class?

  • In MainWindow.cs, I subscribe to UI.TaskCompleted event
  • In UI.cs, I subscribe to AsyncTaskActions.TaskCompleted event

Using this pattern, AsyncTaskActions.TaskCompleted is raised when an async task is completed. UI catch the event and raise UI.TaskCompleted. This way, the event is caught in MainWindow where I can use Displacher.Invoke to refresh the displayed page. The end result is I get a page refresh when a task is completed and the task still runs asychronously.

Application design summary:

  • MainWindow: main window which can have several different page classes in content area within the main window.
  • Common.cs public static class contains a number of common methods through the UI in the application.
  • AsyncTaskActions.cs - class with a number of async common methods (i.e. download file)

Code snippets:

    public partial class MainWindow 
        public MainWindow()
        {    
           UI.TaskCompleted += UI_TaskCompleted; 
        }

        void UI_TaskCompleted(EventArgs e)
        {
           Dispatcher.Invoke(new Action(this.PageRefresh));
        }

       public void PageRefresh()        
       {
           var page = ((ContentArea)).Content;
           if (page == null) return;

            //if (page.GetType().Name == "")
            switch (page.GetType().Name)
            {
                case "SearchPage":
                    ((SearchPage) page).SearchParts();
                    break;
                case "LegoPartPage":
                    ((LegoPartPage) page).LoadData();
                    break;
                case "LegoSetPage":
                    ((LegoSetPage) page).LoadData();
                    break;
                case "MainPage":
                    ((MainPage) page).LoadData();
                    break;
                case "MiniFigPage":
                    ((MiniFigPage) page).LoadData();
                    break;
            }
        }
   }

    public static class UI
    {
       public delegate void TaskComplete(EventArgs e);
       public static event TaskComplete TaskCompleted;

        public static async Task<int> DownloadPriceSummaryAsync(String itemNo, Int64 colorId)
        {
            var wAsyncTaskClasses = new AsyncTaskClasses();
            wAsyncTaskClasses.TaskCompleted += wAsyncTaskClasses_TaskCompleted;
            Task<HtmlDocument> task = wAsyncTaskClasses.DownloadPriceGuide(string.Format(Common.BrickLinkPrice, itemNo, colorId), itemNo, colorId);
            return await  wAsyncTaskClasses.ParsePriceSummaryAsync(task, itemNo, colorId);
        }
 }


public class AsyncTaskActions
{
    public delegate void TaskComplete(object sender, EventArgs e);
    public event TaskComplete TaskCompleted;

    public async Task<int> ParsePriceSummaryAsync(Task<HtmlDocument> task, string itemNo, Int64 colorId)
    {
        return await Task.Run(() => ParsePriceSummary(task, itemNo, colorId));
    }

    public int ParsePriceSummary(Task<HtmlDocument> task, string itemNo, Int64 colorId)
    {


        if (null != TaskCompleted)
        {
            TaskCompleted(this, new EventArgs());
        }

        return recordCount;
    }
\$\endgroup\$
1
\$\begingroup\$

I would look into MVVM, then your async task will operate on the ViewModel and not the UI element. Then WPF will update the UI when it deem fit.

I like Caliburn.Micro for the MVVM parts

https://github.com/Caliburn-Micro

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.