Domanda

Sto costruendo un'app wpf usando MVVM. Ho viewModels che impiegano il caricamento lento come di seguito:

public class AssignmentsViewModel
{

    List<AssignmentViewModel> _Assignments;
    public List<AssignmentViewModel> Assignments
    {
        get
        {
            if (_Assignments == null)
                _Assignments = new List<AssignmentViewModel>(Data.GetAssignments());
            return _Assignments;
        }
        set { _Assignments = value; }
    }
}
public class AssignmentViewModel
{
    List<NoteViewModel> _Notes;
    public List<NoteViewModel> Notes
    {
        get
        {
            if (_Notes == null)
                _Notes = new List<NoteViewModel>(Data.GetNotes());
            return _Notes;
        }
        set { _Notes = value; }
    }
}

La vista ha AssignmentViewModels in un ListView e le note in un ListBox con un datatemplate.

Quando visualizzo uno dei modelli AssignmentView che ha 160 elementi, sono necessari 1000 ms per caricare. Ho pensato che fosse a causa della proprietà Notes che afferra da una tabella di database con 1,5 milioni di righe. L'ho controllato e ci sono voluti solo 60ms per popolare l'elenco Note. Quindi immagino che sia il databinding di caricare i 160 elementi nella lista. Ma questo non dovrebbe essere il caso perché listBoxes virtualizza il loro contenuto (l'ho cercato e verificato che gli elementi si trovino in un pannello di virtualizzazione).

Quindi sono perplesso, non so come scoprire cosa richiede 940 ms in più.

Cosa posso fare per rintracciarlo? Le prestazioni sono fondamentali e non so come migliorarle.

È stato utile?

Soluzione

Senza sapere com'è l'interfaccia utente, c'è la possibilità che qualcosa dall'interfaccia utente la stia rallentando come un grande uso di BitmapEffects.

Inoltre, potresti voler passare dall'elenco a ObservableCollection, come vincolante per questo può essere significativamente più veloce di un Elenco .

Esistono anche alcuni buoni profiling delle prestazioni che possono aiutare te.

Altri suggerimenti

Potremmo vedere la tua XAML?

Se la casella di riepilogo è all'interno di uno stackpanel (o un controllo simile), la casella di riepilogo non virtualizzerà le voci.

Questo virtualizzerà:

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>

  <Label Grid.Row=0>Your label here</Label>
  <ListBox Grid.Row=1 Your properties here... />

</Grid>

Questo non::

<StackPanel>
  <Label>Your label here</Label>
  <ListBox Your properties here... />
</StackPanel>

All'interno dello stackpanel la casella di riepilogo verrà visualizzata alla sua altezza massima e dipenderà dallo stackpanel per lo scorrimento. (Nessuna virtualizzazione)

All'interno della griglia la casella di riepilogo verrà visualizzata all'altezza della riga della griglia e utilizzerà il proprio visualizzatore di scorrimento. (Virtualizzazione)

Potresti anche semplicemente impostare le proprietà Height o MaxHeight nella casella di riepilogo invece di inserirlo in una griglia, ma se stai usando uno stackpanel sospetto che tu voglia ridimensionare in qualche modo.

Nota che non puoi imbrogliare mettendo lo stackpanel all'interno della griglia; la tua lista deve essere in grado di ricavare un'altezza massima da qualche parte.

Hai provato perf-test senza caricamento lento?

Inoltre, quanto sono complicati i tuoi DataTemplates / Views per i tuoi articoli? Prova a eseguire un test con semplici rappresentazioni di TextBlock per assicurarti che le visualizzazioni non siano complicate.

Vorrei dare un'altra occhiata all'SQL e assicurarmi che la tua raccolta si sta riempiendo. L2S non verrà effettivamente popolato fino a quando non si enumera il risultato.

private IEnumerable<Thing> Method1()
{
    return _db.Things.Where(t => t.ID > 500);
}
private void Method2()
{
    var things = Method1(); // here, 'things' doesn't really contain anything
                            // even though you've already done the db fetch
    foreach (var thing in things) // 'things' gets populated here.
    {
        // do something
    }
}

es: chiama .ToList () immediatamente dopo la restituzione dei dati. Vedrai molte più attività nel livello dati che potrebbero non essersi verificate fino al livello della tua azienda o dell'interfaccia utente.

L'ho capito. Avevo un blocco di testo che aveva bisogno di essere spostato perché a volte è piuttosto grande. Ne ho impostato esplicitamente la larghezza (in modo che si avvolgesse) all'interno del datatemplate e per qualche motivo che fa sì che VirtualizingStackPanel all'interno di ListBox realizzi tutti gli elementi nell'elenco. L'ho rielaborato per adattarlo a una griglia in questo modo ..

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="3*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Grid Grid.Column="0">
       ....
    </Grid>
    <ListBox Grid.Column="1" ItemsSource="{Binding}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" >
       ...//DataTemplate
    </ListBox>
</Grid>

Ciò ha causato il caricamento rapido della casella di riepilogo. Grazie per le tue risposte mi hanno portato sulla strada giusta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top