2014-12-08 6 views
9

Ich implementiere eine Liste, die leicht 10.000 kleine Bilder enthalten könnte. Der aktuelle Anwendungsfall zeigt eine Liste von Miniaturansichten eines Videos, so dass Sie durch ein Video Bild für Bild blättern können. Ich habe alle zwei Drittelsekunden im Video ein Miniaturbild des Videos in die Liste eingefügt. Ich muss sehr lange Videos (z. B. 1-Stunden-Video) unterstützen.Direkte Datenvirtualisierung für ListView unter Windows Runtime

So Virtualisierungsmöglichkeiten:

http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh780657.aspx

Ich habe versucht, „Incremental Datenvirtualisierung“ und verbraucht zu viel Speicher für mich, weil die Bilder nur über Ströme bezeichnet werden kann, und ich würde am Ende 10.000 Öffnung Ströme. Dies würde eine Windows Phone-Anwendung wegen nicht genügend Arbeitsspeicher zum Absturz bringen.

Jetzt möchte ich "Random Access Datenvirtualisierung" versuchen. Ich sehe, wie die Schnittstellen IObservableVector<object>, INotifyCollectionChanged implementieren (ja <object> b/c <T> funktioniert nicht). Der schwierige Teil ist, wie ich Bilder entsorgen und Bilder laden kann. Das Laden von Bildern ist eine Async-Methode.

Darüber hinaus sollte diese Lösung Platzhalter enthalten, genau wie das MSFT-Dokument sagt "Ein Beispiel für diese Art der Datenvirtualisierung wird häufig in Fotoanzeige-Apps gesehen. Anstatt den Benutzer warten zu lassen, alle Fotos in einem Album herunterzuladen Die App zeigt Platzhalterbilder an.Während jedes Bild abgerufen wird, ersetzt die App das Platzhalterelement fürdas Bild durch ein Rendering des tatsächlichen Fotos.Während alle Bilder noch nicht heruntergeladen und angezeigt wurden, kann der Benutzer trotzdem schwenken und mit dem Bild interagieren Sammlung."

Wenn Sie das MSFT-Beispiel für Platzhalter betrachten, scheint die Verwendung von "ContainerContentChanging" ein wichtiger Pfad zu sein. Ich vermute hier, dass es eine Möglichkeit gibt, das Bild innerhalb dieses Ereignisses zu entsorgen und auch das Laden eines Bildes zu starten. https://code.msdn.microsoft.com/windowsapps/ListViewSimple-d5fc27dd

Boiling dies auf eine Frage nach unten - Wo ist es möglich, den Bildstrom zu verfügen und die Last eines Bildes für eine Direktzugriffs Virtualisierung Liste starten? Dies ist ein sehr häufiges Szenario in Foto-Apps und ist sehr einfach in iOS zu tun, aber es scheint noch niemand es unter Windows-Laufzeitumgebung getan hat.

Antwort

0

Sie müssen die Implementierung von VirtualizingCollection anpassen, überprüfen Sie bitte den folgenden Artikel http://www.codeproject.com/Articles/34405/WPF-Data-Virtualization.

Ich schrieb eine Beispielanwendung mit einer Anpassung von VirtualizingCollection für Windows Phone 8.1 Runtime App.

public class ThumbnailItem 
{ 
    public Uri ImageUri { get; set; } 
} 

Schreiben Sie später den ThumbnailItem-Anbieter.

public class ThumbnailProvider : IItemsProvider<ThumbnailItem> 
{ 
    private readonly int _itemsCount; 

    public ThumbnailProvider(int itemsCount) 
    { 
     _itemsCount = itemsCount; 
    } 

    public int FetchCount() 
    { 
     return _itemsCount; 
    } 

    public IList<ThumbnailItem> FetchRange(int startIndex, int count) 
    { 
     var items = new List<ThumbnailItem>(); 
     while (count-- > 0) 
     { 
      items.Add(new ThumbnailItem() 
      { 
       ImageUri = new Uri("ms-appx:///Assets/Square71x71Logo.scale-240.png") 
      }); 
     } 
     return items; 
    } 
} 

