Обсуждая проблему с сотрудниками WPF на TechEd, я показал сотруднику Microsoft этот вопрос. Он был в замешательстве.
Мы загрузили инструмент, который опрашивает макеты WPF и идентифицировали контейнер как элемент «Панель виртуализации стека» в ListView.
В последующем электронном письме он написал: «Это ошибка VirtualizingStackPanel. Я открыл ошибку по этому поводу. Надеюсь, это можно исправить в будущем выпуске. Обходной путь (с помощью StackPanel) должен подойти на данный момент до тех пор, пока вам не нужен ListView для виртуализации его содержимого.
Ошибка включает в себя шаг в алгоритме Measure VSP, который запоминает самый большой размер из когда-либо обнаруженных и вынуждает все будущие вызовы Measure сообщать о размере, по крайней мере, таком большом. В вашем случае VSP первоначально измеряется до срабатывания любых триггеров, поэтому он вычисляет размер, как если бы все было видно. Когда триггеры запускают и сворачивают кнопки, алгоритм измерения вычисляет правильный (маленький) размер, но затем вынуждает результат снова быть большим. Комментарий говорит о том, что нужно избегать ненужных перекомпоновок при прокрутке, но код работает, даже если прокрутка не происходит. "
Обходной путь заключается в повторном шаблонировании ListView с этим кодом:
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
Это привело к тому, что поведение списка работало должным образом, но у него был недостаток, заключающийся в отсутствии возможностей управления памятью в VirtualizingStackPanel. Для моего использования это было уместно; элементы списка никогда не будут превышать 2000 или около того за один раз.