Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Bild kann nicht gelöscht werden, während es angezeigt wird
ASommer
myCSharp.de - Member



Dabei seit:
Beiträge: 6

Themenstarter:

Bild kann nicht gelöscht werden, während es angezeigt wird

beantworten | zitieren | melden

Hallo,

vielleicht kann mir jemand helfen zu WPF MVVM

Ich habe eine Klasse (Bilder) erstellt, dazu eine ObservableCollection in einem ViewModel. Diese Speichert Informationen zu Bildern die auf dem Laufwerk liegen.

String Pfad {get; set;}
String Bildname {get; set;}
usw.

In der Klasse wird der Pfad zu den Bildern gespeichert z.B. Ablageort = C:// Bilder/meinBild.jpg


Die ObservableCollection wird dann in XAML (View) als Liste angezeigt.
<Image Source="{Binding Klasse.Bild}"


Das klappt auch alles
Die Liste mit den Bildinformationen sicher ich dann in einer xml Datei.

Wenn ich aber nun versuche das Bild zu löschen, dann bekomme ich die Fehlermeldung, dass das Bild noch verwendet wird. Ich bekomme es einfach nicht hin, das Bild als Kopie zu öffnen, damit der Zugriff auf die Bilddatei möglich ist. Der Bildordner soll nicht als Ressource im Projekt eingebunden werden.


Mein Problem ist bei MVVM.... wie kann ich im ViewModel das Bild als Image holen und an die View übergeben?


Danke für eure Hilfe

Gruß
ASommer
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.752

beantworten | zitieren | melden

Das hat mit MVVM nichts zutun, sondern wie Resourcen in .NET verwaltet werden bzw wie Betriebssysteme funktionieren. Das kannst Du auch alles in der Doku nachlesen:
- Image erstellt ein Handle, um auf das Bild zugreifen zu können bzw. die Inhalte zu lesen.
- Durch das Handle (Handles und Objekte - Win32 apps) weiß das Betriebssystem, dass das Bild in Verwendung ist
- Den Löschaufruf verweigert das Betriebssystem, weil darauf zugegriffen wird
- Du erhälst in .NET deswegen eine Fehlermeldung

Willst Du das Bild löschen, während Du es anzeigst, dann musst Du das Bild zuerst in den RAM laden, zB. mit Hilfe eines Memory Streams.


PS: Du suchst nach Hilfe, daher beachte in Zukunft bitte [Hinweis] Wie poste ich richtig?
- Erstell das Thema im richtigen Bereich (Du redest schließlich von WPF; dann erstell doch auch im WPF Bereich das Thema...?)
- Verwende ein Titel, der zum Thema passt, das macht es für alle einfacher und Du bekommst evtl. mehr Hilfe
private Nachricht | Beiträge des Benutzers
ASommer
myCSharp.de - Member



Dabei seit:
Beiträge: 6

Themenstarter:

beantworten | zitieren | melden

Verstanden soweit.

Leider fehlt mir das wissen wie ich das mit dem Memory Stream mache.
Wo mache ich das am besten im View , im ViewModel oder XAML?
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.752

beantworten | zitieren | melden

Dann musst Dir das Wissen aneignen, zB. weil andere Leute schon das Problem hatten :-)
Google Suche nach "c# image memorystream"

Du kannst es alternativ auch direkt als Byte Array lesen, und dann ImageSource nutzen.
Steht alles auch in der Doku. Um das Lesen kommst leider nicht drum herum :-)
Google Suche nach "wpf image byte array"

Die Umsetzung wäre im ViewModel, siehe auch [Artikel] MVVM und DataBinding für die Verantwortlichkeiten.
private Nachricht | Beiträge des Benutzers
ASommer
myCSharp.de - Member



Dabei seit:
Beiträge: 6

Themenstarter:

beantworten | zitieren | melden

Ich habe mir erstmal damit beholfen.
Das Bild wird dann in xml gespeichert und wieder gelesen somit muss ich das Original nicht löschen.
Muss jetzt nur noch schauen, dass ich die Bilder verkleinert bekomme, damit die xml nicht zu groß wird.


System.IO.File.ReadAllBytes(filePath);

Mit dem lesen... konnte ich ein wenig mehr darüber erfahren, aber so richtig schlau bin ich daraus noch nicht geworden.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.752

beantworten | zitieren | melden

XML für Binärdaten? Hört sich nich gerade nach einer schlauen Lösung an.
Willst vielleicht einfach mal erzählen, was Du überhaupt machen willst und was die Anforderungen sind?
private Nachricht | Beiträge des Benutzers
ASommer
myCSharp.de - Member



Dabei seit:
Beiträge: 6

Themenstarter:

beantworten | zitieren | melden

Ganz Trivial eigentlich.


Beispiel: Eine ObservableCollection<Personen>

Diese ObservableCollection will ich als XML auf der Festplatte speichern, damit beim nächsten Programmaufruf die Daten wieder da sind.

