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.
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
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
Mi chiedo se aiutare a mettere i TextBox in un contenitore di virtualizzazione come un ListBox? – Paparazzi