Image in Datagridview - Pfad für Image aus Dataset

  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von GuentherA.

    Image in Datagridview - Pfad für Image aus Dataset

    Hallo zusammen,

    ich habe ein recht lästiges Problem mit einer ImageColumn in einem Datagridview.

    Das Dgv bekommt die Daten von einer Bindingsource (gebunden an ein typisiertes DataSet). Durch den angewählten Filter wird im dgv nur eine Spalte angezeigt. So weit so gut. In der Datatable gibt es eine weitere Spalte namens ImagePath, in der befindet sich der Pfad zu einem lokal abgelegtem Bild. Dieses möchte ich jetzt in der Ersten Spalte im DGV darstellen.

    Dafür habe ich im Code, nachdem das dgv gefüllt wurde, eine ImageColumn an Index 0 hinzugefügt. Anschließend laufe ich alle Zeilen des dgv durch und über die Position in der BindingSource erhalte ich den jeweiligen Pfad des Bildes. Klappt auch.

    Nun teile ich das neu erstellte Bitmap der Zelle zu. Das klappt eigentlich auch, also im Debug sehe ich, das die Zelle den dementsprechenden Inhalt "Image" hat. Das würde passen. Angezeigt bekomme ich aber leider nur das Fehlerbiild (rotes x) vom dgv.

    Hier mal der Code mit dem ich das dgv befülle:

    VB.NET-Quellcode

    1. Public Sub New(ShowPalette As cls_Palette, img As Image, AsReadOnly As Boolean)
    2. Me.New
    3. _isStarting = True
    4. _Palette = ShowPalette
    5. Me.BackgroundImage = img
    6. Me.BackgroundImageLayout = Windows.Forms.ImageLayout.Zoom
    7. txt_Laenge.Text = ShowPalette.Laenge.ToString("F2")
    8. txt_Breite.Text = ShowPalette.Breite.ToString("F2")
    9. txt_Hoehe.Text = ShowPalette.Hoehe.ToString("F2")
    10. txt_MaxLast.Text = ShowPalette.MaxLast.ToString("F2")
    11. ChangeInputState(AsReadOnly)
    12. 'DataBinding
    13. _BS = New Windows.Forms.BindingSource(Ronden_DB.Ronden_DS, Ronden_DB.Ronden_DS.Ronden_Table.TableName)
    14. Dim Filterstring As String
    15. Filterstring = String.Format("ID_Vorzugspalette = '{0}'", _Palette.VorlagenID.ToString) '"ID_Vorzugspalette='" & _Palette.VorlagenID.ToString & "'"
    16. _BS.Filter = Filterstring
    17. dgvRonden.DataSource = _BS
    18. For Each col As Windows.Forms.DataGridViewColumn In dgvRonden.Columns
    19. If Not col.HeaderText = "GeometrieFileNameEinfach" Then
    20. col.Visible = False
    21. Else
    22. col.HeaderText = "Ronden Bezeichnung"
    23. End If
    24. Next
    25. Dim dgcs As New Windows.Forms.DataGridViewCellStyle
    26. Dim dgc As New Windows.Forms.DataGridViewImageColumn(False)
    27. dgcs.BackColor = My.Settings.AMABackColor
    28. dgcs.ForeColor = My.Settings.AMAForeColor
    29. dgvRonden.Columns.Insert(0, dgc)
    30. Dim i As Integer
    31. For i = 0 To dgvRonden.Rows.Count - 1
    32. Dim rT As DS_Ronden.Ronden_TableRow = TryCast(TryCast(_BS(i), System.Data.DataRowView).Row, DS_Ronden.Ronden_TableRow)
    33. Dim bild As Image
    34. Using s As System.IO.FileStream = New IO.FileStream(rT.ImagePath, IO.FileMode.Open)
    35. bild = New Bitmap(s)
    36. PictureBox1.Image=bild '--> NUR FÜR TESTZWECKE UM ZU SEHEN, DASS DAS LADEN DES BILDES FUNKTIONIERT
    37. dgvRonden.Rows(i).Cells.Item(0).Value = bild ' My.Resources.EURO_PaletteGrau ' = RondenImage
    38. End Using
    39. dgvRonden.UpdateCellValue(i, 0)
    40. Next
    41. dgvRonden.ClearSelection()
    42. _isStarting = False
    43. End Sub


    Und das Ergebnis:


    Hat von Euch jemand vielleicht einen guten Tip für mich? Ich verstehe einfach nicht, wesshalb mir das Bild in der zeile des Datagridviews nicht angezeigt wird, wenn ich das Bild aber einfach einer PictureBox zuweise, dann funktionierts?

    Danke und LG
    Günther

    GuentherA schrieb:

    VB.NET-Quellcode

    1. PictureBox1.Image=bild
    Nimm diese Zeile mal raus.
    Das sollte eigentlich funktionieren.
    Ansonsten probierst Du mal, das Bild gleich in die DataTable zu packen und dem DGV keine separate Spalte zuzuweisen. Das läuft dann über das Binding.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    wenn mans richtig machen will, wirds bisserl schwierig.
    Erstmal darf man den Stream, von dem ein Bitmap geladen wurde, nicht disposen, solange man das Bild noch anzeigen will.

    Andererseits darf mans auch nicht nicht disposen, wenn mans nicht mehr braucht.
    Was vorhanden ist, sind Dateipfade, und die musste nun umwandeln in Bitmapse.
    Üblicherweise täte man denken, Bitmap aus Dateipfad einlesen und an DgvCell zuweisen - feddich.
    Das ist hier auch implementiert - wie gesagt mit dem Fehler, dass der Stream disposed wird, obwohl das Bild noch in Benutzung.
    Das erzeugt aber Problem, wenn du auf einen SpaltenHeader klickst, sodass sich das Grid umsortiert: Die Bilder kommen da nämlich nicht mit.
    Ist das eiglich ein Problem für dich?
    Weil ansonsten brauch ich ja nicht weiter zu erklären.

    ErfinderDesRades schrieb:

    Erstmal darf man den Stream, von dem ein Bitmap geladen wurde, nicht disposen, solange man das Bild noch anzeigen will.
    Ist so nicht richtig,

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. Using s As System.IO.FileStream = New IO.FileStream("C:\Temp\Test.jpg", IO.FileMode.Open)
    3. Dim bild = New Bitmap(s)
    4. DataGridView1.Rows(0).Cells.Item(0).Value = bild
    5. PictureBox1.Image = bild
    6. End Using
    7. End Sub
    funktioniert.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Danke für die Antworten ihr 2 :)

    @ErfinderDesRades Das Umsortieren wäre kein Problem, weil das lass ich in dem dgv eh nicht zu :) "Schwierig" klingt jetzt irgendwie spannend?!

    @RodFromGermany Ja das Funktioniert bei mir auch - bis auf die Zeile 4 :) Bzw. deren Auswirkung. Denn Fehler bekomm ich da auch keinen, im Debug steht im Item(0) auch schön das Bitmap drin, nur angezeigt wird nur das rote kreuz. In der Picture Box hingegen sehe ich schön das Bild (im Fall der Schleife natürlich das des letzten Durchlaufs)

    LG Günther

    GuentherA schrieb:

    bis auf die Zeile 4
    die da wäre?
    ====
    Lösch mal die Zeile

    VB.NET-Quellcode

    1. dgvRonden.UpdateCellValue(i, 0)

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. Using s As System.IO.FileStream = New IO.FileStream("C:\Temp\Test.jpg", IO.FileMode.Open)
    3. Dim bild = New Bitmap(s)
    4. DataGridView1.Rows(0).Cells.Item(0).Value = bild '<-- DIESE ZEILE
    5. PictureBox1.Image = bild
    6. End Using
    7. End Sub



    Die in der das Bild dem der dgv-Zelle zugewiesen wird. Also die Zuweisung ansich funktioniert ja, wird ja korrekt zugewiesen. Nur nicht dargestellt. ?(
    @GuentherA Bei mir schon.

    VB.NET-Quellcode

    1. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    2. For i = 0 To DataGridView1.Rows.Count - 1
    3. Dim bild As Image
    4. Using s As System.IO.FileStream = New IO.FileStream("C:\Temp\Überziehen.jpg", IO.FileMode.Open)
    5. bild = New Bitmap(s)
    6. PictureBox1.Image = bild '--> NUR FÜR TESTZWECKE UM ZU SEHEN, DASS DAS LADEN DES BILDES FUNKTIONIERT
    7. DataGridView1.Rows(i).Cells.Item(0).Value = bild ' My.Resources.EURO_PaletteGrau ' = RondenImage
    8. End Using
    9. 'DataGridView1.UpdateCellValue(i, 0)
    10. Next
    11. End Sub

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    aaaha... 8|

    Na jetzt wirds interessant! ?( Und hättest du vielleicht irgendeinen Ansatz woran das liegen könnte das das bei mir nicht funktioniert? Denn das Bild wird richtig geladen (in der Picture Box wirds ja dargestellt) die Zuweisung ist soweit ja auch richtig. Wenn ich mir die Feldinhalte beim debug anschaue, dann ist nach dem Erstellen der neuen Spalte der Inhalt der Zelle in der For Schleife natürlich nothing. Wenn ich das Image zuweise, klappt das auch. Also wo kann da der Bock sein?!

    Danke und LG
    Günther

    GuentherA schrieb:

    Also wo kann da der Bock sein?!
    Da hab ich keine Ahnung.
    Du arbeitest da noch mit einer Datenbank, die hab ich nicht.
    Vielleicht nimmst Du mein Snippet und baust vorsichtig Deinen Code drum herum (eine neue Button_Click sollte da reichen) und testest nach jeder Änderung.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Guenter: hmm - bei dir steht

    GuentherA schrieb:

    VB.NET-Quellcode

    1. DataGridView1.Rows(0).Cells.Item(0).Value = bild '<-- DIESE ZEILE
    und bei Rod:

    RodFromGermany schrieb:

    VB.NET-Quellcode

    1. DataGridView1.Rows(i).Cells.Item(0).Value = bild ' My.Resources.EURO_PaletteGrau ' = RondenImage

    Kann der Unterschied mit dem Prob zu tun haben?
    Na ist ja toll! Über das Button_Click wie von dir @RodFromGermany vorgeschlagen, funktionierts tatsächlich. Aber der selbe Code, egal zu welchem Zeitpunkt (dgv.bindingcomplete, dgv.Datasourcechanged, new() ) führt zu oben beschriebenem Verhalten... :(

    @ErfinderDesRades: Auch bei mir steht Rows(i), keine Ahnung von wo Rows(0) her kommt... ;)

    Danke und LG
    Günther

    EDIT:
    Habe jetzt EINE (- keine schöne) Lösung fürs Erste:
    Das DGV befindet sich auf einem Panel, welches ich durch einen Klick auf ein Element einer ListView (ListView ist in einem Splitcontainer) als weiteres Control in das Splittview einfüge, also quasi darüber lege. Ich habe nun in der Klasse des UserControls "PalettenPanel" eine Public Sub SetRondenPics eingefügt und rufe diese Sub auf, nachdem das Control der ControlCollection des Splitviews hinzugefügt wurde. So gehts.

    Aber warum das auf "normalen" Wege nicht klappt wäre schon interessant zu wissen....

    In jedem Fall dank ich Euch für Eure Unterstützung,

    LG Günther

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „GuentherA“ ()