Listview Zeile mit einer Grafik (aus Datei) füllen

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Listview Zeile mit einer Grafik (aus Datei) füllen

    Hallo Leute,

    ist es möglich ein normales Listview Control auch mit einer Grafik aus einer Datei zu befüllen?
    Dabei sollen Zeilen mit Text UND Grafik gemischt werden und die Zeile mit der Grafik sollte natürlich höher sein als die anderen Zeilen.

    In der Anlange findet Ihr ein Bild wie das aussehen sollte (wurde mit Fotoshop gemacht).
    Gibt es diese Möglichkeit beim Listview-control ?

    LG Roland
    Bilder
    • listviewmitgrafik.jpg

      259,84 kB, 1.143×757, 184 mal angesehen
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    dive26 schrieb:

    Dabei sollen Zeilen mit Text UND Grafik gemischt werden
    Sollen in einer gemeinsamen Zelle sowohl Text als auch Grafik angezeigt werden?
    Im DrawItem / DrawSubItem-Event kannst Du Dein Bildchen malen, zu Fuß.

    VB.NET-Quellcode

    1. Private Sub ListView1_DrawSubItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawListViewSubItemEventArgs) Handles ListView1.DrawSubItem
    2. ' die richtige Zelle bestimmen
    3. If e.Item.SubItems(3) Is e.SubItem AndAlso e.SubItem.Text = "3" Then
    4. e.Graphics.DrawImage(My.Resources.Delete, e.Bounds.X, e.Bounds.Y, e.Bounds.Height, e.Bounds.Height)
    5. ' hier e.Graphics.DrawText() aufrufen
    6. Else
    7. e.DrawDefault = True
    8. End If
    9. End Sub
    Du müsstest die Höhe der entsprechenden Zeile anpassen.
    Wie es aussieht, müsstest Du dazu eine von ListView abgeleitete eigene Klasse erstellen und mit OnMeasureItem() sie Zielhöhe bereitstellen: stackoverflow.com/questions/62…rows-in-winforms-listview
    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!
    @RodFromGermany vielen Dank.

    Wenn in der Zelle nur das Bild erscheint reicht das schon.
    Die Zelle ist Subitem Index 2 (Index 0 ist 0 Pixel breit).

    Ich könnte ja den Wert "TAG" in der Zelle modifizieren und sobald dort was drin steht (vielleicht sogar gleich der Dateiname), dann wird in Listview1_DrawSubItem das Bild gezeichnet.

    Gehe ich richtig in der Annahme, dass damit die Zeile selbst nicht höher wird und ich wohl nur den Bildausschnitt in der Höhe der Zeile sehen werde. Erst wenn ich mit einer abgeleiteten Klasse arbeite (da trau ich mich nicht wirklich ran), istdiese einzelne Zeile höher machbar?
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    dive26 schrieb:

    istdiese einzelne Zeile höher machbar?
    Ja.
    Du musst zu jeder Zeile und Spalte die gewünschte Höhe angeben.
    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!
    Ich habe in meine Form diese Funktion wie von Dir empfohlen eingebaut:

    VB.NET-Quellcode

    1. Private Sub ListView1_DrawSubItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawListViewSubItemEventArgs) Handles ListView1.DrawSubItem
    2. MsgBox("draw")
    3. End Sub


    Jedoch wird die Funktion bei mir nicht aufgerufen. Mache ich was falsch oder hab ich was vergessen?
    Es gibt natürlich das Listview1 Control in der Form.

    Edit: habs gefunden: OwnerDraw=true
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    @dive26 Jou, die MessageBox laggt.
    Mach Dir lieber eine Debug-Ausgabe:

    VB.NET-Quellcode

    1. Private Sub ListView1_DrawSubItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawListViewSubItemEventArgs) Handles ListView1.DrawSubItem
    2. Debug.WriteLine("ListView1_DrawSubItem")
    3. If e.Item.SubItems(3) Is e.SubItem AndAlso e.SubItem.Text = "3" Then
    4. e.Graphics.DrawImage(My.Resources.Delete, e.Bounds.X, e.Bounds.Y, e.Bounds.Height, e.Bounds.Height)
    5. Else
    6. e.DrawDefault = True
    7. End If
    8. 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!
    Die msgbox war ja nur da um zu sehen ob die Funktion überhaupt aufgerufen wird ;)
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    Vielen Dank für Deine Hilfe.

    Mit folgendem Code kann ich zumindest die Grafik in Zeilenhöhe positionieren wo und wie ich will.
    Das ist ausbaufähig. Theroretisch könnte ich die Grafik größer machen und dafür nachfolgende Leerzeilen in das Listview einfügen.

    Hier mein Code (der Dateiname wird im .TAG Feld des Subitems anderswo gespeichert):

    VB.NET-Quellcode

    1. Private Sub ListView1_DrawSubItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawListViewSubItemEventArgs) Handles ListView1.DrawSubItem, ListView2.DrawSubItem, ListView3.DrawSubItem, ListView4.DrawSubItem, ListView5.DrawSubItem, ListView6.DrawSubItem, ListView7.DrawSubItem, ListView8.DrawSubItem, ListView9.DrawSubItem, ListView10.DrawSubItem, ListView11.DrawSubItem, ListView12.DrawSubItem
    2. If e.Item.SubItems(2) Is e.SubItem And e.Item.SubItems(2).Tag <> "" Then
    3. Dim drawFont As Font = e.Item.SubItems(2).Font
    4. Dim drawBrush As New SolidBrush(e.Item.SubItems(2).ForeColor)
    5. Dim drawBack As New SolidBrush(e.Item.SubItems(2).BackColor)
    6. Dim Dateiname As String = e.Item.SubItems(2).Tag
    7. If File.Exists(Dateiname) Then
    8. Dim Grafikbreite As Integer = CInt(e.Bounds.Height / 5 * 8) 'Image ist immer in der Proportion 8:5
    9. Dim TempImage As Bitmap = CType(Image.FromFile(Dateiname, True), Bitmap)
    10. Dim drawRect As New RectangleF(e.Bounds.X + Grafikbreite, e.Bounds.Y, e.Bounds.Width - Grafikbreite, e.Bounds.Height)
    11. e.Graphics.FillRectangle(drawBack, e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height)
    12. e.Graphics.DrawString(e.Item.SubItems(2).Text, drawFont, drawBrush, drawRect)
    13. e.Graphics.DrawImage(TempImage, e.Bounds.X, e.Bounds.Y, Grafikbreite, e.Bounds.Height) 'Links neben dem Text
    14. Else
    15. e.DrawDefault = True
    16. End If
    17. Else
    18. e.DrawDefault = True
    19. End If
    20. End Sub

    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    dive26 schrieb:

    Die msgbox war ja nur da um zu sehen ob die Funktion überhaupt aufgerufen wird
    Das hab ich gesehen und nach einem eigenen Test verworfen:

    RodFromGermany schrieb:

    die MessageBox laggt.
    deswegen die Debug.WriteLine()-Ausgabe.
    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!
    Hallo Rod,

    dank Deiner Hilfe Habe ich soweit (fast) alles hinbekommen (Siehe Screenshot).

    Nun habe ich nur noch das Problem, dass die selbst in die Zelle gezeichnete Grafik beim Scrollen verschwindet bzw. gar nicht erscheint wenn Sie außerhalb des sichtbaren Bereiches ist.

    Wo muss ich dazu nochmals den Grafik-Code unterbringen? Gibt ja sicher irgend ein "refresh" oder "scroll" Event wo man diese Elemente dann neu zeichnen muss?

    LG Roland
    Bilder
    • Unbenannt-1.jpg

      625,76 kB, 3.440×1.440, 138 mal angesehen
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    dive26 schrieb:

    Wo muss ich dazu nochmals den Grafik-Code unterbringen?
    Bei mir isses in

    VB.NET-Quellcode

    1. Private Sub ListView1_DrawSubItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawListViewSubItemEventArgs) Handles ListView1.DrawSubItem
    2. ' ...
    3. 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!
    Hallo Rod,

    ich denke Du hast meine Frage nicht richtig verstanden. Der Code zum generieren der Grafik (und des Textinhaltes) steht ja schon in dieser Routine. Jedoch verschwindet die Grafik sobald man das Listview scrollt (und beim Scrollen die Grafik außerhalb des sichtbaren Bereiches verschwindet). Beim zurückscrollen ist die Grafik dann nicht mehr da.

    Muss also irgendwas mit "Refresh" oder so geben, damit man die Grafik dann auch immer "Nachzeichnen" kann.

    VB.NET-Quellcode

    1. Private Sub ListView1_DrawSubItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawListViewSubItemEventArgs) Handles ListView1.DrawSubItem, ListView2.DrawSubItem, ListView3.DrawSubItem, ListView4.DrawSubItem, ListView5.DrawSubItem, ListView6.DrawSubItem, ListView7.DrawSubItem, ListView8.DrawSubItem, ListView9.DrawSubItem, ListView10.DrawSubItem, ListView11.DrawSubItem, ListView12.DrawSubItem
    2. If e.Item.SubItems(2) Is e.SubItem And e.Item.SubItems(2).Tag <> "" Then
    3. Dim drawFont As Font = e.Item.SubItems(2).Font
    4. Dim drawBrush As New SolidBrush(e.Item.SubItems(2).ForeColor)
    5. Dim drawBack As New SolidBrush(e.Item.SubItems(2).BackColor)
    6. Dim Dateiname As String = e.Item.SubItems(2).Tag
    7. If File.Exists(Dateiname) Then
    8. Dim Grafikbreite As Integer = CInt((e.Bounds.Height * 5) / 5 * 8) 'Image ist immer in der Proportion 8:5 und immer 3 Zeilen hoch
    9. Dim TempImage As Bitmap = CType(Image.FromFile(Dateiname, True), Bitmap)
    10. 'Normaler Text in der aktuellen Zeile
    11. Dim drawRect As New RectangleF(e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height)
    12. e.Graphics.FillRectangle(drawBack, e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height)
    13. e.Graphics.DrawString(e.Item.SubItems(2).Text, drawFont, drawBrush, drawRect)
    14. 'Bild in den nächsten 3 Zeilen
    15. e.Graphics.DrawImage(TempImage, e.Bounds.X, e.Bounds.Y + e.Bounds.Height, Grafikbreite, e.Bounds.Height * 5) '3 Zeilen Gross unterhalb des Textes
    16. ElseIf e.Item.SubItems(2).Tag = "*" Then
    17. 'Hier nichts zeichnen, denn die Felder sollten komplett leer sein
    18. Else
    19. e.DrawDefault = True
    20. End If
    21. Else
    22. e.DrawDefault = True
    23. End If
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    dive26 schrieb:

    Beim zurückscrollen ist die Grafik dann nicht mehr da.
    Ich hab zwar nur ein kleines Bild, aber das ist beim Scrollen hoch und quer wieder da.
    Vielleicht machst Du mal ein kleines Testprojekt mit einer ausgewählten Zelle, die größer ist und in der gemalt wird.
    ====
    Hast Du ggf. eine separate Scroll-Behandlung für Dein LV?
    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!