2013-10-28 19 views
15

ho un piuttosto semplice interfaccia utente calendario scorrevole:sporchi Rect raggruppamento

enter image description here

Ma di volta in volta lampeggia di calendario durante lo scorrimento. Ho guardato WPF Performance Suite e notato che c'è una notevole quantità di sporchi Rect (circa 400):

enter image description here

La marcatura del calendario è ItemsControl che lega giorni (solo giorni visibili sono vincolati). Sembra che WPF si ridisegna giorno dopo giorno (ecco perché ci sono così tanti recessi sporchi per un'interfaccia utente così semplice). Ho pensato che ci fosse un modo per dire a WPF di non ridisegnare molti piccoli rettangoli ma ridisegnare l'intero ItemsControl in una volta (simile a quello che ha fatto Double Buffering nei bei giorni di WinForms).

P. S. WritableBitmap risolve il problema, ma spero che ci sia un modo migliore

Update. Ecco come Calendar appare se posso passare l'opzione "Mostra dirty-regione aggiornamento overlay" a:

enter image description here

Così WPF trova correttamente la regione sporca. La domanda è: perché decide di usare così tante recinzioni per ridisegnarlo. La mia ipotesi è che ciò avvenga a causa dello spazio tra i giorni (uno o due pixel di bianco), che è lo stesso durante lo scorrimento.

Update 2.

Ecco il markup del Calendario:

<ItemsControl Panel.ZIndex="1" Grid.Column="1" 
     ItemsSource="{Binding Days}" 
     VerticalAlignment="Center" 
     HorizontalAlignment="Stretch"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <StackPanel Orientation="Horizontal"/> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <Border Margin="1,0,1,0" Padding="0,0,3,0" 
        CornerRadius="1" Width="28" Height="28" 
        VerticalAlignment="Top"> 
       <Border.Background> 
        <MultiBinding Converter="{StaticResource DayOfWeekToColorConverter}"> 
         <Binding Path="IsWeekend"/> 
        </MultiBinding> 
       </Border.Background> 
       <StackPanel> 
        <TextBlock Style="{StaticResource TextStyle}" 
          HorizontalAlignment="Center" 
          VerticalAlignment="Center"/> 
        <Label Style="{StaticResource LabelStyle}" 
          Content="{Binding Date.Day}" 
          HorizontalAlignment="Center" 
          VerticalAlignment="Center"/> 
       </StackPanel> 
      </Border> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 
+0

Hai provato a utilizzare ScrollViewer.CanContentScroll = true in modo da scorrere solo interi giorni? Probabilmente non ha senso scorrere mezza giornata comunque. –

+0

@SoMoS, ScrollViewer non è utilizzato qui per tutto – SiberianGuy

+2

prova utilizzando "Mostra overlay aggiornamento area sporca" e "Disegna rendering software con tinta viola" ti mostrerà la parte ridisegnata della tua app. pubblicare il tuo codice potrebbe probabilmente aiutare a diagnosticare il problema. – makc

risposta

1

avrei aggiunto alla lista di commento, ma non ho abbastanza reputazione per farlo. Un altro possibile motivo per cui si può vedere il lampeggiamento è dovuto a un rallentamento delle prestazioni dell'interfaccia utente causato da un GC. A seconda di come funziona il tuo codice (solo una parte di esso viene pubblicata) potresti creare e rendere orfani molti oggetti che potrebbero causare un GC e potenzialmente causare un leggero rallentamento nell'interfaccia utente. Dovresti essere in grado di vedere se questo è il caso eseguendo perfmon e vedendo se un GC viene attivato ogni volta che l'interfaccia utente lampeggia.

Ho pensato di menzionare questa possibilità anche perché non sembra essere stata considerata ed è qualcosa che può essere testata eseguendo una traccia di chiamate GC mentre l'applicazione è in esecuzione.

1

Non è una risposta, ma è un suggerimento. Ho pensato che potrebbe essere come il xaml all'interno verrà ripetuto tante volte quanti sono gli elementi nella collezione giorni, migliora il rendering se abbiamo la codifica il più minimale possibile.

  1. stili muoversi per Border a risorsa statica BorderStyle
  2. Change Label a TextBlock (Label ha fatto un po 'di pre-elaborazione divertente.es: Rimuovere _ underscore)
  3. Come solo una proprietà è destinata, siamo in grado di estrarre MultiBinding e mettere vincolante
  4. Hai usato un convertitore per il bordo Sfondo semplice. È possibile creare una proprietà in Data che restituisce il colore in base a WeekDay.

     <DataTemplate> 
          <Border Style="{StaticResource BorderStyle}" Background="{Binding Date.DayBackgroundColor}"> 
           <StackPanel> 
            <TextBlock Style="{StaticResource TextStyle}"/> 
            <TextBlock Style="{StaticResource LabelStyle}" Text="{Binding Date.Day}" /> 
           </StackPanel> 
          </Border> 
         </DataTemplate> 
    

Come quando si modifica una query SQL leggermente le modifiche del piano di query e l'ottimizzazione si verifica, questi cambiamenti possono migliorare programma di rendering di WPF :)

1

Ecco la causa di ridisegnare potrebbe essere dovuto alla proprietà indesiderabile notifica modificata sparata dal codice per la raccolta giorni. Ciò potrebbe causare il riavvolgimento dell'intera lista con conseguente lampeggiamento.

Provare a utilizzare visual studio profiler per restringere la causa e quindi risolverlo. Profiler è disponibile nelle versioni premium e ultimate di VS studio.