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

Code:
item.ImageIndex = listView1.LargeImageList.Images.Count - 1;
listView1.Items.Insert(0, item);
listView1.Items[item.ImageIndex].Tag = Pdata;
Du fügst dein Bild an Index 0 ein, weist dann aber die zugehörigen Daten dem letzten Element in der Liste zu...

Die Idee dahinter ist, immer das Bild und Daten in einem Objekt zu haben. Wird also ein ListItem selektiert, hast du automatisch das Bild und Daten in einem. Hast das Datenobjekt aus dem ListItem, kannst du dieses auch in deiner PassPort-Liste suchen und ggf. löschen.
 
Die Suche nach dem Tag will nur nicht funktionieren..

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

habe ich so geschrieben:

Code:
 var myobj = new PassPortData();

            myobj = PassPortList.Find(x => x is this.listView1.SelectedItems[0].Tag);

Also so wird der Code nicht angenommen... -_-
Ergänzung ()

So klappt es anscheind

Code:
 private void listView1_Click(object sender, EventArgs e)  
        {
            var myobj = new PassPortData();
            
            if (listView1.SelectedItems.Count > 0)
            {
                 myobj = (PassPortData)listView1.SelectedItems[0].Tag;                
            }

            label_type.Text = myobj.type;
            label_Code.Text = myobj.code;
            label_PassportNr.Text = myobj.passportnr;
            label_Surname.Text = myobj.surname;
            label_GivenNames.Text = myobj.givenname;
            label_Nationality.Text = myobj.nationality;
            label_DateOfBirth.Text = myobj.dateofbirth;
            label_Sex.Text = myobj.sex;
            label_DateOfExpiry.Text = myobj.dateofbirth;

        private void AddImage(Image img, PassPortData Pdata)
        {
            
            listView1.LargeImageList = imageList1;
 
            listView1.LargeImageList.Images.Add(img);
            ListViewItem item = new ListViewItem();
            item.ImageIndex = listView1.LargeImageList.Images.Count - 1;
            item.Tag = Pdata;  
            
            listView1.Items.Insert(0, item);
           

        }

Nun geht aber wieder die Sortierung nicht mehr obwohl ich doch immer an index 0 einfüge...?
 
Sieht soweit aber ok aus.
 
Es macht grad keinen Unterschied ob ich Insert oder Add nehme. Die Sortierung bleibt dieselbe...

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

liegt es am item.Tag = Pdata?


mmmh...
Ergänzung ()

MAl was anderes und zwar das löschen der Items. Wie kann ich das denn mit den Tags machen?
Im Moment hatte ich es so gemacht:

Code:
private void delete_Items_Click(object sender, EventArgs e)
        {                  

            foreach (ListViewItem item in listView1.SelectedItems)
            {
                listView1.Items.Remove(item);
                Image img = imageList1.Images[item.ImageIndex];
                imageList1.Images.RemoveAt(item.ImageIndex);
                img.Dispose();
                PassPortList.RemoveAt(item.ImageIndex);
                item.ImageIndex = listView1.LargeImageList.Images.Count - 1;
                this.pictureBox1.Image.Dispose();
                this.pictureBox1.Image = null;           
            }

Bei MEhrfachauswahl gibt es aber Probleme mit dem Index.. dieser stimmt dann nicht mehr :(
Ergänzung ()

Nun gut so geht es:

Code:
            foreach (ListViewItem item in listView1.SelectedItems)
            {
                if (item.Selected)
                {
                    listView1.Items.Remove(item);
                }          
            }

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

Allerdings muss ich dafür die Bilder selber markieren und nicht die Checkboxen in der Listview anklicken. Das wird aber schon noch...

Nur wieso die Sortierung nun nicht mehr passt versteh ich nicht!! :freak:
 
Ich glaube es gibt auch noch die CheckedItems-Property im ListView, die dir eine Liste mit den angehakten ListViewItems zurück gibt.
 
Glaube sowas müsste es dann sein

Code:
ListView.CheckedListViewItemCollection checkedItems =
            listView1.CheckedItems;

            foreach (ListViewItem item in checkedItems)
            {                
                    listView1.Items.Remove(item);                        
            }

hab ich aber wieder auskommentiert da ich die Checkboxen erstmal deaktiviert habe.

Die Sortierung nervt mich bei weitem mehr.. ich möchte nochmal Schritt für Schritt den Prozess durchgehen:

Event wird getriggert und Daten erstellt:

Code:
...
 if (m_FileName != "" && m_FileName != pictureTemp)
                {
                    pictureBox1.Image = Image.FromFile(m_FileName);
                    pictureTemp = m_FileName;

                    Pdata = ShowData(Image.FromFile(m_FileName));
                    AddImage(Image.FromFile(m_FileName),Pdata);

                      
                }
...
zuerst wird ShowData aufgerufen. Hier wird die Struktur gefüllt und in den Labels angezeigt:
Rückgabewert ist die Struktur

Code:
private PassPortData ShowData(Image img)
        {        
                       
            Pdata.type = init.getPassportData("type");
            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");
            Pdata.MRZ = init.getMRZ();
            Pdata.PassImage = img;

            PassPortList.Add(Pdata);
            //PassPortList.Insert(0, Pdata);
            
            label_type.Text = Pdata.type;
            label_Code.Text = Pdata.code;
            label_PassportNr.Text = Pdata.passportnr;
            label_Surname.Text = Pdata.surname;
            label_GivenNames.Text = Pdata.givenname;
            label_Nationality.Text = Pdata.nationality;
            label_DateOfBirth.Text = Pdata.dateofbirth;
            label_Sex.Text = Pdata.sex;
            label_DateOfExpiry.Text = Pdata.dateofexpiry;
            label_MRZ.Text = Pdata.MRZ;

            return Pdata;
        }

Anschließend wird der Tag auf Pdata gesetzt und das Bild in die listview geladen:

Code:
private void AddImage(Image img, PassPortData Pdata)
        {
            
            listView1.LargeImageList = imageList1;
 
            listView1.LargeImageList.Images.Add(img);
            ListViewItem item = new ListViewItem();
            item.ImageIndex = listView1.LargeImageList.Images.Count - 1;
            item.Tag = Pdata;  
            
            listView1.Items.Insert(0, item);        

        }

So... das war alles.



Tjo so einfach kann es gehen... Sorting = Ascending... läuft.. -_-

Gut, kann ich mich den Checkboxen wieder witmen :)
 
Zuletzt bearbeitet:
Ab und an habe ich noch einen Fehler wenn ich zwischen den Objekten hin und her klicke:

System.ArgumentException wurde nicht behandelt.
HResult=-2147024809
Message=Ungültiger Parameter.
Source=System.Drawing
StackTrace:
bei System.Drawing.Image.get_FrameDimensionsList()
bei System.Drawing.ImageAnimator.CanAnimate(Image image)
bei System.Drawing.ImageAnimator.ImageInfo..ctor(Image image)
bei System.Drawing.ImageAnimator.Animate(Image image, EventHandler onFrameChangedHandler)
bei System.Windows.Forms.PictureBox.Animate(Boolean animate)
bei System.Windows.Forms.PictureBox.Animate()
bei System.Windows.Forms.PictureBox.InstallNewImage(Image value, ImageInstallationType installationType)
bei System.Windows.Forms.PictureBox.set_Image(Image value)
bei PKT4000Final.Form1.listView1_Click(Object sender, EventArgs e) in d:\c# Übungen\PKT4000Final\PKT4000Final\Form1.cs:Zeile 241.
bei System.Windows.Forms.Control.OnClick(EventArgs e)
bei System.Windows.Forms.ListView.WmReflectNotify(Message& m)
bei System.Windows.Forms.ListView.WndProc(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
bei System.Windows.Forms.UnsafeNativeMethods.SendMessage(HandleRef hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
bei System.Windows.Forms.Control.SendMessage(Int32 msg, IntPtr wparam, IntPtr lparam)
bei System.Windows.Forms.Control.ReflectMessageInternal(IntPtr hWnd, Message& m)
bei System.Windows.Forms.Control.WmNotify(Message& m)
bei System.Windows.Forms.Control.WndProc(Message& m)
bei System.Windows.Forms.ScrollableControl.WndProc(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
bei System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
bei System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
bei System.Windows.Forms.Control.DefWndProc(Message& m)
bei System.Windows.Forms.ListView.WmMouseDown(Message& m, MouseButtons button, Int32 clicks)
bei System.Windows.Forms.ListView.WndProc(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
bei System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
bei System.Windows.Forms.Application.Run(Form mainForm)
bei PKT4000Final.Program.Main() in d:\c# Übungen\PKT4000Final\PKT4000Final\Program.cs:Zeile 19.
bei System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
bei System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
bei System.Threading.ThreadHelper.ThreadStart()
InnerException:


Dieser Fehler taucht hier auf:

Code:
        private void listView1_Click(object sender, EventArgs e)  
        {
            var myobj = new PassPortData();            

            if (listView1.SelectedItems.Count > 0)
            {
                 myobj = (PassPortData)listView1.SelectedItems[0].Tag;                
            }            


            label_type.Text = myobj.type;
            label_Code.Text = myobj.code;
            label_PassportNr.Text = myobj.passportnr;
            label_Surname.Text = myobj.surname;
            label_GivenNames.Text = myobj.givenname;
            label_Nationality.Text = myobj.nationality;
            label_DateOfBirth.Text = myobj.dateofbirth;
            label_Sex.Text = myobj.sex;
            label_DateOfExpiry.Text = myobj.dateofbirth;
            label_MRZ.Text = myobj.MRZ;
           pictureBox1.Image = myobj.PassImage;
            
        }
---> diese Zeile: pictureBox1.Image = myobj.PassImage;

Wie kann ich das verhindern?
In myobj.PassImage steht zu diesem Zeitpunkt:
Flags = "myobj.PassImage.Flags" hat eine Ausnahme vom Typ "System.ArgumentException" verursacht.
usw.
 
Ich kenne mich nicht so gut mit struct aus aber vermutlich kommt das Problem daher, dass bei der Zuweisung das Bild selbst kopiert wird und nicht die Referenz.

Wenn du aus PassPortData eine Klasse machst, wäre das 1. performanter und könnte 2. das Problem lösen.
Dann musst du aber aufpassen, wenn du Dispose auf dem Bild aufrufst, da du es dann nicht mehr verwenden kannst.

Beim verarbeiten der Daten rufst du 3x Image.FromFile(m_FileName) auf. 1x würde ausreichen.

Du scheinst irgendwo eine (Klassen-?)Variable Pdata zu haben. Lösche diese und arbeite ausschließlich mit lokalen Variablen. In ShowData müsste dann soetwas stehen:
Code:
        private PassPortData ShowData(Image img)
        {        
            PassPortData pdata = new PassPortData();
            pdata.Type = init.getPassportData("type");
            ...
            return pdata;
Oder besser: Du baust einen Konstruktor für PassPortData, dem du init und img übergeben kannst.
Idealerweise machst für das Erstellen eine eigene Methode. Dieses Verhalten würde man von ShowData nicht erwarten.
 
Meinst du so?

Neue Klasse:
Code:
public class data
    {
        private string type;
        public string Type
        {
            get { return type; }
            set { type = value; }
        }
....
 
Zuletzt bearbeitet:
Das sieht schon mal gut aus. Zum Codestyle: Private Instanzvariablen beginnt man i.d.R. mit einem Unterstrich, Properties mit einem Großbuchstaben und lokale Variablen und Argumente mit einem Kleinbuchstaben. Du machst das irgendwie Querbeet.

Code:
        private string _dateOfExpiry;

        public string DateOfExpiry
        {
            get { return _dateOfExpiry; }
            set { _dateOfExpiry= value; }
        }

Was den Fehler noch verursachen könnte:
Wenn Sie dasselbe Bild für mehrere PictureBox-Steuerelement verwenden möchten, erstellen Sie pro PictureBox einen Klon des Bilds. Wenn mehrere Steuerelemente auf dasselbe Bild zugreifen, wird eine Ausnahme ausgelöst.
Quelle: PictureBox.Image

Du könntest die Property dann immer eine Kopie liefern lassen, anstatt das Original.
 
Das selbe Bild in Form vom selben Dateinamen wahrscheinlich. Dies ist nicht der Fall da ich ja die aktuelle Zeit als Dateinamen genommen habe und dadurch jedes Bild anders heißt,

PS: Danke für den Tipp zum Codestyle. Werde ich ändern.
 
Du verwendest das selbe Bild (genauer: das selbe Objekt) einmal für die Liste und dann nochmal für die PictureBox (so habe ich das zumindest von deinen Codefragmenten verstanden). Die Datei dahinter spielt keine Rolle (nicht so wie bei PictureBox.LoadImage).

Du hast ja schon die Klasse mit dem Image-Property. Also einfach das Bild klonen und gucken, was passiert.
 
Meinst du das mit der Kopie so?

Code:
        private void listView1_Click(object sender, EventArgs e)  
        {
            try
            {
                var obj = new data();
                
                if (listView1.SelectedItems.Count > 0)
                {
                    obj = (data)listView1.SelectedItems[0].Tag;
                    hz = obj;
                }
                Image image = new Bitmap(obj.PassImage);

                label_type.Text =obj.Type;
               
            }
            catch (Exception ex)
            {
                toolStripStatusLabel1.Text = ex.Message;
            }
        }

Keine Ahnung ob es Einbildung ist aber es läuft nun sehr stabil. Ich muss schon sehr schnell die Bilder wechseln um einen Fehler zu verursachen.
Ergänzung ()

Hab da noch eine Frage zum löschen der Daten.
Wenn ich alles löschen möchte mache ich einfach folgendes:

Code:
        private void button_deleteall_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem item in listView1.Items)
            {
                listView1.Items.Remove(item);
                blub = new data();
                if (pictureBox1.Image != null)
                {
                    this.pictureBox1.Image.Dispose();
                    this.pictureBox1.Image = null;
                }
                label_type.Text = string.Empty;
               
            }
        }

Aber wie lösche ich einzelne Einträge in meiner data Klasse?
Aus ist das mit if(item.Selected) ja kein Problem..
 
Zuletzt bearbeitet:
Ja, es sieht soweit gut aus. Dispose das Image noch, bevor du es neu setzt, sonst läuft der Speicher voll.
Wenn mrz eine Klassenvariable ist, benenne sie entsprechend um (_mrz), damit man auf den ersten Blick sieht, womit man es zu tun hat.

Eine Fehlermeldung dürfte dennoch nicht geworfen werden. Ist es exakt die gleiche Fehlermeldung?

Für das Löschen brauchst du einen Zugriff auf deine MRZList. Durch das LIstViewItem.Tag hast du die Referenz und kannst dann in der Liste danach suchen und löschen.

Und das ListViewItem löschen funktioniert, während du durch die Liste iterierst? Könnte schwören, dass da eine Exception geworfen wird. Könnte aber auch sein, dass ich das mit Java verwechsle.
 
Danke -mal wieder- vielmals.
Läuft bisher ganz gut und ich kann mich dem nächsten widmen. Kurz gesagt: Mache bestimmt bald wieder einen Thread auf :freak:
 
Zurück
Oben