Dann in Ihrem Ansichtsmodell, müssen Sie eine IList Eigenschaft erstellen und den Wert eine Implementierung von VirtualizingCollection verwenden. Ich schlage vor, dass Sie AsyncVirtualizingCollection verwenden.

Items = new AsyncVirtualizingCollection<ThumbnailItem>(new ThumbnailProvider(1000000), 100); 

schließlich die Ansicht müssen Sie die Datacontext-Objekt festgelegt eine Instanz Ihrer Ansichtsmodell und Ihre Listview sollte ähnlich aussehen mit auf:

<ListView 
    ItemsSource="{Binding Items,Mode=OneWay}" 
    VirtualizingStackPanel.VirtualizationMode="Recycling"> 
<ListView.ItemsPanel> 
    <ItemsPanelTemplate> 
     <WrapGrid Orientation="Horizontal"/> 
    </ItemsPanelTemplate> 
</ListView.ItemsPanel> 

<ListView.ItemTemplate> 
    <DataTemplate> 
     <Grid Margin="0 0 20 20"> 
      <Image Source="{Binding ImageUri,Mode=OneTime}" 
        Width="72" Height="72"/> 
     </Grid> 
    </DataTemplate> 
</ListView.ItemTemplate> 

Natürlich die Logik des Provider muss entsprechend Ihren Anforderungen geändert werden, der Code, den ich geschrieben habe, ist nur ein Beispiel.

Bitte markieren Sie es als Antwort, wenn Ihnen geholfen hat.

Mit freundlichen Grüßen, Denys

EDIT Freund @Quincy erzielte ich ein einfaches Beispiel, können Sie es anpassen können. Vielleicht enthält die ThumbnailItem-Klasse für Ihre Anwendung die Filename-Eigenschaft, die den IsolateStorageFile-Dateinamen angibt. In diesem Fall müssen Sie eine Bindung mit dem Converter erstellen. Daher müssen Sie ein IValueConverter-Objekt implementieren, um mithilfe von IsolateStorageFile eine BitmapImage-Instanz zu erstellen.

BitmapBild image = new BitmapImage(); image.SetSource (Quelldatei); Rückbild;

Über das Schließen von Bildern hat die VirtualizingCollection standardmäßig eine Seitengröße von 100 definiert. Ihre IsolateStorageFiles werden einmal verwendet, um die BitmapImage in Ihrem IValueConverter-Objekt zu erstellen. Später wird die VirtualizingCollection alte Seiten löschen, wenn sie nicht verwendet werden (nicht angezeigt, überprüfen Sie die Implementierung von VirtualizingCollection), und schließlich schließt der GC & die BitmapImage entsorgen.

Portieren von VirtualizingCollection ist einfach, ich erinnere mich, ich habe gerade Änderungen an AsyncVirtualizingCollection-Klasse. Meine Lösung war einfach:

Ersetzen Sie ThreadPool.QueueUserWorkItem für ThreadPool.RunAsync.

Ersetzen Trace für Debug (nur Debug-Nachrichten, nicht wirklich wichtig).

SynchronizationContext Methoden-Aufruf Ersetzen durch Verwendung von:

(für Windows phone app) CoreApplication.MainView.CoreWindow.Dispatcher.

(für Windows app) CoreApplication.MainView.Dispatcher.

Ich hoffe, es hilft Ihnen.

+0

In diesem Ihr Laden nicht das Bild selbst, was ich tun muss. Sie verwenden nur einen URI. Ich muss einen Stream öffnen und schließen Sie schließlich – Quincy

+0

Ist nicht alle dieser Code von WPF abhängig? AsyncVirtualizingCollection ist in Winrt nicht verfügbar – Quincy

+0

@Quincy Ich habe meine Antwort bearbeitet. Bitte überprüfen Sie es noch einmal. – dbvega