Laden...

Universal App: Bitmap in Gridview binden ohne Referenz auf physische Datei

Erstellt von ChristophF vor 8 Jahren Letzter Beitrag vor 8 Jahren 1.236 Views
C
ChristophF Themenstarter:in
12 Beiträge seit 2014
vor 8 Jahren
Universal App: Bitmap in Gridview binden ohne Referenz auf physische Datei

Hallo,

die genaue Bezeichnung des Themas fällt mir schwer. Anbei deshalb eine kurze Erklärung des Sachverhaltes

Vorhaben
Ich habe ein Gridview mit einem gebunden Template, das ein <Image> enthält. An das Gridview binde ich eine Liste von Objekten, woraufhin die einzelnen Einträge angezeigt werden (unter anderem auch das BitMap). -> Das funktioniert soweit auch.

public string ThumbnailPath
{
   get{
      return "ms-appdata:///local/thumbnails/" + this._id.toString() + "_thumb_0.png");
   }
}

Nun habe ich die App nach hinten erweitert und möchte die Bilder bei einigen Elementen tauschen. Dazu suche ich mir die Quelle (in dem Fall eine PDF aus der ich das Bild rendere) und schreibe das Bild entsprechend auf dem DAtenträger an die passende Position. Es ergeben sich zwei mögliche Fälle

Fallunterscheidung
Möglichkeit 1 - Es existiert zu der PDF-Datei noch kein Bild. Die PDF wird geöffnet, dass Bild gerendert und anschließend im Verzeichnis gespeichert -> funktioniert

Möglichkeit 2 - Es existiert bereits ein Bild zur PDF, die PDF wird geöffnet, das Bild gerendert und beim Speichern erhalte ich eine "Unauthorized Access"-Exception.

Meine Vermutung
Wenn das Bitmap-Image in der Gridview angezeigt wird, entsteht eine Referenz auf die Datei, die mir nach hinten raus sagt, dass die DAtei nciht überschrieben (auch nicht gelöscht) werden kann.

Lösungsansatz
a) Ich habe versucht alle gebundenen Listen zu nullen bzw. auf eine leere Liste zurück zu setzen...Problem besteht weiterhin.

b) Ich habe versucht das Bild in ein IRandomAccessStream zu laden, um daraus ein Bitmap abzuleiten...der Code läuft durch, aber ich erhalte keine Anzeige der Bilder mehr

public string ThumbnailPath
{
   get{
      return this.CreateBitapFromFile();
   }
}


public async Task<BitmapImage> CreateBitmapFromFile()
{
   BitmapImage image = new BitmapImage();
   StorageFolder thumbsFolder = await ApplicationData.Current.LocalFolder.getFolderAsync("Thumbnails");
   StorageFile file = await thumbsFolder.getFileAsync(this._id.toString() + "_thumb_0.png");
   using(IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read))
   {
      await image.SetSourceAsync(stream);
   }

   return image;
}


Hat jemand von euch eine Idee, wie ich die Bilder an das Gridview binden kann, ohne eine Referenz auf die Datei zu halten? Ich möchte erreichen, dass ich über die App die Bilder tauschen kann.

Vielen Dank für jede Art von Hilfe.

742 Beiträge seit 2005
vor 8 Jahren

Da du den Stream ja freigibst sollte das doch eigentlich passen. Falls du dir unsicher bist, kannst du die Datei ja in einen MemoryStream schreiben und das mal testen.

C
ChristophF Themenstarter:in
12 Beiträge seit 2014
vor 8 Jahren

Hallo und schon einmal Danke für deine Antwort.

Der Code läuft durch, wirft auch keine fehler...aber die variante mit dem IRandomAccessStream liefert mir kein Bild im Gridview. Das Image-Element bleibt leer, vergesse ich an der Stelle etwas oder muss ich auf etwas bestimmtes achten?

S
248 Beiträge seit 2008
vor 8 Jahren

Hallo ChristophF,

ich würde die Datei in einen MemoryStream kopieren und diesen zum Laden verwenden, da die Datei dann nicht geöffnet bleibt.
Am einfachsten ist es die Datei als Stream zu öffnen und mit CopyTo in den MemoryStream zu kopieren.
Danach die Position des MemoryStreams wieder auf 0 setzen und dann zum Laden des Bildes vewenden (den danach FileStream natürlich mit Close oder Dispose schließen).

Grüße
spooky

C
ChristophF Themenstarter:in
12 Beiträge seit 2014
vor 8 Jahren

Hallo,

laut Debugger komme ich entsprechend oft in die Methode zum Erstellen des Images aus dem IRandomAccessStream (ich habe 7 Bilder im Ordner, 7 mal springt er rein).

Kann es sein, dass etwas mit der Datenbindung zum Image-Element nicht Stimmt?

<Image Source="{Binding Path=ThumbnailPath, Mode=TwoWay, UpdateSourceTrigger=OnPropertyChanged" Strech="Uniform" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />

Die Methoden im hintergrund bleiben die selben, wie schon oben genannt. Ich scheine gerade wirklich auf dem Schlauch zu stehen.

Danke schon im Voraus.

742 Beiträge seit 2005
vor 8 Jahren

Also oben in dem Beispiel stimmt was nicht mit dem async und await.

was für mich funktioniert hat:


public sealed class NodeIconBitmapConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            INodeIcon icon = (INodeIcon)value;

            BitmapImage bitmapImage = new BitmapImage();

            icon.OpenAsStreamAsync().ContinueWith(stream =>
            {
                if (stream.Result != null)
                {
                    CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
                        CoreDispatcherPriority.Normal,
                        () =>
                        {
                            bitmapImage.SetSourceAsync(stream.Result.AsRandomAccessStream()).Forget();
                        }).Forget();
                }
            });

            return bitmapImage;
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotSupportedException();
        }
    }

C
ChristophF Themenstarter:in
12 Beiträge seit 2014
vor 8 Jahren

Hallo,

ich hab das Beispiel am Wochenende noch einmal getestet...verstehe aber nicht so richtig die Zusammenhänge in deinem Converter. Besteht die Möglichkeit, dass du das Binding im XAML noch mit auflistest und gegebenenfalls 2-3 Sätze zum Verständnis?

Vielen Dank!