Вопрос

Я создаю приложение wpf, используя MVVM. У меня есть viewModels ленивая загрузка, как показано ниже:

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; }
    }
}

Представление имеет AssignmentViewModels в ListView и заметки в ListBox с табличкой данных.

Когда я отображаю одну из AssignmentViewModels, которая имеет 160 элементов, для загрузки требуется 1000 мс. Я думал, что это из-за того, что свойство Notes извлекается из таблицы базы данных с 1,5 миллионами строк. Я проверил это, и потребовалось всего 60 мс, чтобы заполнить список заметок. Так что я предполагаю, что это привязка данных для загрузки 160 элементов в список. Но это не должно иметь место, потому что listBoxes виртуализируют свой контент (я отследил его и убедился, что элементы находятся в панели стека Virtualization).

Так что я в растерянности, я не знаю, как узнать, что занимает дополнительные 940 мс.

Что я могу сделать, чтобы отследить это? Производительность имеет ключевое значение, и я не знаю, как ее улучшить.

Это было полезно?

Решение

Не зная, на что похож пользовательский интерфейс, существует вероятность того, что что-то из пользовательского интерфейса замедляет его, как большое использование BitmapEffects.

Кроме того, вы можете захотеть переключить свой список на ObservableCollection, как привязка к этому может быть значительно быстрее, чем список .

Есть также несколько хороших профилирования производительности , которые могут помочь вы.

Другие советы

Можем ли мы увидеть ваш XAML?

Если ваш список находится внутри панели стека (или аналогичного элемента управления), список не будет виртуализировать свои записи.

Это будет виртуализировано:

<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>

Это не будет:

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

Внутри стековой панели окно списка будет отображаться на максимальной высоте и зависит от стековой панели для прокрутки. (Нет виртуализации)

Внутри сетки список выводится на высоту строки сетки и использует свой собственный просмотрщик прокрутки. (Виртуализация)

Вы также можете просто установить свойства Height или MaxHeight в списке вместо того, чтобы помещать их в сетку, но если вы используете стековую панель, я подозреваю, что вы хотите какой-то авторазмер.

Обратите внимание, что вы не можете обмануть, поместив панель стека в сетку; ваш список должен быть в состоянии получить максимальную высоту откуда-то.

Вы пробовали тестирование без ленивой загрузки?

Кроме того, насколько сложны ваши шаблоны данных / представления для ваших элементов? Попробуйте запустить тест с простыми представлениями TextBlock, чтобы убедиться, что ваши взгляды не так сложны.

Я бы еще раз взглянул на SQL и убедился, что ваша коллекция заполняется. L2S фактически не будет заполняться, пока вы не перечислите результат.

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
    }
}

ex: Вызовите .ToList () сразу после возврата данных. Вы увидите гораздо больше активности на уровне данных, чего, возможно, не было до вашего бизнеса или уровня пользовательского интерфейса.

Я понял это. У меня был текстовый блок, который нуждался в переносе текста, потому что иногда он был довольно большим. Я явно установил его ширину (чтобы он был перенесен) внутри таблицы данных и по какой-то причине заставил VirtualizingStackPanel внутри ListBox реализовать все элементы в списке. Я переработал его, чтобы поместить его в сетку, как это ..

<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>

Это привело к быстрой загрузке списка. Спасибо за ваши ответы, они привели меня на правильный путь.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top