Reputation: 9901
Very simply, how can I make binding more responsive. That is, changing the interface closer to when the view model is changed in the background.
I have a timer-based progress bar that is incredibly jumpy. And I have a touchscreen keyboard that updates the field like hours (exaggeration) later than the key is pressed.
Upvotes: 3
Views: 6317
Reputation: 17638
The problem is the queue priorities of the Dispatcher (see this). Even if you were to respond faster to a change in the ViewModel (for example by manually updating controls), the rendering itself is done at a lower priority. Thus, I guess it won't make any noticeable difference for you to respond faster since the user won't see it under after the next rendering.
EDIT: In general, the UI in WPF, even when doing data binding, is very responsive. However, there are some reasons why it can be slow (take a look at the app using the WPF performance toolkit):
Upvotes: 3
Reputation: 20746
OK, there are three options you can use when it comes to making UI responsive:
(1). Use asynchronous bindings:
<TextBlock Text="{Binding ViewModelTextProperty, IsAsync=True}"/>
This way the value of ViewModelTextProperty
will be retrieved asynchronously.
(2). Use PriorityBinding
- it is similar to the previous option, but additionally it allows you to display something while main binding is executing asynchronously:
<TextBlock>
<TextBlock.Text>
<PriorityBinding>
<Binding Path="ViewModelTextProperty" IsAsync="True"/>
<Binding Path="FastViewModelTextProperty" IsAsync="True"/>
</PriorityBinding>
</TextBlock.Text>
</TextBlock>
Slow bindings are specified on the top and the fast ones in the buttom. That is, in this example, value of FastViewModelTextProperty
will be displayed first and when value of ViewModelTextProperty
is ready it will be displayed.
(3). And finally, you can use usual asyncronious programming in your view model (call methods asynchronously, use timers, etc.). And whenever you are ready to display some data, update the UI (set values of bound properties) using Dispatcher:
private void OnAsyncOperationCompleted()
{
Application.Current.Dispatcher.BeginInvoke(new Action(() => {
// Update the UI
}));
}
Upvotes: 5