[C#] (Explorer)ListView mit Miniaturansicht.

Danielku15

Erfahrenes Mitglied
Hi Leute.
Ich hab nun mittlerweilse schon einige Artikel durch aber immer noch nichts optimales gefunden.
Ich hab ein Explorer Control welches mir ein ListView mit den Daten des FileSystems und den entsprechenden SystemIcons füttert. Nun möchte ich wie man es vom Explorer so schön kennt, auch eine Miniaturansicht anbieten. Die Miniaturansichten will ich aus der Thumbs.db auslesen (dafür hab ich bereits eine Klasse, die Bilder stehen also zum Zeichnen zur Verfügung). Mein eigentliches Problem ist nun das Control selbst. Wie ermögliche ich nun am Besten eine Miniaturansicht?
Festlegen lassen könnte ich das Ganze über eine Eigenschaft (UseThumbView) oder so nur wie löse ich das Zeichnen des Controls. Muss ich mir hier selbst ein Raster generieren in welche ich aufwendig die einzelnen Elemente zeichne. Oder bietet da das .net Framework Möglichkeiten Höhe und Breite der Elemente zu setzen und dementsprechend im OnDrawItem den Bereich zur Verfügung zu haben?

Gibts da schon Lösungsansätze bei welchen die Miniaturansichten bei den Bildern gezeichnet wird, und bei den anderen nur die Default Icons? Seit CodeProject alle Artikel der unterschiedlichen Plattformen zusammengefügt hat, ist es langsam schwer die .net Artikel zu finden (selbst mit den Filtern klappt das nicht immer).

Gruß Daniel.
 
Hallo,

also ich würde es nicht mit dem ListView Control lösen. Ich würde dafür ein FlowLayoutPanel verwenden und dem die Controls (in meinem Beispiel sind es PictureBoxes(PreviewPictureBox)) hinzufügen.
In meinem Beispiel werden aus dem Verzeichnis "c:\test" alle Dateien geladen und angezeigt. Alle Bilder werden mit dem eigenem Inhalt angezeigt und sonstige mit einem default Bild.

Hier ist die Item-Klasse, die eine Datei repräsentiert:
C#:
	public interface IItem
    {
        Guid Id
        {
            get;
        }

        string Filename
        {
            get;
            set;
        }

        EItemType ItemType
        {
            get;
            set;
        }

        void RefreshType();
    }
	
	public enum EItemType
    {
        Default,
        Picture
    }
	
	public class Item : IItem
    {
        public Item()
        {
            id = Guid.NewGuid();
        }

        Guid id;

        public Guid Id
        {
            get { return id; }
        }

        string filename;

        public string Filename
        {
            get { return filename; }
            set
            {
                filename = value;
                RefreshType();
            }
        }

        EItemType itemType;

        public EItemType ItemType
        {
            get { return itemType; }
            set { itemType = value; }
        }

        public void RefreshType()
        {
            FileInfo info = new FileInfo(Filename);
            ItemType = ItemTypeFactory.GetItemType(info.Extension);
        }


    }
		
	class ItemTypeFactory
    {
        static string[] pictures = { ".png", ".bmp", ".jpg", ".gif" };
        public static EItemType GetItemType(string aFileExtension)
        {
            EItemType result = EItemType.Default;
            List<string> pictureList = new List<string>();
            pictureList.AddRange(pictures);

            if (pictureList.Contains(aFileExtension))
            {
                result = EItemType.Picture;
            }

            return result;
        }
    }

und hier das Control:
C#:
	public interface IPreviewUserControl
    {
        void Add(IItem anItem);
        void Remove(IItem anItem);
        void ClearItems();
    }
	
	public class PreviewUserControl : FlowLayoutPanel, IPreviewUserControl
    {
        public PreviewUserControl()
        {
            items = new List<IItem>();
        }

        IList<IItem> items;

		// add an item to items 
        public void Add(IItem anItem)
        {
            items.Add(anItem);
            AddControl(anItem);
        }

		// remove an item from items 
        public void Remove(IItem anItem)
        {
            items.Remove(anItem);
            RemoveControl(anItem);
        }

		//add preview picture box
        private void AddControl(IItem anItem)
        {
            this.Controls.Add(new PreviewPictureBox(anItem));
        }
        
		//remove preview picture box
        private void RemoveControl(IItem anItem)
        {
            for (int i = this.Controls.Count - 1; i >=0 ; i--)
            {
                if (this.Controls[i] is PreviewPictureBox)
                {
                    if ((this.Controls[i] as PreviewPictureBox).PreviewItem.Id == anItem.Id)
                    {
                        this.Controls.RemoveAt(i);
                        break;
                    }
                }
            }
        }

        // Clear list
        public void ClearItems()
        {
            items.Clear();
            for (int i = this.Controls.Count - 1; i >= 0; i--)
            {
                if (this.Controls[i] is PreviewPictureBox)
                {
                    this.Controls.RemoveAt(i);
                }
            }
        }
    }
	
	class PreviewPictureBox : PictureBox
    {
        public PreviewPictureBox(IItem anItem)
        {
            previewItem = anItem;
            base.SizeMode = PictureBoxSizeMode.Zoom;
            this.Width = 100; //default width
            this.Height = 60; // default width;
            this.Click += new EventHandler(PreviewPictureBox_Click);
        }

        void PreviewPictureBox_Click(object sender, EventArgs e)
        {
            MessageBox.Show(PreviewItem.Filename);
        }

        IItem previewItem;

        public IItem PreviewItem
        {
            get { return previewItem; }
        }
		
        Image image;
        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);
           
            if (image == null)
            {
                switch (PreviewItem.ItemType)
                {
                    case EItemType.Default:
                        image = Image.FromFile(@"c:\default.png");
                        break;
                    case EItemType.Picture:
                        image = Image.FromFile(PreviewItem.Filename);
                        break;
                }
                this.Image = image;
            }
           
        }
    }

C#:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace PreviewControl
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string[] files = Directory.GetFiles(textBox1.Text);
            previewUserControl1.ClearItems();   
            //create new items
            foreach(string file in files)
            {
                IItem item = new Item();
                item.Filename = file;
                previewUserControl1.Add(item);
            }

        }

    }
}

Gruß Konstantin
 
Zuletzt bearbeitet von einem Moderator:
Wow. Vielen Dank für das Control. Diese Idee werde ich bei einem weiteren Modul meines Projektes sehr gut verwenden können. Jedoch arbeite ich ja an einem Explorer Control und will die Miniaturansicht noch zusätzlich als View hinzufügen. Hab ich aber nun auch hin bekommen. (War gestern wohl doch noch zu spät :D ).

Idee:
Einfach die Listview auf Tile-View setzen und dann die TileSize anpassen. Dann einfach beim OnDrawItem den Content ensprechend zeichnen. Funktioniert wunderbar.

Jetzt hab ich nur noch 2 Probleme mit der Miniaturansicht:
1. Die Ordner-Vorschaubilder fehlen bei meiner Thumbs.db Klasse. Ich versuche gerade den Vorschau-Bilder Code aus diesem Artikel zu extrahieren: http://www.codeproject.com/KB/cpp/ExpCombo.aspx

2. Wenn ich von der Miniaturansicht auf die Kacheln-Ansicht wechseln will, bleibt die Tile-Ansicht bestehen, Wenn ich dann die TileSize ändere, wird diese nicht übernommen. Die PerformLayout mit RedrawItems oder auch Invalidate wird auch ignoriert. Im Moment ändere ich die Ansicht zuerst auf LargeIcon und dann wieder auf Tile. Gibts da noch etwas was beachtet werden muss?

Gruß Daniel
 
Zurück