2010-07-06 7 views
2

J'ai un TextBox qui fait un SelectAll() quand il obtient le focus. Fonctionne très bien. Le problème est que si le contenu ne rentre pas dans la boîte, alors le SelectAll entraîne le défilement du contenu jusqu'à la fin. Je veux qu'il défile vers l'avant à la place - cette boîte est utilisée avec des champs numériques.Comment empêcher le défilement de la boîte d'édition WPF de se terminer sur un SelectAll programmatique?

Ma question est: est-il possible de SelectAll() mais éviter le défilement?

La solution de contournement que j'ai en ce moment est de mettre en file d'attente un ScrollToHome. Je n'apprécie pas trop cela car il provoque parfois une pop comme le texte rend dans une position puis une autre.

public new void SelectAll() 
    { 
     base.SelectAll(); 

     // changing selection does something with a queued scroll request, so have to queue ours in the back. this still may cause a flash 
     // if a render slips through. would like to find a better way to do this. 
     Dispatcher.BeginInvoke(DispatcherPriority.Background, ScrollToHome); 
    } 

Notez que le ScrollToHome doit être mis en attente comme celui-ci ou il obtient « écrasé » en raison d'une autre file d'attente event..I'm deviner un événement changé notify-interne au système de zone de texte. J'ai fouillé dans la source et c'est assez compliqué, j'ai eu du mal à comprendre exactement où il faisait sa demande de défilement.

Donc ce que je suis à la recherche est une des opérations suivantes:

  1. Comment selectall() sans défilement se produisant ou avec elle le défilement vers l'avant.
  2. Comment forcer une mise à jour à l'affichage pour que je ne reçoive pas le popping.

Répondre

3

Enveloppez vos SelectAll() et avec ScrollToHome() appels avec BeginChange() et EndChange(). Cela le sauver de repeindre:

public new void SelectAll() 
{ 
    BeginChange(); 
    SelectAll(); 
    ScrollToHome(); 
    EndChange(); 
} 

Une autre option est de perdre le focus de votre TextBox, puis faire la sélection.

+0

J'ai oublié le début/la fin. Cela l'a corrigé exactement, merci! – scobi

0

J'ai eu exactement le même problème (zone de texte qui sélectionne tout quand il obtient le focus et je veux qu'il fasse défiler au début et non la fin), mais dans silverlight. Il n'y a pas de BeginChange/EndChange ici, donc j'ai trouvé la réponse de Scott Bilas. Cela signifie que je reçois la repeindre, ce qui est frustrant, mais c'est le meilleur que je peux trouver pour le moment. Pour le rendre encore plus hackier, juste un BeginInvoke ne suffit pas, comme le défilement automatique vers le bas est en file d'attente et arrive parfois après l'action BeginInvoke, donc je dois introduire un retard artificiel (spawn dans un nouveau thread et dors pendant 10ms avant le BeginInvoke) pour le rendre plus fiable. Donc, je me suis retrouvé avec ceci:

var scrollViewer = VisualTreeWalker.FindVisualChildren<ScrollViewer>(TextBox) 
    .FirstOrDefault(); 

new Thread(delegate() 
{ 
    Thread.Sleep(10); 
    scrollViewer.Dispatcher.BeginInvoke(() => 
    { 
     scrollViewer.ScrollToLeft(); 
     scrollViewer.ScrollToTop(); 
    }); 
}).Start(); 

j'ai joué avec faire un veilleur de propriété de dépendance pour regarder le HorizontalOffset du ScrollViewer dans la zone de texte, et puis en faisant le BeginInvoke lorsque le HorizontalOffset est devenu non nul, mais cela juste obligé trop de cas spéciaux .. que se passerait-il s'il n'y avait pas assez de texte dans la zone de texte pour provoquer un défilement automatique, de sorte que le paramètre HorizontalOffset restait à 0? Ensuite, une modification de l'utilisateur légitime qui devrait causer le défilement serait ramenée en haut/à gauche. Il s'est juste transformé en un grand trou de lapin donc j'ai dû me contenter de ce terrible bidouillage.

Questions connexes