Reputation: 1720
I fear I may already know the answer to this question but I'm holding out the smallest glimmer of hope that I am wrong.
I have repository that contains a Collection Property with a list of Items. This collection is updated from a webservice call that does 1 of 2 things. If it is the first call it will create a new instance of an Item for each row returned, populate it, and add it to the Collection. Subsequent calls instead look for that item in the collection and update its properties. The ViewModel, Item Class, and Repository implement INotifyPropertyChanged.
The call to the dataservice executes every 30 seconds updating the data using async / await with a Task similar to this: How to execute a method periodically from WPF client application using threading or timer. The ViewModel takes the items from the repositorys Collection and splits them into various collection properties. The View then binds via an ItemsControl to the individual items in each collection and properties are continually updated.
It all works beautifully... but, the DataService Call isn't in its own thread and despite the async/await the UI gets a little unresponsive about every 30 seconds. When I went to put the DataService call in a BackgroundWorker I realized I can't when it threw an exception about modifying from a different thread.
I am familar with this issue from WinForms but I was hoping to somehow sidestep it with WPF and twoway binding. Is there a way to make the UI more responsive with just async/await or is there a way put the updates in a thread without having to write the events to support a dispatcher to do the updates on the main thread?
Upvotes: 1
Views: 1800
Reputation: 4651
Your issue may lie in notifying each property on each item indivually. Using WPFPref (still part of the Windows SDK, I believe), you can see dirty areas of your UI (areas that are being rendered). If you find that your entire UI is being render again and again that will bog down performance.
A solution to this could be to prevent the UI from being notified while you are doing your refresh. There are several options:
Upvotes: 2
Reputation: 965
use "Binding.IsAsync" Property in your binding. Set the IsAsync property to true when the get accessor of your binding source property might take a long time. When IsAsync property is true then the UI will not blocked until the value is bound. For more info : MSDN
One example is an image property with a get accessor that downloads from the Web. Setting IsAsync to true avoids blocking the UI while the download occurs.
Also you can use PriorityBinding to achieve your requirement. PriorityBinding in Windows Presentation Foundation (WPF) works by specifying a list of bindings. The list of bindings is ordered from highest priority to lowest priority. If the highest priority binding returns a value successfully when it is processed then there is never a need to process the other bindings in the list. It could be the case that the highest priority binding takes a long time to be evaluated, the next highest priority that returns a value successfully will be used until a binding of a higher priority returns a value successfully.
<PriorityBinding FallbackValue="defaultvalue">
<Binding Path="SlowestDP" IsAsync="True"/>
<Binding Path="SlowerDP" IsAsync="True"/>
<Binding Path="FastDP" />
</PriorityBinding>
Detailed Info : PriorityBinding
Upvotes: 1