C# PictureBox Array sortieren und befüllen mit einer Schleife

-Rayz-

Lieutenant
Registriert
Okt. 2010
Beiträge
895
Hallo mal wieder. So langsam könnte ich ja schon als Spamer durchgehen...

Nun gut hier mal ein neues Problem. Ich erstelle bei starten der Form 6 Pictureboxen welche von oben nach unten ausgegeben werden:

Code:
 public Form1()
        {                        
            
            InitializeComponent();
            for (int i = 0; i < 6; i++)
            {
                pbArray[i] = new PictureBox();
                pbArray[i].SizeMode = PictureBoxSizeMode.StretchImage;
                pbArray[i].Left = 35;
                pbArray[i].Top = pictureTop;
                pbArray[i].Size = new System.Drawing.Size(136, 183);
                pbArray[i].BackColor = Color.Red;
                panel1.Controls.Add(pbArray[i]);
                pictureTop += 200;
            }
        }

Das funktioniert auch. Nun werden die Boxen nach und nach mit Bildern gefüllt. Immer wenn ein Event triggert, wird ein Bild reingeladen und das Bild, was vorher ganz oben war, rückt nun in die Box darunter. Ich habe dies mal anhand einer Switchanweisung erstellt:

Code:
                        switch (pictureCounter)
                        {
                            case 0:
                                pbArray[0].Load(picture[0]);
                                break;
                            case 1:
                                pbArray[0].Load(picture[1]);
                                pbArray[1].Load(picture[0]);
                                break;
                            case 2:
                                pbArray[0].Load(picture[2]);
                                pbArray[1].Load(picture[1]);
                                pbArray[2].Load(picture[0]);
                                break;
                            case 3:
                                pbArray[0].Load(picture[3]);
                                pbArray[1].Load(picture[2]);
                                pbArray[2].Load(picture[1]);
                                pbArray[3].Load(picture[0]);
                                break;
                            case 4:
                                pbArray[0].Load(picture[4]);
                                pbArray[1].Load(picture[3]);
                                pbArray[2].Load(picture[2]);
                                pbArray[3].Load(picture[1]);
                                pbArray[4].Load(picture[0]);
                                break;
                        }
pictureCounter++;

Problem ist, dass das mit Switch aber nicht funktionieren wird. Ich habe ja max. 6 Boxen. Sind alle befüllt, dann wird das letzte Bild gelöscht und alle anderen rücken nach. Dachte ja, dass das irgendwo so funktionen könnte:

Code:
                    for (int i = 0; i <= pictureCounter; i++)
                    {
                        for (int j = pictureCounter; j >= 0; j--)
                        {
                            pbArray[i].Load(picture[j]);
                        }
                    }

tut es natürlich nicht ;)
Wer eine Idee wie ich das mit einer Schleife umsetzen könnte?
Vielen Dank.
 
Versuch' es doch mit der ImageList-Klasse in Verbindung mit einer ListView. Brauchste keine Schleife für.
 
So ganz klappt es noch nicht. Also ich habe eine imageList und Listview. In den Eigenschaften der Listview habe ich der LargeImageList meine imageList1 zugewiesen.
Wenn die Form gestartet wird, fülle ich die Imagelist auf:

Code:
            string[] pictureCount = new string[System.IO.Directory.GetFiles(PicturePath).Length];
            int i = 0;
            foreach (string str in System.IO.Directory.GetFiles(PicturePath))
            {
                if (str.Split('.')[1] == "jpeg")
                {
                    pictureCount[i] = str;
                    i++;
                }
            }
            pictureCount = pictureCount.Where(x => !string.IsNullOrEmpty(x)).ToArray();

            foreach (string picture in pictureCount)
            {
                Image bild = new Bitmap(picture);
                imageList1.Images.Add(bild);
            }

Das befüllen funktioniert auch. Es werden alle Bildpfade darin angelegt. Nur zeigt die listview diese nicht an...?
Ergänzung ()

wenn ich das erweitere geht es:

