Jordan
Jordan

Reputation: 9901

Real-time Binding in WPF

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

Answers (2)

Daniel Rose
Daniel Rose

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):

  • The specific control itself (which is so slow) may be too complicated/bloated. For example, I had a control which loaded a 400kb style file every time it was created. Obviously, this took some time. In my case, the solution was to load the style file in the parent control once.
  • The main thread (which generally is your UI thread) does too much processing at a time. You might be blocking the thread with some long-running calculation, which means it has no chance to update the UI. So this calculation should be done in a different thread (BackgroundWorker, ThreadPool thread, ...).
  • The entire UI may be too complicated. You might have an extremely deep visual/logical tree or be using large styles/templates with lots of triggers or legacy bitmap effects, etc.

Upvotes: 3

Pavlo Glazkov
Pavlo Glazkov

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

Related Questions