Zu jeder Person gibt es ein Bild. Im ersten Ansatz hatte ich einen Ordner angelegt und dort eine Kopie des Bildes gespeichert wenn man eine neues Bild/Person hinzufügt.
Wenn ich aber aus der ObservableCollection den Eintrag lösche... war der Zugriff (von meinem Programm) auf dem Bild noch da, somit konnte ich das Bild nicht löschen.


Mit der jetzigen Methode, habe ich das Bild der Person in der XML der ObservableCollection gespeichert. Somit brauche ich keinen neunen Ordner wo die Bilder rein kommen.

Ob das der richtige weg ist weiß ich nicht... bin Newbie in der Sache was WPF und C# angeht.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.752

beantworten | zitieren | melden

Dann hast Du Dir jetzt quasi mehr Arbeit gemacht und nicht die Ursache sondern nur das Sympton gelöst - aber neue Steine in Weg gelegt.
Lade Deine Bilder in den Speicher und binde den Speicher an Deine View - nicht das Bild direkt.
Bei den Personen speicherst Du nur den Pfad zum Bild ab - mehr nicht. Würde man so in "echten Datenbank" genau so machen, weil Binärdaten in der Masse absolut nichts in relationalen Datenbanken zu suchen haben.

Hättest also mit ~5 Zeilen Code einfach lösen können (via MemoryStream oder Byte-Array, wie oben genannt).
Das wäre auch die technisch bessere Variante gewesen als Binärdaten in einer XML.
private Nachricht | Beiträge des Benutzers
ASommer
myCSharp.de - Member



Dabei seit:
Beiträge: 6

Themenstarter:

beantworten | zitieren | melden

Hallo Abt,

danke für deine Hilfe. Genauso will ich es und wollte ich es auch machen. Aber das Problem war darin, dass ich es nicht hinbekomme das Bild darzustellen.
Bin fleißig dran das Problem zu beheben, aber ein bisschen fehlt mir noch alles zu kapieren.

Zitat
~5 Zeilen Code einfach lösen können (via MemoryStream oder Byte-Array, wie oben genannt).

Hättest du vielleicht ein Beispiel von dem MemoryStream?

Danke für deine Tipps.

Gruß
ASommer
private Nachricht | Beiträge des Benutzers
Caveman
myCSharp.de - Member

Avatar #avatar-3854.jpg


Dabei seit:
Beiträge: 150

beantworten | zitieren | melden

Ein Bild in den Speicher laden


using (MemoryStream ms = new MemoryStream())
using (FileStream file = new FileStream("file.bin", FileMode.Open, FileAccess.Read)) {
   byte[] bytes = new byte[file.Length];
   file.Read(bytes, 0, (int)file.Length);
   ms.Write(bytes, 0, (int)file.Length);
}

Im View Model eine Eigenschaft vom Typ byte[] anlegen


private byte[] userImage;

public byte[] UserImage
   {
       get { return userImage; }
       set
       {
           if (value != userImage)
           {
               userImage = value;
               OnPropertyChanged("UserImage");
           }
       }
   }

Und im Xaml darauf binden

<Image Source="{Binding UserImage}"/>

Alles ungetestet! Das Byte-Array muss noch mit der Eigenschaft UserImage verbunden werden.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.752

beantworten | zitieren | melden

Zitat von ASommer
Hättest du vielleicht ein Beispiel von dem MemoryStream?
Wieso schaust nicht einfach in die Suchtreffer aus meinem ersten Beitrag? Da steht alles mit Erklärung und Co.
Oder einfach in die Dokumentation schauen.

@Caveman das sieht nach .NET 3.5 Code oder früher aus.
Seit .NET 4 kann man einfach CopyTo verwenden


    fileStream.CopyTo(memoryStream);

Den Magic String im Property Event braucht man mittlerweile auch nicht mehr; so ist die potentielle Fehlerquelle auch eliminiert.
private Nachricht | Beiträge des Benutzers
Caveman
myCSharp.de - Member

Avatar #avatar-3854.jpg


Dabei seit:
Beiträge: 150

beantworten | zitieren | melden

Zitat von Abt
@Caveman das sieht nach .NET 3.5 Code oder früher aus.
Seit .NET 4 kann man einfach CopyTo verwenden

Ich habe in dem Fall einfach nur stur gegoogelt und die erstbesten Beispiele von StackOverflow kopiert.
Dass mit CopyTo habe ich gelesen, wollte es aber nicht posten, weil es dann keine 5 Zeilen Code geworden wären

Deswegen hatte ich auch geschrieben, dass ich das selber nicht probiert hatte.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.752

beantworten | zitieren | melden

Zitat von Caveman
weil es dann keine 5 Zeilen Code geworden wären


using... 
using...
{
 CopyTo
}
:-)
private Nachricht | Beiträge des Benutzers