Окно списка с более чем 100 элементами аварийно завершает работу

Я работаю над приложением для Windows Phone 8.

У меня есть список с более чем 200 элементами для отображения.

<DataTemplate x:Key="DataTemplate1">
            <Grid VerticalAlignment="Center" HorizontalAlignment="Center">
                <Grid.RowDefinitions>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <Border Grid.Row="0" Background="White" Height="400" Width="400" CornerRadius="30,30,30,30">
                </Border>
                <Grid Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Top">
                    <TextBlock HorizontalAlignment="Center" 
                               VerticalAlignment="Center"
                               Margin="5,20,5,5"
                               Foreground="#000000"
                               Text="{Binding Title}"/>
                </Grid>

            </Grid>
        </DataTemplate>

Но он вылетает, я отлаживал его до 100 элементов, он работает, но после этого он вылетает.

В методе PhoneApplicationPage_Loaded у меня есть

private void PhoneApplicationPage_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
myList.Add(new MyObject("A","A value"));
            myList.Add(new MyObject("B", "B value"));
            myList.Add(new MyObject("C", "C value"));

and so on... 200 items

ListBoxItems.ItemsSource = myList;
}

Как я могу это исправить ?

Обновление:

<ItemsPanelTemplate x:Key="ItemsPanelTemplate">
            <local:CollectionFlowPanel ItemHeight="400" 
                                       ItemWidth="400"
                                       FocusedItemOffset="120" 
                                       UnfocusedItemOffset="20" 
                                       ItemVisibility="5">
                <VirtualizingStackPanel />
            </local:CollectionFlowPanel>
        </ItemsPanelTemplate>
    </phone:PhoneApplicationPage.Resources>

    <Grid x:Name="LayoutRoot" Background="#000000">
        <local:CollectionFlow x:Name="ListBoxItems"
                              ItemTemplate="{StaticResource DataTemplate}" 
                              ItemsPanel="{StaticResource ItemsPanelTemplate}"/>
    </Grid>

person Goofy    schedule 11.06.2014    source источник
comment
Какую ошибку показывает сбой?   -  person Nick    schedule 11.06.2014
comment
@Николас В. иногда показывает Out of Memory error   -  person Goofy    schedule 11.06.2014


Ответы (4)


Убедитесь, что у вас есть VirtualizingStackPanel внутри ItemsPanelTemplate вашего списка, см. этот ответ для получения дополнительной информации.

Вот XAML, который вам, вероятно, понадобится для вашего ListBox:

<ListBox.ItemsPanel>
    <ItemsPanelTemplate>
        <VirtualizingStackPanel />
    </ItemsPanelTemplate>