Code:
 int a = 0;
            foreach (string picture in pictureCount)
            {
                Image bild = new Bitmap(picture);
                imageList1.Images.Add(bild);
                listView1.Items.Add(picture, a);
                a++;
            }

allerdings wird dann unter dem Bild auch der Pfad ausgegeben...
 
Code:
string[] pictureCount
Man könnte bei dieser Namensgebung vermuten, dass es sich hier um eine Zahl handeln sollte.
Hast du schon mal mit Listen gearbeitet? Die eignen sich viel besser als Arrays, wenn die Größe der Liste vorher nicht feststeht.

str.Split ist auch suboptimal, nimm besser DirectoryInfo.EnumerateFiles(String).

Im Moment nutzt du die Imageliste nicht wirklich. Ich dachte eher an ListView.LargeImageList. Den Text kannst du vermutlich mittels der ListView.View-Eigenschaft wegbekommen.
 
nein hab noch nicht mit Listen gearbeitet. Werde ich mir mal anschauen.
Wenn ich den Teil

Code:
                Image bild = new Bitmap(picture);
                imageList1.Images.Add(bild);

weglasse habe ich aber keine Bilder mehr. Also muss ich es ja irgendwie nutzen.
Danke für die Links. Die werde ich mal durchgehen und ausprobieren.
Melde mich wieder sobald es updates gibt :)
 
Leider klappt es einfach nicht.
Wenn ich kompiliere werden die Bilder in die Listview geladen. Beim Debugging steht unter ListView->LargImageList->Images Count 4

Also sind vier Bilder in der Listview und das stimm auch. Nur werden diese nicht angezeigt... -_-

Code:
            DirectoryInfo di = new DirectoryInfo(PicturePath);            
            foreach (var fi in di.EnumerateFiles("*jpeg*"))
            {     
                imageList1.Images.Add(Bitmap.FromFile(PicturePath + "\\" + fi.Name));
            }

            ListView listView1 = new ListView();
            listView1.Bounds = new Rectangle(new Point(10, 10), new Size(185, 600));
            listView1.View = View.Details;
            listView1.LargeImageList = imageList1;            
            
            panel1.Controls.Add(listView1);

bmp habe ich auch getestet.

Anscheind muss ich wohl noch was mit den Items der ListView machen.. bzw anlegen und dir Bilder dort dann zuweisen...
 
Zuletzt bearbeitet:
verstehe nicht wieso ich diesen Beitrag nicht gefunden habe...
Es fehlte wirklich nur noch der Teil mit dem ListViewItem. Das mit den Pattern korrigiere ich noch.

Die Bilder werden nun wie gewünscht angezeigt.
Eine Frage (jaja nur eine.... :D) habe ich noch.

Nun habe ich eine Liste mit Bildern. Ich hätte aber gerne auf jedem Bild ein/zwei Buttons (löschen/speichern). Geht sowas direkt in der Listview oder muss ich mir einen Button anlegen und diesen "darüberlegen" ?
 
Ich bin eher den Umgang mit WPF gewohnt und stelle es mir mit WindowsForms ziemlich müßig vor.

Ein interessanter Ansatz wäre vielleicht das DrawItem-Event des ListViews?

Aber überhaupt... Auf jedes Item einen(zwei) eigenen Button zu legen finde ich zu viel Overhead. Ich würde 2 Buttons unter dem ListView anlegen oder mit einem ContextMenu arbeiten :)
 
Ja da hast du wohl recht. Man kann ja Checkboxen hinzufügen und dann kommen wie du schon geschrieben hast zwei Buttons unter den Listview.
Ergänzung ()

Ich habe noch ein Problem mit meiner Listbox

Code:
 private void ShowImages()
        {
            DirectoryInfo di = new DirectoryInfo(PicturePath);

            foreach (FileInfo file in di.GetFiles())
            {
                try
                {
                    this.imageList1.Images.Add(Image.FromFile(file.FullName));

                }
                catch
                {

                }
            }
            
            listView1.BackColor = Color.Gainsboro;
            listView1.View = View.LargeIcon; 
            listView1.LargeImageList = imageList1;

            for (int i = 0; i < this.imageList1.Images.Count; i++)
            {
                ListViewItem item = new ListViewItem();
                item.ImageIndex = i;
                itemCount = i;
                listView1.Items.Add(item);
            }
           

            tabPage1.Controls.Add(listView1);
        }

