Wert aus Combo in OnSelchangeCombo1() verwenden



  • Hi Leute ich habe ein Problem, ich will einen Wert einer Combobox gleich in OnSelchangeCombo1() verwenden. Das geht so aber irgendwie nicht, weil er das irgendwie nicht richtig läd, er zeigt mir immer die zuletzt gewählte Selektion an! Gibt es da einen Trick? (UpdateData bringt da auch nichts!)



  • Wie machst du es denn bisher?

    Mit GetCurSel solltest du eigentlich an die aktuelle Auswahl kommen. 🙂



  • hm also bisher mach ich einfach mit nem Button UpdateData(TRUE); und dann steht der Wert der Combo auch in der Member, GetCurSel(); bin ich grad am probieren, wie funktioniert denn das? In der MSDN steht nicht viel drin, nur dass ich den Index vom Feld zurück bekomme. aber was mach ich dann mit dem Index ich durchsuche nacher nach dem String aus der Combo meine DB, ich kann aber doch nicht nach dem Index aus der Combo suchen!



  • Okay, dann schmeiß ich dir mal ne Runde Funktionsnamen an den Kopf, versuch mal zu puzzeln - Erklärungen hole ich nachher mit Ruhe nach, wenn du es noch nicht raus hast. 😉

    SetItemData, GetItemData, AddString gibt nen Index zurück. In das ItemData packst du die ID aus der Datenbank. 🙂



  • okay ich fang mal an mit den Teilen zu pzzeln, aber ob ich da was hin bekomm weiß ich nicht, melde mich wenn ich wieder völlig verzweifelt bin!



  • Bin zwar noch nicht ganz verzweifelt (bin ja noch nicht all zu lange dran) aber ne Frage hab ich dennoch, die ID aus der DB ist das was festes? Ich mein gibt die DB für die Zeilen IDs oder muss ich da in meiner DB ne Spalte machen mit nem Autotext der mir automatisch die IDs einfügt?



  • Also ich habe jetzt in meiner Access DB eine Spalte ID eingeführt, hab die meinem Projekt zugewiesen und hab beim füllen des Combos setItemData verwendet. Soweit so gut, jetzt geht des auch tatsächlich, aber ich verstehe es nicht so ganz, denn ich muss um auf den richtigen Datensatz zu kommen immer +2 machen, dass er auf den richtigen Datensatz kommt. Was aber nicht schlimm ist, denn die Combo fängt bei 0 an meine IDs bei 1 das heißt es wird die erste ID nicht angezeigt. Was auch wiederum nicht schlimm ist, da dieser Datensatz eh nur Bitte wählen sie eine PCD Nummer aus beinhaltet. Aber irgendwie kommt mir das ein wenig spanisch vor, was mach ich falsch?
    Hier mein Code:

    void CDokumentenVerwaltungView::loadPCD()
    {
    	CDBVariant varValue;
    
    	UpdateData(TRUE);
    
    	short nFields = m_pSet->GetODBCFieldCount();
    
    	for( short index = 0; index < nFields; index++ )
    		{
    			m_pSet->MoveFirst();
    			while (!m_pSet->IsEOF())
    			{
    				m_pSet->GetFieldValue( index, varValue );
    
    				m_PCD_CMB.SetItemData(m_pSet->m_ID,m_pSet->m_ID);
    				m_PCD_CMB.AddString(*(varValue.m_pstring));
    
    				m_pSet->MoveNext();
    			}
    			if (m_pSet->IsEOF())
    			{
    				m_pSet->MoveFirst();
    				break;
    			}
    		}
    
    	UpdateData(FALSE);
    
    }
    
    void CDokumentenVerwaltungView::OnSelchangeCombo1() 
    {
    	int Test= m_PCD_CMB.GetCurSel();
    	m_pSet->SetAbsolutePosition( Test+2 );
    	selectedPCD = m_pSet->m_PCD_NR;
    	selectedAnweisungsindex =m_pSet->m_Anweisungsindex;
    	m_Selected = m_pSet->m_PCD_NR;
    	isSelected =TRUE;
    	UpdateData(FALSE);
    }
    

    🙂



  • Du hast was verdreht:

    int nIdx = m_PCD_CMB.AddString(*(varValue.m_pstring)); //Merken, an welche Position es geschrieben wird (wegen evtl. Sortieren oder so)
                    m_PCD_CMB.SetItemData(nIdx,m_pSet->m_ID);
    

    Und beim Auslesen hast du dann den Zugriff auf ItemData vergessen:

    int Test= m_PCD_CMB.GetCurSel();
    if (Test != -1) // es muss was gewählt sein
    {
        int nID = m_PCD_CMB.GetItemData(Test);
    }
    


  • hm OK aber irgendwie muss ich immernoch +2 machen weil er sonst nicht auf dem richtigen Datensatz ist. Irgendwas läuft da schief, denn wenn ich die Combo wieder leeren will, dann löscht er nur ein paar raus!

    leeren geht doch so, oder??

    for( int i = 0; i < 100; i++ )
    	{
    		m_PCD_CMB.DeleteString(i);
    	}
    


  • Ohne es ausprobiert zu haben gehe ich mal davon aus, dass nur jeder zweite gelöscht wird, oder ?

    Weil:
    - der erste hat den Index 0
    - den löscht du
    - jetzt rutschen alle nachfolgenden nach (der mit ursprünglich Index 1 ist jetzt der erste, hat also Index 0)
    - jetzt löscht du den mit Index 1 (ursprünglich Index 2)
    - usw.

    Eine komplette ComboBox-Liste kannst du übrigens mit ResetContent( ) löschen.



  • Polofreak schrieb:

    hm OK aber irgendwie muss ich immernoch +2 machen weil er sonst nicht auf dem richtigen Datensatz ist.

    Zeig mal den Code bitte.



  • WOW Respekt! Aber für was mache ich dann die ganze Scheiße mit SetItemdata, das würde ja bedeuten sobald ich einen raus nehme stimmt ja gar nichts mehr, dann entspricht das ja gar nicht mehr meiner DB! Naja gut egal dann lösch ich entweder nichts raus oder ich mach danach halt immer ein Load auf das COmbo. Vielen Dank Isbeau und Estartu_de



  • Hm wenn du jetzt noch den Fehler findest küss ich dir die Füsse

    void CDokumentenVerwaltungView::loadPCD()
    {
    	CDBVariant varValue;
    
    	UpdateData(TRUE);
    
    	short nFields = m_pSet->GetODBCFieldCount();
    
    	for( short index = 0; index < nFields; index++ )
    		{
    			m_pSet->MoveFirst();
    			while (!m_pSet->IsEOF())
    			{
    				m_pSet->GetFieldValue( index, varValue );
    				 //Merken, an welche Position es geschrieben wird (wegen evtl. Sortieren oder so) 
    				int nIdx = m_PCD_CMB.AddString(*(varValue.m_pstring));
                    m_PCD_CMB.SetItemData(nIdx,m_pSet->m_ID); 
    
    				m_pSet->MoveNext();
    			}
    			if (m_pSet->IsEOF())
    			{
    				m_pSet->MoveFirst();
    				break;
    			}
    		}
    
    	UpdateData(FALSE);
    
    }
    
    void CDokumentenVerwaltungView::OnSelchangeCombo1() 
    {
    	int Test= m_PCD_CMB.GetCurSel(); 
    	if (Test != -1) // es muss was gewählt sein 
    	{ 
    	    int nID = m_PCD_CMB.GetItemData(Test); 
    	} 
    	m_pSet->SetAbsolutePosition( Test+2 );
    	selectedPCD = m_pSet->m_PCD_NR;
    	selectedAnweisungsindex =m_pSet->m_Anweisungsindex;
    	m_Selected = m_pSet->m_PCD_NR;
    	isSelected =TRUE;
    	UpdateData(FALSE);
    }
    

    aber mach dir nicht zu viel mühe, ich mein für das was ich bisher damit mach reicht es eigentlich auch. Wenn du den Fehler aber findest wäre ich dir dennoch super riesig Dankbar!



  • *seufz* Wenn ich ne neue Variable mache, wo das rein kommt, was du suchst - dann benutz sie doch auch...

    void CDokumentenVerwaltungView::OnSelchangeCombo1()
    {
        int Test= m_PCD_CMB.GetCurSel();
        if (Test != -1) // es muss was gewählt sein
        {
            int nID = m_PCD_CMB.GetItemData(Test);
            m_pSet->SetAbsolutePosition(nID);
            selectedPCD = m_pSet->m_PCD_NR;
            selectedAnweisungsindex =m_pSet->m_Anweisungsindex;
            m_Selected = m_pSet->m_PCD_NR;
            isSelected =TRUE;
            UpdateData(FALSE);
        }
    }
    

    Okay, jetzt auch die versprochene Erklärung:
    Ein Eintrag einer Combobox besteht nicht nur aus der Zeichenkette, die du sehen kannst.
    Du kannst auch einen Zeiger (Get-/SetItemDataPtr) oder eine Zahl (Get-/SetItemData) an einen Eintrag anhängen. (Ob beides gleichzeitig geht, habe ich noch nicht probiert.)

    Mit AddString hängst du ja einen neuen Eintrag in die Combobox. Wenn die jetzt aber sortiert wird oder du was löschst, dann weißt du ja den Index nicht (haste ja gemerkt).

    Wenn du nun aber deine ID aus der Datenbank mit anhängst, hast du etwas absolutes, den auch egal ist, in welcher Reihenfolge die Zeichenketten stehen. Das passt immer!

    Ich habe dafür eine eigene Comboboxklasse (du erinnerst dich an die Codeschnipsel von neulich?) die machen dir den Kram mit der ID etwas leichter.

    Nun solltest du aber noch eines beherzigen:
    In deinem Recordset ist NICHT unbedingt gewärleistet, dass der Datensatz mit der ID 3 auch an dritter Stelle steht. Spätestens wenn einer gelöscht wurde oder du die Sortierung änderst, klappt das nicht mehr.
    Bau also am besten eine Suchfunktion mit "Positionierung" des Cursors (also dass er auf dem gefundenen Datensatz steht, wenn er fertig ist) ein.

    Ich hab die hier in meiner Recordsetbasisklasse:

    // ------------------------------------------------------------------------------------------------
    // Gibt true zurück, wenn ein Datensatz mit der gegebenen ID gefunden wurde.
    // Lässt sich also zur "Vorhandenheitsprüfung" und zur Cursor Positionierung nutzen.
    // ------------------------------------------------------------------------------------------------
    bool CBasisSet::Suche(long f_lID)
    {
    	bool fReturn = false;
    
    	// Stimmt die Kombination?
    	if (m_lID == f_lID) 
    	{
    		// Die ID merken
    		fReturn = true;
    	}
    	else
    	{
    		// Einmal über alle Datensätze laufen
    		if (IsBOF())
    		{
    		}
    		else
    		{
    			// Vorne anfangen
    			MoveFirst();
    			while((!IsEOF()) && (!fReturn))
    			{
    				// Stimmt die Kombination?
    				if (m_lID == f_lID) 
    				{
    					// Die ID merken
    					fReturn = true;
    				}
    				if (!fReturn)
    				{
    					MoveNext();
    				}
    			}
    		}
    	}
    
    	return fReturn;
    }
    

    Okay? 🙂



  • Erst mal vielen lieben dank für deine ausfürliche Beschreibung, mir ist so einiges klar geworden. Ich hab auch schon ne Suchfunktion, die ein wenig anders aussieht wie deine aber in meinen Augen schon so ziemlich das gleiche macht.

    void CDokumentenVerwaltungView::suchen(CString Anfrage)
    {
    	bool Suchergebnis=FALSE;
    	CDBVariant varValue;
    
    	UpdateData(TRUE);
    
    	short nFields = m_pSet->GetODBCFieldCount();
    
    	for( short index = 0; index < nFields; index++ )
    		{
    			m_pSet->MoveFirst();
    			while (!m_pSet->IsEOF())
    			{
    				m_pSet->GetFieldValue( index, varValue );
    				if (m_pSet->m_PCD_NR == Anfrage)
    				{
    					Suchergebnis = TRUE;
    					selectedPCD = m_pSet->m_PCD_NR;
    					selectedAnweisungsindex =m_pSet->m_Anweisungsindex;
    					isSelected =TRUE;
    					break;
    				}
    				m_pSet->MoveNext();
    			}
    			if (m_pSet->IsEOF())
    			{
    				m_pSet->MoveFirst();
    				break;
    			}
    		}
    
    		if (!Suchergebnis)
    		 MessageBox("Die angeforderte Nummer ist nich vorhanden !","ERROR",MB_ICONERROR); 
    
    	UpdateData(FALSE);
    }
    

    aber was hat das andere mit meiner Suchfunktion zu tun, naja bzw. wie beeinflusst das meine Comboboxfüllung?? wo oder wie muss ich die aufrufen?
    P.S.: jetzt geht es echt super!! (hab aber auch noch nichts gelöscht



  • Ja, die macht das selbe, nur eben mit einer Zeichenkette und einem kleinen Nachteil:
    Stell dir vor, du hast eben etwas gefunden, das ist der letzte Datensatz.
    Nun suchst du das gleich nochmal.
    So, wie du das machst, fängt der blind wieder vorne an und rennt bis ganz hinten.

    Ich habe das erst vor ein paar Tagen eingebaut, mit der Zusatzprüfung - das spart ENORM viel Zeit. 😮

    Die Suche nach der ID brauchst du, weil das SetAbsolutePosition ja nicht stimmen muss. (s.o.)
    Also statt

    m_pSet->SetAbsolutePosition(nID);
    

    besser

    m_pSet->Suche(nID);
    

    🙂

    Noch ein kleiner Hinweis in Sachen Klassendesign:
    Pack das suchen besser in die Recordsetklasse. Sonst musst du das, wenn du es an einer anderen Stelle (in einem anderen View) brauchst, nochmal tippen bzw. kopieren. Sowas ist unschön, wartungshemmend und sehr fehleranfällig. ⚠
    (Oder hast du da Sachen drin, die unbedingt im View passieren müssen und nicht ausgelagert werden können?)



  • A L S O!!
    Ich habe jetzt meine Suche angepasst, dass ich auch nach ner ID suchen kann. Problem war nämlich ich hab ja immer nur eine Spalte mit dem Suchwert verglichen denn ích hab mehrere Spalten, wo z.B. 2 drin vor kommt. naja egal das geht ja auch alles ABER. Ich hab mal Spasseshalber einen Datensatz raus gelöscht und ans Ende mit ner neuen ID eingefügt, und ich hab genau das von dir angesprochene Problem, und das ohne dass ich moveabsoluteposition mach, sondern suchen (ID). Woran liegt das denn schon wieder ??



  • Zeig den Quellcode bitte.

    Einmal vom suchen(id) und einmal, wie du es aufrufst. 🙂



  • öhm ich hab mir mal angeschaut was du sehen willst, und mir ist schon klar wo der fehler sitzt. Also:

    void CDokumentenVerwaltungView::suchen(CString Anfrage, CString typ)
    {
    	bool Suchergebnis=FALSE;
    	CDBVariant varValue;
    
    	UpdateData(TRUE);
    
    	short nFields = m_pSet->GetODBCFieldCount();
    
    	for( short index = 0; index < nFields; index++ )
    		{
    			m_pSet->MoveFirst();
    			while (!m_pSet->IsEOF())
    			{
    				m_pSet->GetFieldValue( index, varValue );
    
    				if (typ=="ID")
    				{
    					int i = atoi(Anfrage);
    					if (m_pSet->m_ID == i)
    					{
    						Suchergebnis = TRUE;
    						break;
    					}
    				}
    				m_pSet->MoveNext();
    			}
    			if (m_pSet->IsEOF())
    			{
    				m_pSet->MoveFirst();
    				break;
    			}
    		}
    
    		if (!Suchergebnis)
    		 MessageBox("Die angeforderte Nummer ist nich vorhanden !","ERROR",MB_ICONERROR); 
    
    	UpdateData(FALSE);
    
    }
    

    und dann noch

    int nID =0;
    	nID = m_PCD_CMB.GetCurSel(); 
    	if (nID != -1) // es muss was gewählt sein 
    	{ 
    	    nID = m_PCD_CMB.GetItemData(nID); 
    	} 
    	suchen(nID,"ID");//Die Funktion erwartet ja aber einen String, muss ich das casten?
    //also wenn ich "7" schreibe macht er mir tatsächlich das Feld mit dem Index 7 auf
    

    🙄 🙄 🙄 kann ich nur über mich selbst mit den Augen rollen, da fehlt mir immer wieder grundlegendes



  • Wieso machst du das so "komisch"?
    Also, warum gibst du den Feldnamen mit - wo es doch eh keine andere Möglichkeit zu geben scheint (oder soll das noch kommen?).

    Naja, ein Vorschlag meinerseits wäre: Du überlädst die Funktion. 🙂
    Kurze Grundlage: Es kann pro Klasse mehrere Funktionen mit dem selben Namen geben, die Parameter müssen sich aber unterscheiden. (Der Rückgabetyp ist leider kein Unterschied.)
    Du kannst also ein
    suchen(int id)
    und ein
    suchen(CString Anfrage)
    haben.

    Und entweder kümmerst du dich da drinne um die Umwandlung in CString - oder du sucht da, dann kannst du dir auch das atoi sparen.

    Okay? 🙂

    PS:

    CString strZahl;
    strZahl.Format("%d");
    

Log in to reply