2011-02-03 6 views
3

Très simplement, comment rendre la reliure plus réactive. C'est-à-dire, changer l'interface plus près du moment où le modèle de vue est changé en arrière-plan.Liaison en temps réel dans WPF

J'ai une barre de progression basée sur le minuteur qui est incroyablement nerveux. Et j'ai un clavier à écran tactile qui met à jour le champ comme des heures (exagération) plus tard que la touche est enfoncée.

+0

Ce n'est pas exactement ce que vous demandez, mais WPF a quelque chose comme PriorityBinding de sorte que vous pouvez afficher la valeur différente lorsque la liaison lente est en cours de chargement en arrière-plan. Il y a aussi DispatchPriority, donc vous pouvez décider comment l'interface utilisateur rapide recevra des éléments du distributeur. – baalazamon

Répondre

2

Le problème réside dans les priorités de file d'attente du Dispatcher (voir this). Même si vous réagissiez plus rapidement à une modification du ViewModel (par exemple en mettant à jour manuellement les contrôles), le rendu lui-même est effectué à une priorité inférieure. Ainsi, je suppose que cela ne fera aucune différence notable pour que vous puissiez répondre plus rapidement puisque l'utilisateur ne le verra pas après le rendu suivant.

EDIT: En général, l'interface utilisateur dans WPF, même lors de la liaison de données, est très sensible. Cependant, il y a des raisons pour lesquelles il peut être lent (jetez un oeil à l'application à l'aide du WPF performance toolkit):

  • Le contrôle spécifique lui-même (ce qui est si lent) peut être trop compliqué/pléthorique. Par exemple, j'avais un contrôle qui chargeait un fichier de style de 400 Ko chaque fois qu'il était créé. Évidemment, cela a pris du temps. Dans mon cas, la solution consistait à charger le fichier de style dans le contrôle parent une fois.
  • Le thread principal (qui est généralement votre thread d'interface utilisateur) effectue trop de traitement à la fois. Vous pouvez bloquer le thread avec un calcul de longue durée, ce qui signifie qu'il n'a aucune chance de mettre à jour l'interface utilisateur. Donc ce calcul devrait être fait dans un thread différent (BackgroundWorker, thread ThreadPool, ...).
  • L'interface utilisateur entière peut être trop compliquée. Vous pouvez avoir un arbre visuel/logique extrêmement profond ou utiliser de grands styles/modèles avec beaucoup de déclencheurs ou d'effets bitmap hérités, etc.
+0

donc votre réponse est qu'il n'y a pas de réponse? – Jordan

+0

J'ai un projet avec près de 1000+ liaisons sur une page qui sont dynamiques w.r.t.curseurs et il est très réactif. – user7116

+0

@Jordan Fondamentalement oui. Comme le rendu est effectué à une priorité inférieure à la liaison de données et à la priorité normale (cela est logique puisque la liaison de données peut entraîner des modifications de rendu), les mises à jour de la liaison de données ne seront pas utiles. avec une réponse lente! *). Vous pourriez vouloir jeter un coup d'oeil avec un profileur, ex. http://windowsclient.net/wpf/perf/wpf-perf-tool.aspx Une autre option pourrait être d'avoir un deuxième fil où vous avez votre (vos) fenêtre (s) "lente (s)". –

4

OK, il existe trois options que vous pouvez utiliser pour rendre l'interface utilisateur réactive :

(1). Utilisez les liaisons asynchrones:

<TextBlock Text="{Binding ViewModelTextProperty, IsAsync=True}"/> 

De cette façon, la valeur de ViewModelTextProperty sera récupéré de manière asynchrone.

(2). Utilisez PriorityBinding - il est similaire à l'option précédente, mais en outre, il vous permet d'afficher quelque chose en liaison principale est l'exécution de manière asynchrone:

<TextBlock> 
    <TextBlock.Text> 
     <PriorityBinding> 
      <Binding Path="ViewModelTextProperty" IsAsync="True"/> 
      <Binding Path="FastViewModelTextProperty" IsAsync="True"/> 
     </PriorityBinding> 
    </TextBlock.Text> 
</TextBlock> 

liaisons lentes sont spécifiées sur le dessus et les rapides dans le buttom. C'est-à-dire, dans cet exemple, la valeur de FastViewModelTextProperty sera affichée en premier et lorsque la valeur de ViewModelTextProperty est prête, elle sera affichée.

(3). Enfin, vous pouvez utiliser la programmation asynchrone habituelle dans votre modèle de vue (appelez les méthodes de manière asynchrone, utilisez les temporisations, etc.). Et chaque fois que vous êtes prêt à afficher des données, mettre à jour l'interface utilisateur (valeurs de consigne des propriétés liées) en utilisant Dispatcher:

private void OnAsyncOperationCompleted() 
{ 
    Application.Current.Dispatcher.BeginInvoke(new Action(() => { 
     // Update the UI 
    })); 
} 
+0

c'est la direction opposée que je veux aller. Je veux que la vue réagisse plus rapidement aux changements dans le modèle de vue. Je ne veux pas seulement que l'interface soit vivante pendant que je fais du traitement. J'ai une barre de progression basée sur le minuteur qui est incroyablement nerveux. Et j'ai un clavier à écran tactile qui met à jour le champ comme des heures (exagération) plus tard que la touche est enfoncée. – Jordan