Производительность привязки данных WPF - PullRequest
2 голосов
/ 16 июня 2009

Я создаю приложение 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 с табличкой данных.

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

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

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

Ответы [ 5 ]

3 голосов
/ 16 июня 2009

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

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

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

2 голосов
/ 16 июня 2009

Можем ли мы увидеть ваш 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 в списке вместо того, чтобы помещать их в сетку, но если вы используете стековую панель, я подозреваю, что вы хотите некоторого автоматического изменения размера.

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

0 голосов
/ 17 июня 2009

Я понял это. У меня был текстовый блок, который нуждался в переносе текста, потому что иногда он был довольно большим. Я явно установил его ширину (чтобы он был перенесен) внутри таблицы данных и по какой-то причине заставил 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>

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

0 голосов
/ 16 июня 2009

Я бы еще раз взглянул на 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() сразу после возврата данных. Вы увидите намного больше активности на уровне данных, чего, возможно, не было до вашего бизнеса или уровня пользовательского интерфейса.

0 голосов
/ 16 июня 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...