Es soll ja nach jedem Event ein weiteres Bild hinzugefügt werden. Wenn ich aber nun jedesmal diese Methode aufrufe, lädt er ALLE Bilder erneut in die Listview dabei soll er ja nur das EINE neue Bild hinzufügen.

Funktioniert das dann überhaupt auf diese Weise..?
 
Hm, wie wäre denn folgende Methode ?

Code:
    Public Sub AddImage(img As Image)
        Me.listView1.LargeImageList.Images.Add(img)
        Me.listView1.Items.Add(New ListViewItem With {.ImageIndex = Me.listView1.LargeImageList.Images.Count - 1})
    End Sub

Nicht wundern, ist VB.NET :p
 
Also meinst du so?

Code:
        private void AddImage(Image img)
        {
            listView1.BackColor = Color.Gainsboro;
            listView1.View = View.LargeIcon;
            listView1.LargeImageList = imageList1;
 
            listView1.LargeImageList.Images.Add(img);
            ListViewItem item = new ListViewItem();
            item.ImageIndex = listView1.LargeImageList.Images.Count - 1;
            listView1.Items.Add(item);
        
        }
Ergänzung ()

Funktioniert ganz gut nur eine Sache geht nun nicht mehr. Die Sortierung.
Das aktuellste Bild wird immer unten an die Liste gehängt. Es soll aber genau umgekehrt sein.

listView1.Sorting = SortOrder.******

habe ich bereits getestet aber geändert hat sich da nichts...
 
Ich schätze die Zeilen 3,4,5 sind überflüssig, da du die Eigenschaften nicht mit jedem neuen Item setzen musst.

Einmalig das sollte ausreichen :
Code:
// Initialisierung des ListViews
ListView listView1 = new ListView();
listView1.BackColor = Color.Gainsboro;
listView1.View = View.LargeIcon;
listView1.LargeImageList = new ImageList();


Sonst sieht der Code OK aus.

Jetzt, wo du deine neue Methode implementiert hast, kannst du die ShowImages()-Methode deutlich vereinfachen :

Code:
private void ShowImages(){
	{
		itemcount = 0;
		DirectoryInfo di = new DirectoryInfo(PicturePath);
		foreach (FileInfo file in di.GetFiles())
		{
			try
			{                
				this.AddImage(Image.FromFile(file.FullName));
				itemcount++; // Keine Ahnung wofür du das benötigst :)
			}
			catch
			{
			}
		}
		tabPage1.Controls.Add(listView1);
	}
}

Falls du etwas nicht verstehst, bitte fragen :)

Gruß
 
Meine Methode wird dann gar nicht mehr benötigt. Wenn die Form geschlossen wird, sollen eh alle Bilder gelöscht werden

Wie gesagt, die Sortierung bekomme ich noch nicht hin...

PS: ItemCount habe ich deswegen, weil ich zu jedem Bild noch ein paar weitere Informationen in einer Struktur speichere und wenn man auf das Bild klickt, werden die Informationen abgerufen.
 
Zuletzt bearbeitet:
Dann tausche

Code:
 listView1.Items.Add(item);

mit

Code:
 listView1.Items.Insert(0,item);

Dann wird das ListViewItem immer an oberster Stelle eingefügt.
 
Ich lasse mit zu jedem Bild den Index ausgeben:

int index = listView1.SelectedIndices[0];

Wenn ich nun ein Bild oben an der Liste anklicke, dann müsste der Index dort am höchsten sein und ganz unten müsste das Bild den Index 0 haben oder nicht?

Im Moment ist es nämlich nicht so..

PS: mal Mittagessen :)
 
Der Index beginnt immer(bin mir nicht 100% sicher bei der Sortierung, in diesem Fall aber schon) von oben an ab 0 und wird absteigend größer.

