Перечисление BitmapCreateOptions определяет перечисление BackgroundCreation таким образом:
Вызывает инициализацию BitmapSource, как только он объявлен. Эта опция использует кэш изображений для ранее использованных URI. Если изображение отсутствует в кэше изображений, оно будет загружено и декодировано в отдельном фоновом потоке.
Это заставляет меня думать, что при изменении свойства UriSource и удалении старого изображения фоновый поток, обрабатывающий загрузку растрового изображения, не уведомляется, и этот фоновый поток продолжает загружать изображение. Это может быть сделано, потому что в телефоне реализовано собственное кэширование всех изображений (обратите внимание на наличие элемента «IgnoreImageCache» в перечислении BitmapCreateOptions).
Это, вероятно, виновник, однако другая возможность заключается в том, что виртуализация ListBox на самом деле не происходит. Наиболее частой причиной этого является то, что элементы в списке не определены явно, чтобы иметь одинаковую высоту. Виртуализация в ListBox использует VirtualizingStackPanel под крышками и требует, чтобы каждый элемент был одинаковой высоты. Если какой-либо элемент имеет другую высоту, поведение виртуализации отменяется. Ниже приведен код, который должен помочь вам определить, является ли virt. на самом деле происходит или нет. Еще одна вещь, связанная с виртуализацией, заключается в том, что в настоящее время ваши изображения не имеют заданной высоты, пока данные изображения не будут загружены. Это означает, что до загрузки изображений все изображения имеют высоту 0 пикселей. Если все изображения имеют высоту 0 пикселей, то это означает, что все они «на виду» в соответствии с вирт. логика, все они должны начать загрузку.
В общем, попробуйте следующее:
- Измените CreateOptions на что-то другое (или не устанавливайте его вообще)
- Явно задайте высоту тега изображения внутри списка. (это обязательно)
- Используйте приведенный ниже код, чтобы проверить, является ли вирт. достигается.
Простая структура для хранения данных изображения:
using System.Diagnostics;
public class BoundImage
{
private string imageURL;
public static int TotalImagesRequested = 0;
public BoundImage(string url)
{
imageURL = url;
}
public string ImageURL
{
get
{
TotalImagesRequested++;
// Watch the output window and see if TotalImagesRequested is
// growing to a crazy high amount (if it is it will eventually
// reach the total Count of the _links variable. But your
// app may crash before that happens.
Debug.WriteLine("Images being requested: " + TotalImagesRequested);
return imageURL;
}
}
}
Измененное свойство для раскрытия ссылок:
//inside MainPage.xaml.cs
public void GetImages(object sender, RoutedEventArgs e)
{
(DataContext as ViewModel).GetMeSomeImages();
}
// inside ViewModel.cs
public void GetMeSomeImages()
{
List<string> links = ThisMethodGetsLinks();
Links.Clear();
_links = new ObservableCollection<BoundImage>();
foreach(string link in links)
{
_links.Add(new BoundImage(link));
}
}
ObservableCollection<BoundImage> _links;
public ObservableCollection<BoundImage> Links
{
get
{
if (_links == null)
_links = new ObservableCollection<BoundImage>();
return _links;
}
set
{
_links = value;
}
}
Изменено связывание XAML с крюком для свойства ImageURL объекта BoundImage:
// inside MainPage.xaml
<Button Tap="GetImages">Get Images</Button>
<ListBox ItemSource="{Binding Links}">
<ListBox.ItemTemplate>
<DataTemplate>
<!-- I am not binding to Image's Source directly, because I want to use the bitmap's 'Background creation' option and it's download progress event in the future -->
<Image>
<Image.Source>
<BitmapImage UriSource="{Binding ImageURL}" CreateOptions="BackgroundCreation"/>
</Image.Source>
</Image>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>