2013-04-08 13 views
7

Sto utilizzando gli eventi KeyUp e KeyDown su una finestra WPF.Perché gli eventi KeyUp e KeyDown si rallentano?

Ho anche molte chiamate nell'evento CompositionTarget_Rendering di questa finestra che crea UIElements e le anima. Questo viene fatto dalla classe del motore di seguito:

int _Fps; 
Stopwatch sw = new Stopwatch(); 

void CompositionTarget_Rendering_Stats(object sender, EventArgs e) 
{ 
    _Fps++; 
    var ms = sw.ElapsedMilliseconds; 
    sw.Restart(); 
    engine.Update(ms/1000f); 
    timeFrames.Add(ms); 
} 

ho notato che più degli elementi che ho, il più lento ottenere KeyUp e KeyDown eventi.

Quando ho circa 1000 UIelementi nella finestra principale, , il codice di control_KeyDown e control_KeyUp viene eseguito circa mezzo secondo dopo che ho colpito o rilasciato una chiave.

Questo non mi sorprenderebbe se le animazioni all'interno della finestra fossero troppo lente, ma non è il caso.

  • Il framerate è a circa 55 fps
  • L'animazione rimane lisce
  • I calcoli in caso CompositionTarget_Rendering non dura più di 20 millisecondi.

Sembra che solo il polling dell'evento della tastiera soffra di condizioni pesanti.

La mia domanda è:

  • Qual è la magia dietro la manipolazione della tastiera in WPF: perché è sempre in condizioni di lag pesante mentre non il processo di rendering?
  • Come posso gestire meglio l'input da tastiera ed evitare questo?

EDIT:

ho scritto un campione ispirato da Andy commento. Puoi copiarlo incollandolo nelle finestre principali di una nuova applicazione WPF. Cambia il colore della finestra quando una chiave è verso il basso o verso l'alto e riempie il maggior numero possibile di caselle di testo nell'evento CompositionTarget_Rendering.

public partial class MainWindow : Window 
{ 
    WrapPanel root2; 

    public MainWindow() 
    { 
     InitializeComponent(); 
     root2 = new WrapPanel(); 
     root2.Margin = new Thickness(10); 
     this.Content = root2; 
    } 

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     for (var i = 0; i < 2000; i++) 
      root2.Children.Add(new TextBlock() { Background = Brushes.Yellow }); 

     this.KeyDown += MainWindow_KeyDown; 
     this.KeyUp += MainWindow_KeyUp; 
     CompositionTarget.Rendering += CompositionTarget_Rendering; 
    } 

    void MainWindow_KeyUp(object sender, KeyEventArgs e) 
    { 
     this.Background = Brushes.Red; 
    } 

    void MainWindow_KeyDown(object sender, KeyEventArgs e) 
    { 
     this.Background = Brushes.Green; 
    } 

    void CompositionTarget_Rendering(object sender, EventArgs e) 
    { 
     foreach (var child in root2.Children) 
      ((TextBlock)child).Text = DateTime.Now.Millisecond.ToString(); 
    } 
} 

A seconda delle prestazioni della macchina, modificare 2000 per aumentare il numero di caselle di testo. Ad una certa quantità, vi sono più trigger CompositionTarget_Rendering di KeyUp o KeyDown. È abbastanza visibile quando viene premuto un tasto per vedere il cambiamento di colore del bordo: il tasto è premuto, quindi il Composition_Rendering viene attivato più volte, quindi l'evento keydown viene attivato e il bordo diventa rosso.

+0

Se imposto un nuovo progetto, creo un nuovo modulo e aggiungo un ciclo per creare 50.000 caselle di testo e agganciare l'evento KeyDown delle finestre principali, in realtà non noto alcun ritardo. Sono questi controlli annidati? – Andy

+1

Nessun controllo è nidificato.Vorresti per favore provare a inserire del codice all'interno dell'evento CompositionTarget_Rendering per inserire del testo a caso all'interno del TextBox? Penso che rifletterà le condizioni che ho. 50000 caselle di testo è molto, pensò. – Larry

+0

Mi chiedo se aiutare a mettere i TextBox in un contenitore di virtualizzazione come un ListBox? – Paparazzi

risposta

Problemi correlati