Guten Appetit.
 
Zuletzt bearbeitet:
Nun funktioniert die Sortierung aber dadurch funktioniert meine Struktur nicht mehr :(
Also ich habe ja ein Event:

Code:
private void RFIDData(object sender, DataEvent e)
        {
            if (InvokeRequired)
            {
                RFIDhelper RFIDthread = new RFIDhelper(RFIDData);
                this.Invoke(RFIDthread, sender,e);
            }
            else
            {
                

                if (this.pictureBox1.Image != null)
                {
                    this.pictureBox1.Image.Dispose();
                    this.pictureBox1.Image = null;
                }
                m_FileName = e.PictureFile;

                if (m_FileName != "" && m_FileName != pictureTemp)
                {
                    pictureBox1.Image = Image.FromFile(m_FileName);
                    pictureTemp = m_FileName;
                    AddImage(Image.FromFile(m_FileName));
                    ShowData(itemCount);
                    itemCount++;  
                }
            }             
        }

Hier die Methoden AddImage und ShowData:

Code:
private void AddImage(Image img)
        {
            listView1.BackColor = Color.Gainsboro;
            listView1.View = View.LargeIcon;
            listView1.LargeImageList = imageList1;
 
            listView1.LargeImageList.Images.Add(img);
            ListViewItem item = new ListViewItem();
            item.ImageIndex = listView1.LargeImageList.Images.Count - 1;
            listView1.Items.Insert(0, item);            
            
        }

private void ShowData(int index)
        {
            Pdata.type = init.getPassportData("type") + index;
            Pdata.code = init.getPassportData("code");
            Pdata.passportnr = init.getPassportData("passportnr");
            Pdata.surname = init.getPassportData("surname");
            Pdata.givenname = init.getPassportData("givenname");
            Pdata.nationality = init.getPassportData("nationality");
            Pdata.dateofbirth = init.getPassportData("dateofbirth");
            Pdata.sex = init.getPassportData("sex");
            Pdata.dateofexpiry = init.getPassportData("dateofexpiry");

            PassPortList.Add(Pdata);

            label_type.Text = PassPortList[index].type;
            label_Code.Text = PassPortList[index].code;
            label_PassportNr.Text = PassPortList[index].passportnr;
            label_Surname.Text = PassPortList[index].surname;
            label_GivenNames.Text = PassPortList[index].givenname;
            label_Nationality.Text = PassPortList[index].nationality;
            label_DateOfBirth.Text = PassPortList[index].dateofbirth;
            label_Sex.Text = PassPortList[index].sex;
            label_DateOfExpiry.Text = PassPortList[index].dateofbirth;
        }

Hier mein struct:

Code:
        public struct PassPortData
        {
            public string type;
            public string code;
            public string passportnr;
            public string surname;
            public string givenname;
            public string nationality;
            public string dateofbirth;
            public string sex;
            public string dateofexpiry;
        }

        List<PassPortData> PassPortList = new List<PassPortData>();
        PassPortData Pdata = new PassPortData();

Und hier der Code der ausgeführt wird, wenn man auf ein Bild klickt:

Code:
 private void listView1_Click(object sender, EventArgs e)
        {
            int index = listView1.SelectedIndices[0];
            label_type.Text = PassPortList[index].type;
            label_Code.Text = PassPortList[index].code;
            label_PassportNr.Text = PassPortList[index].passportnr;
            label_Surname.Text = PassPortList[index].surname;
            label_GivenNames.Text = PassPortList[index].givenname;
            label_Nationality.Text = PassPortList[index].nationality;
            label_DateOfBirth.Text = PassPortList[index].dateofbirth;
            label_Sex.Text = PassPortList[index].sex;
            label_DateOfExpiry.Text = PassPortList[index].dateofbirth;
            pictureBox1.Image = listView1.LargeImageList.Images[index];
        }

Nun stimmt der index natürlich nicht mehr. Es ist halt verkehrtherum. Ich muss das nun bestimmt anders lösen und irgendwie Bild + Text fest verketten nur wie stell ich das an? Bisher habe ich es ja über den Index der listview gemacht.

Denke das hier ist nun falsch: int index = listView1.SelectedIndices[0];
 
Wie befüllst du die PassPortList ?

Du willst mit den Bildern ein PassPortData-Objekt visualisieren. Also würde ich das PassPortDataObjekt zusammen mit dem ListViewItem erzeugen.

Die Controls bieten die Tag-Property an - perfekt um Daten zwischenzuspeichern.

Ich würde es wie folgt angehen :

Code:
public void LoadData(){
	
 //keine Ahnung wie du die PassPortData-Objekte gespeichert hast -> PseudoCode
 DataTable dt = this._Database.getTable("SELECT * FROM tPassPortData")
 foreach (DataRow row in dt.rows)
 {
	PassPortData data = new PassPortData(row);
	this.PassPortList.add(data);
	this.AddImage(data);
 }
}

//Als Parameter das jeweilige PassPortData-Objekt übergeben
public void AddImage(PassPortData data)
{
	Image img = null; // Hier das passende Image zum Objekt laden.
	
	listView1.LargeImageList.Images.Add(img);
    ListViewItem item = new ListViewItem();
    item.ImageIndex = listView1.LargeImageList.Images.Count - 1;
    item.Tag = data; //ListViewItem mit dem Objekt verknüpfen
	listView1.Items.Insert(0, item);        
}


Dann kannst du nämlich ganz einfach folgendes machen :


Code:
PassPortData data = PassPortList.Find(x => x is me.listView1.SelectedItem.Tag);

Ich hoffe ich habe jetzt keine Syntax-Fehler drin. C# ist nicht so meins :D
 
na in ShowData befülle ich diese und zeige sie direkt an:

Code:
        private void ShowData(int index)
        {
            Pdata.type = init.getPassportData("type") + index;
            Pdata.code = init.getPassportData("code");
            Pdata.passportnr = init.getPassportData("passportnr");
            Pdata.surname = init.getPassportData("surname");
            Pdata.givenname = init.getPassportData("givenname");
            Pdata.nationality = init.getPassportData("nationality");
            Pdata.dateofbirth = init.getPassportData("dateofbirth");
            Pdata.sex = init.getPassportData("sex");
            Pdata.dateofexpiry = init.getPassportData("dateofexpiry");

            PassPortList.Add(Pdata);
            
....

schaue mir mal deinen Code an :)

Aber LoadData würde ja bei jedem Event aufgerufen werden und dadurch würden sich ja alle Daten jedesmal verdoppeln.
Ergänzung ()

ich verstehe das mit dem Tag nicht. Wie soll ich meine Labels mit einem Tag befüllen und wie soll ich via Tag dann die Einträge aus der Listview und largeimagelist sowie aus meiner Struktur löschen..
Ergänzung ()

KAnn es sein, dass man nur einen Tag speichern kann?
Ich habe zu ca. 10 Bildern noch weitere Informationen gespeichert welche ich jederzeit mit einem Klick auf das Bild abrufen möchte. Irgendwie schaffe ich es aber nicht, mit dem Tag diese Informationen zu speichern.

listView1.LargeImageList = imageList1;

listView1.LargeImageList.Images.Add(img);
ListViewItem item = new ListViewItem();
item.ImageIndex = listView1.LargeImageList.Images.Count - 1;
//listView1.Items.Add(item);
listView1.Items.Insert(0, item);
listView1.Items[item.ImageIndex].Tag = Pdata;

und der Aufruf:

var myobj = new PassPortData();
if (listView1.SelectedItems.Count > 0)
{
var selecteditem = listView1.SelectedItems[0];
myobj = (PassPortData)listView1.Items[selecteditem.ImageIndex].Tag;
}
Ergänzung ()

PS: ich möchte auch nicht nur die Sachen hinzufügen, es muss auch an jeder Stelle löschbar sein..
 
Zuletzt bearbeitet:
Zurück
Oben