0

I have MVVM application with multiple pages. My all pages have ReadCommand() bound with:

<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
        <i:InvokeCommandAction Command="{Binding ReadCommand}" CommandParameter="{Binding}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

This is my Read() command in ViewModel:

private void Read(object parameter)
    {
        HwDevice Device = new HwDevice();

        this.Alarms = Device.Alarms; // this is slow (reading data from RS232 device)
        Device.Dispose();
    }

One page has slow data source and my application is frozen when this page is being loaded (about 5 seconds).

I want to set wait cursor on whole window, but I don't know how to do it in MVVM (Im MVVM newbie). Do I have to pass window reference by command parameter and set Wait cursor in command? If I should - how can I do it in XAML?

Kamil
  • 13,363
  • 24
  • 88
  • 183

1 Answers1

1

The problem is that the thread where you are going to execute your operation, is the same where your UI live. It's here that the BackgroundWorker come in handy.

BackgroundWorker bw = new BackgroundWorker();
bw.RunWorkerAsync += bw_DoWork;
bw.ProgressChanged += bw_ProgressChanged;
bw.RunWorkerCompleted += bw_WorkDone

The previous part was the declaration. Now you need to implement the events, but first modify Read method

private void Read(object parameter)
{
     bw.RunWorkerAsync(parameter);
     // put your logic here
}

private void bw_DoWork(object sender, DoWorkEventArgs e)
{
    object parameter = e.Argument;
}

Now that the logic is placed on another thread, you can use the progressChanged method to do various stuff. Like showing a progress bar to report the status, or simply enable or disable your wait cursor.

EDIT: You don't need to pass the bw to the UI. If you are using MVVM (like you should and you are doing) you can use bindings and event at your advantage, or implement an interface like this one. The point of the whole thing is that the UI is just "informed" that something on the background is going on, avoiding to freeze the main thread. You just need to decide how to display it. So it can be either using a wait cursor, or implementing a progress bar.

Daniele Sartori
  • 1,674
  • 22
  • 38
  • But how do I pass `bw` reference from `ViewModel` to my UI? Should I create object in my ViewModel and bind UI to it? – Kamil Nov 21 '17 at 23:32
  • @Kamil i extended a little my answer. You don't need to pass the bw to your UI. the bw, through it's event notify something to the UI that will act accordingly, for instance showing a progress bar, while the bw will do it's job – Daniele Sartori Nov 22 '17 at 08:02