</ListBox.ItemsPanel>
person Soonts    schedule 11.06.2014
comment
но как это влияет на сбой приложения для 200+ элементов? - person Goofy; 11.06.2014
comment
Элементы GUI не бесплатны. Они поддерживаются памятью текстур на графическом процессоре и поэтому довольно дороги. Система Qualcomm на чипе внутри устройства Windows Phone не имеет ни выделенного чипа графического процессора (он интегрирован), ни выделенной видеопамяти (системная оперативная память используется как ЦП, ГП и DSP). Я подозреваю, что с вашими 200 элементами по 400 пикселей у вас заканчивается системная память из-за того, что графический процессор хочет выделить слишком много текстур для ваших элементов графического интерфейса. При использовании VirtualizingStackPanel создается всего несколько визуальных элементов, которые повторно используются для отображения различных элементов при прокрутке списка. - person Soonts; 11.06.2014
comment
хорошо, я не знал об этом, не могли бы вы помочь мне, где мне нужно добавить это в моем случае? а также я сделал еще одну вещь, если я установил ширину и высоту границы на 200, она отображается без ошибок, но если ее 400, это дает мне OOM. Почему так? любая идея? - person Goofy; 11.06.2014
comment
При необходимости я могу отправить вам весь POC, который у меня есть для вас? мне послать тебя? - person Goofy; 11.06.2014
comment
«куда мне нужно добавить это в моем случае» — см. обновление. Почему так? — потому что объем оперативной памяти пропорционален Ширине*Высоте текстуры. Когда вы увеличиваете общую площадь ваших элементов, вам нужно больше памяти для текстур. - person Soonts; 11.06.2014
comment
выдает ошибку Cannot explicitly modify Children collection of Panel used as ItemsPanel for ItemsControl. ItemsControl generates child elements for Panel. - person Goofy; 11.06.2014
comment
Пожалуйста, смотрите также мой РЕДАКТИРОВАТЬ - person Goofy; 11.06.2014
comment
У вас не может быть и вашей пользовательской локальной панели: CollectionFlowPanel, и VirtualizingStackPanel в качестве панели элементов. Чтобы использовать виртуализацию, замените панель CollectionFlowPanel на предоставленную системой VirtualizingStackPanel. - person Soonts; 11.06.2014
comment
@Soonts здесь Проблема с виртуализацией не внутри списка, а снаружи. Я попробовал ваше решение, внедрив виртуализацию StackPanel, результат тот же. Я думаю, что ListBox находится в элементе управления canvas/stackpanel, и высота ширины не определена для списка, который вызывает проблему. - person Muhammad Saifullah; 11.06.2014
comment
@MuhammadSaifullah, пожалуйста, перезагрузите вопрос: OP опубликовал XAML с некоторой пользовательской панелью CollectionFlowPanel, которая явно не поддерживает виртуализацию (панели виртуализации трудно реализовать правильно, например, предоставленная MS VirtualizingStackPanel содержит более 2000 строк кода C#). - person Soonts; 11.06.2014

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

Использование виртуализации со списком или сеткой

Не видя всего вашего кода xaml, я не могу предложить точный ответ, но я предполагаю, что вы в xaml ListBox помещены внутри элемента управления canvas/StackPanel или scrollviewer.

Когда размер области просмотра ItemsControl не ограничен, элемент управления не выполняет виртуализацию. Вместо этого он создает контейнер для каждого элемента в своей коллекции. Некоторыми распространенными контейнерами, не ограничивающими размер области просмотра, являются Canvas, StackPanel и ScrollViewer. Вы можете включить виртуализацию в этой ситуации, задав размер ItemsControl напрямую, вместо того, чтобы позволить его размеру определяться его родительским контейнером. Здесь мы устанавливаем высоту и ширину в GridView. Это ограничивает размер области просмотра, а элементы за пределами области просмотра виртуализируются.

Ниже приведены 2 сценария, один из которых выдаст исключение из памяти, а другой будет работать нормально (используйте тот же код и протестируйте его).

<сильный>1. ListBox на холсте

 <Canvas .....
    <ListBox Name="ListBoxItems".....
    </ListBox>
 </Canvas>

Вышеприведенный код выдаст исключение из памяти, так как область просмотра элемента управления элементами не определена (если вы все еще хотите использовать Canvas, тогда укажите ширину/высоту, если ListBox в этом случае определен порт элемента управления элементами и будет применена виртулизация )

<сильный>2. Список в сетке

  <Grid .....
    <ListBox Name="ListBoxItems".....
    </ListBox>
 </Grid>

Приведенный выше код не будет выдавать исключение из памяти, поскольку виртуализация применяется к списку.

Надеюсь, это поможет

person Muhammad Saifullah    schedule 11.06.2014
comment
Поделюсь ли я своим проектом? Пожалуйста, дайте мне ваш почтовый идентификатор - person Goofy; 11.06.2014
comment
Я отправил его вам, не могли бы вы пригласить меня в какой-нибудь чат, чтобы я мог объяснить вам - person Goofy; 11.06.2014
comment
пожалуйста, проверьте это, я буду ждать вашего ответа - person Goofy; 12.06.2014
comment
Вы нашли какое-либо решение для этого, почему это происходит? - person Goofy; 12.06.2014
comment
Я проверил ваш код.... вы используете настраиваемую панель (а не элемент управления списком, который виртуализируется по умолчанию. Наследуйте класс CollectionFlowPanel с помощью VirtualizingPanel, а не просто панель, чтобы получить преимущества виртуализации. Я унаследовал VirtualizingPanel и загрузил 5000 записей , Теперь исключение не thorws, но я не вижу элементы на главном экране.Вы можете проверить свой код в этих строках. - person Muhammad Saifullah; 12.06.2014
comment
да, у меня есть класс Inherited CollectionFlowPanel с VirtualizingPanel, а не просто панель, но элементы не отображаются, есть идеи, почему? - person Goofy; 12.06.2014
comment
следуйте этой серии сообщений в блоге для реализации VirtualiingPanel. это поможет. blogs.msdn.com/b/dancre/archive/ 13/02/2006/531550.aspx - person Muhammad Saifullah; 12.06.2014
comment
я не понимаю, какие изменения мне нужно внести, можете ли вы указать мне некоторые вещи? - person Goofy; 12.06.2014

Насколько велик ваш объект? Если ваш объект слишком велик, вы не сможете загрузить их все сразу.

person LaCartouche    schedule 11.06.2014
comment
в нем более 200 элементов, это из-за ширины и высоты границы? потому что я уменьшил его с 400 до 200, он отображается, но я хочу, чтобы было 400 - person Goofy; 11.06.2014
comment
Я имел в виду, сколько памяти занимает объект типа MyObject? Это примерно сумма того, из чего сделан ваш объект. Например, если ваш объект содержит 4 целых числа, объем памяти, который будет потреблять ваш объект, в четыре раза превышает размер целого числа. Если ваш объект содержит элементы мультимедиа, такие как изображения видео, он может потреблять много памяти, и поэтому у вас будет это исключение OutOfMemoryException. - person LaCartouche; 11.06.2014

Вы пробовали использовать цикл for?

public List<Fellow> fellowList { get; set; }

private void PhoneApplicationPage_Loaded(object sender, System.Windows.RoutedEventArgs e)
{

fellowList = new List<Fellow>();

for (int i = 0; i < 2; i++)
{
    Fellow fellow = new Fellow();
    fellow.x = "B" + i;
    fellow.value = "B Value" + i;
    fellowList.Add(fellow);
}
this.DataContext = this;

ListBoxItems.ItemsSource = fellowList;    

}

public class Fellow
{
public string x { get; set; }
public string value { get; set; }
}

Надеюсь, это поможет... измените модель представления по вашему желанию.

person Kulasangar    schedule 11.06.2014