Drag and Drop C#

  • #1
W

w1z4rd2003

Mitglied
Themenersteller
Dabei seit
04.05.2006
Beiträge
14
Reaktionspunkte
0
Hi

Kann mir jemand helfen?

Ich habe 2 Listsboxen auf einer Form. Mein Ziel ist es das ich von einer in die anderen Daten herum verschieben kann.

Code:
C#-Code: 
private void lstVereine_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {    
            if(lstVereine.Items.Count==0)
                return;
            string s = lstVereine.Items[lstVereine.IndexFromPoint(e.X,e.Y)].ToString();            
            DragDropEffects dde1=DoDragDrop(s,
                DragDropEffects.All);
            
            if(dde1 == DragDropEffects.All )
            {
                lstVereine.Items.RemoveAt(lstVereine.IndexFromPoint(e.X,e.Y));                
            }        
            
        }

private void lstAusgewählteVereine_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
        {
            if(e.Data.GetDataPresent(DataFormats.StringFormat))
            {                
                string str= (string)e.Data.GetData(DataFormats.StringFormat);
                lstVereine.Items.Add(str);                
            }
            
        }

private void lstAusgewählteVereine_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
        {
            e.Effect=DragDropEffects.All;
        } 
 


Im Designer steht in einer Listbox folgendes

C#-Code:
Code:
this.lstAusgewählteVereine.DragOver += new System.Windows.Forms.DragEventHandler(this.lstAusgewählteVereine_DragOver);
this.lstAusgewählteVereine.DragDrop += new System.Windows.Forms.DragEventHandler(this.lstAusgewählteVereine_DragDrop); 
 


und in der zweiten

C#-Code:
Code:
this.lstVereine.MouseDown += new System.Windows.Forms.MouseEventHandler(this.lstVereine_MouseDown); 



Das grösste Problem ist das in eine Listbox an einer DataSource angehängt wird und ich bekomme folgende Meldung


An unhandled exception of type->System.ArgumentException' occurred in system.windows.forms.dll

Additional information: Cannot modify the Items collection when the DataSource property is set.



MFG
w1z4rd2003
 
  • #2
Mehr Informationen wären hilfreich. Z.B.: Willst Du die Daten in der DB verändern? Das berücksichtige ich hier jetzt nicht, d.h., den PK lasse ich wegfallen. Drag&Drop funktioniert jedenfalls nicht zusammen mit gesetzter DataSource, wie Du ja schon gemerkt hast. Die Verbindung wieder zu lösen, hilft auch nicht (und wenn, wäre der Weg über Data Binding eh sinnlos). Du kannst aber die Liste von Hand füllen.

Wenn Du die Daten in der DB selbst nicht verändern willst z.B. einfach über einen DataReader. Falls Du interaktive Joins brauchst und/oder filtern willst und die Datenmenge überschaubar ist, könntest Du nötigen Tables holen und bei Bedarf lokale Views erzeugen (und die Rows dann in die ListBox eintragen). Oder Du machst eben komplett neue Abfragen bzw. schreibst eine Stored Procedure.

Einfaches Füllen einer ListBox von Hand (SQL Server); im realen Code natürlich mögliche Timeouts berücksichtigen und sonstige Fehler abfangen:

Code:
using System.Data;
using System.Data.SqlClient;

...

string connectionStr = ...

...

string queryStr =
  SELECT ProductName  +
  FROM Products JOIN Categories  + 
  ON Products.CategoryID = Categories.CategoryID  + 
  ORDER BY ProductName;

...

private void FillListBox1(string query) {
  SqlConnection connection = new SqlConnection(connectionStr);
  DataSet ds = new DataSet();
  SqlDataAdapter adapter = new SqlDataAdapter(query, connection);
  adapter.Fill(ds);

  foreach(DataRow dr in ds.Tables[0].Rows) {
    listBox1.Items.Add(dr[0].ToString());
  }
}

Drag&Drop zwischen zwei ListBox-Controls:
http://msdn.microsoft.com/library/d...rmsControlClassDoDragDropTopic.asp?frame=true
 
  • #3
In der Fehlermeldung steht doch schon was der Fehler ist. Entweder du füllst das von Hand oder du mußt das, was du einfügen willst in die DataSource einfügen.

Gruß
Christian
 
  • #4
Hi zusammen... als erstens mal danke für die Antworten

in meinem Code steht folgdendes:


Code:
private void FillListBox1(string query )
		{
			SqlConnection connection = new SqlConnection(conString);
			DataSet ds = new DataSet();
			SqlDataAdapter adapter = new SqlDataAdapter(query, connection);
			adapter.Fill(ds);

			foreach(DataRow dr in ds.Tables[0].Rows) 
			{
				lstVereine.Items.Add(dr[0].ToString());
			}
		}


SQL String

Code:
	string queryStr = SELECT tblMannschaften.Mannschaftsname  +
			FROM (tblMannschaften INNER JOIN tblKategorie  +
			ON tblMannschaften.[FK Kategorie_ID] = tblKategorie.[PK Kategorie_ID])  +
			WHERE (tblMannschaften.[FK Kategorie_ID] = ?);

Wenn ich eine Kategorie aus der Combobox auswähle wird folgendes ausgelöst

Code:
		private void cmbKategorien_SelectedIndexChanged(object sender, System.EventArgs e)
		{					
			dataSet11.tblMannschaften.MannschaftsnameColumn.Table.Clear();
			con.Open(conString,null,null,0);
			FillListBox1(queryStr);
		}

Ich bekomme aber folgendes Meldung auf die Zeile:
SqlConnection connection = new SqlConnection(conString);

Additional information: Keyword not supported:->provider'.

???'
 
  • #5
w1z4rd2003 schrieb:
Additional information: Keyword not supported:->provider'.

Dein Connection-String ist falsch. Wenn Du SqlConnection (das Beispiel war für SQL Server, wie gesagt) verwendest, steht der Provider ja fest; da gibt es kein Keyword provider. Mache es so wie vorher, was die Verbindung angeht (als die ListBox noch gefüllt wurde).

BTW: Die Daten könntest Du beim Drag&Drop auch direkt aus der angeschlossenen Tabelle (oder einer Kopie) entfernen bzw. in sie einfügen, aber das wäre hier wahrscheinlich keine besonders gute Idee. Der Weg über eine an die ListBox gebundene Standard-Collection (mit entsprechender Schnittstelle), in welche die Daten kopiert werden, wäre auch möglich. Ich würde hier eher die vorgeschlagene Variante wählen.

// Nachtrag
Du verwendest eine ComboBox, um die Kategorie auszuwählen? Dann binde diese doch an die Kategorien (tblKategorie), setze DisplayMember auf den Namen der Kategorienamen-Zeile, ValueMember auf den Namen der ID-Zeile. Wenn etwas ausgewählt wird, baust Du den Query-String zusammen [so in der Art:
string queryMansch =
  SELECT Mannschaftsname +
  FROM tblMannschaften +
  WHERE [FK Kategorie_ID] =->;
...
FillListBox1(queryMansch + comboBox.SelectedValue.ToString() +-> ORDER BY Mannschaftsname);
]
Natürlich die Listbox in FillListBox1 erst leeren.
Also mehr oder weniger die Minimallösung. Es geht zwar auch anders, aber das sollte eigentlich reichen.
 
  • #6
Hi Dings

Ich habe jetzt diesen String erstellt

Code:
string queryMansch = 
			SELECT Mannschaftsname  +
			FROM tblMannschaften  +
			WHERE [FK Kategorie_ID] =->;

Danach folgende Methode

Code:
private void FillListBox1(string queryMansch )
		{
			SqlConnection connection = new SqlConnection(queryMansch);
			DataSet ds = new DataSet();
			SqlDataAdapter adapter = new SqlDataAdapter(queryMansch, connection);
			adapter.Fill(ds);

			foreach(DataRow dr in ds.Tables[0].Rows) 
			{
				lstVereine.Items.Add(dr[0].ToString());
			}
		}


und im Ereigniss SelectedIndexChanged folgendes


Code:
private void cmbKategorien_SelectedIndexChanged(object sender, System.EventArgs e)
		{					
			dataSet11.tblMannschaften.MannschaftsnameColumn.Table.Clear();
			con.Open(conString,null,null,0);
			FillListBox1(queryMansch + cmbKategorien.SelectedValue.ToString());
		}

Bekomme aber folgender Fehler

Additional information: Format of the initialization string does not conform to specification starting at index 0.
 
  • #7
Code:
private void FillListBox1(string queryMansch )
{
  SqlConnection connection = new SqlConnection(queryMansch);

queryMansch ist der Abfrage-String, Du verwendest queryMansch als Connection-String.
Benutzt Du denn überhaupt SQL Server? Wenn nicht, kannst Du auch nicht die Sql...-Klassen verwenden.

OleDB
http://msdn.microsoft.com/library/d...brary/DEU/cpref/html/frlrfsystemdataoledb.asp

Connection-String
http://msdn.microsoft.com/library/d...oledbconnectionclassconnectionstringtopic.asp

SQL (-Server)
http://msdn.microsoft.com/library/d...y/DEU/cpref/html/frlrfsystemdatasqlclient.asp

Connection-String
http://msdn.microsoft.com/library/d...ntsqlconnectionclassconnectionstringtopic.asp

-

In cmbKategorien_SelectedIndexChanged brauchst Du keine Verbindung zu öffnen, das wird in adapter.Fill automatisch gemacht. Außerdem benutzt Du dort eh eine andere Verbindung (auf con wird in FillListBox1 gar nicht zugegriffen; dort wird lokal eine neue Verbindung - connection - erstellt). Ich nehme an, dass Du con für die ComboBox verwendest. Dann kannst Du in FillListBox1 statt connection auch con nehmen.

-

Wenn Du den ersten Teil des Abfrage-Strings mit = ' beendest:

WHERE [FK Kategorie_ID] = ';

musst Du ihn auch mit ' schließen:

FillListBox1(queryMansch + cmbKategorien.SelectedValue.ToString() + ');

Falls es sich beim Schlüssel um eine Zahl handelt (int?), kannst Du beide ' weglassen:

...
WHERE [FK Kategorie_ID] = ;

...
FillListBox1(queryMansch + cmbKategorien.SelectedValue.ToString());
 
  • #8
Ich benutze Access  :-\


Ich habs mal so codiert:

Code:
public const string conString = Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\db1.mdb;

Code:
string queryMansch = 
			SELECT Mannschaftsname  +
			FROM tblMannschaften  +
			WHERE [FK Kategorie_ID] = ;


Code:
private void FillListBox1(string conString)
		{
			OleDbConnection connection = new OleDbConnection(conString);
			DataSet ds = new DataSet();
			OleDbDataAdapter adapter = new OleDbDataAdapter(conString, connection);
			adapter.Fill(ds);

			foreach(DataRow dr in ds.Tables[0].Rows) 
			{
				lstVereine.Items.Add(dr[0].ToString());
			}
		}


und im selectedindexchanged ereigniss

Code:
FillListBox1(queryMansch + cmbKategorien.SelectedValue.ToString());

Bekomme aber jetzt diese Meldung:

Additional information: An OLE DB Provider was not specified in the ConnectionString. An example would be,->Provider=SQLOLEDB;'.
 
  • #9
Jetzt hast Du das Kind mit dem Bade ausgeschüttet, sozusagen. ;)

Code:
private void FillListBox1(string queryMansch)
{
  OleDbConnection connection = new OleDbConnection(conString);
  OleDbDataAdapter adapter = new OleDbDataAdapter(queryMansch, connection);
  DataSet ds = new DataSet();
  adapter.Fill(ds);

  foreach(DataRow dr in ds.Tables[0].Rows) 
  {
    lstVereine.Items.Add(dr[0].ToString());
  }
}

Leider ist das wahrscheinlich nicht die Ursache des Fehlers, der ja in dieser Zeile auftritt:

OleDbConnection connection = new OleDbConnection(conString);

Du hast sonst nirgendwo ein SqlConnection oder OleDbConnection-Objekt in Deinem Programm, oder? Wenn Du das Programm im Debug-Mode startest und in der Messagebox auf Break klickst, wenn der Fehler auftritt, wird doch die oben genannte Zeile markiert?

Der Connection-String sieht ok aus (vorausgesetzt, die Datei C:\db1.mdb existiert und es gibt kein Passwort; aber sonst müsste es eigentlich andere Fehlermeldungen geben). Hast Du mal probiert, über Visual Studio eine Verbindung zu erstellen (über den Server Explorer oder Tools -> Connect to Database).
Bevor Du wegen dem Drag&Drop gefragt hast, hattest Du doch schon Daten in der Listbox. Also muss es ja irgendwo, irgendwann ein korrekt initialisiertes OleDbConnection-Objekt in Deinem Programm gegeben haben.
 
  • #10
Hi Ding

Es funktioniert jetzt! :) Danke für deine Hilfe
 
  • #11
Hi Dings

Ich habe noch eine Frage!

Ich habe folgende Daten:
- Turnierbeginn (Zeit)
- Turnierschluss (Zeit)
- Anzahl Spielfelder
- Spielzeit


und dank deiner Hilfe weiss ich jetzt auch welche Mannschaft zu welcher Gruppe gehört!  :)

Ich sollte jetzt ein Plan erstellen anhand der 3 Daten die ich oben erwähnt habe.
Sodass es ungefähr so aussieht

Gruppe A
8:00 - 8:15 Mannschaft 1 - Mannschaft 2  Spielfeld 1
8:00 - 8:15 Mannschaft 3 - Mannschaft 4  Spielfeld 2

usw.

übrigens... diese Daten sind in einer DB abgespeichert

Gruss
 
  • #12
Du willst also, wenn ich das richtig verstehe, aus
- Turnierbeginn (Zeit), Turnierschluss (Zeit), Anzahl der Spielfelder, Spielzeit
- Deinen Gruppenlisten
einen Spielplan erstellen. Hmm ... ohne die Regeln (Spielmodus Gruppenspiele, Spielmodus danach, Pausen etc.) zu kennen, kann man dazu eigentlich nichts sagen. Vielleicht hast Du es aber auch anders gemeint?
 
  • #13
Ich habe mir es so vorgestellt:

Ich erstelle zuerst diese Gruppen... sagen wir mal

- Gruppe A
- Gruppe B

zu jeder Gruppe füge ich z.B 4 Mannschaften. Danach erstelle ich eine neue Gruppe Endrunde und anstatt Mannschaften füge ich Platzhalter ein. z.B 1. Gruppe A, 2. Gruppe B, 1 Gruppe B, 2 Gruppe A.

Als ich dann sozusagen dieser Spielplan habe stelle ich es mir so vor. In einer neuer Maske die geöffnet wird steht folgendes:

- eine Combobox wo ich die Gruppe auswählen kann.
- eine Combobox wo ich die Spieltage auswäheln kann.

bei Gruppe A sind es z.B 3 Spieltage da es vier Mannschaften sind

Wenn ich jetzt Gruppe A auswähle wird im unteren DataGrid folgendes angezeigt:
je nach dem welchen Spieltag ich auswähle wechseln die Teams die gegneinander spielen müssen.

- Spielfeld
- Datum
- Zeit
- Spiel (Team x - Team x)
- Heim
- Gast

In Heim und Gast wird danach das Resultat eingefügt und abgespeichert

mfg
w1z4rd2003

P.S falls du mir deine mail adresse gibst könnte ich dir die Masken als .jpg senden sodass es vielleicht besser zum verstehen ist was ich genau meine ;)
 
  • #14
Sorry, dass ich mich erst jetzt melde (und dann noch mit wenig Sinnvollem), aber ich habe leider gerade wenig Zeit. Hast Du Dir denn schon überlegt, wie Du das Programm insgesamt gestaltest? Mit gestalten meine ich den Programmaufbau selbst, nicht nur die Oberfläche. Also welche Funktionalität Du willst, welche Klassen Du brauchst, wie diese zusammenarbeiten sollen, ob und wie das Ganze prinzipiell erweiterbar sein soll (z.B. Ergebnis-Tabellen, Spielstatistiken) etc.
Falls es sich nicht nur um einen ganz simplen Gruppen-Editor handelt (wovon ich nach Deiner Frage bezüglich der Gruppen ausgegangen war), solltest Du auch schon die Gruppendaten nicht direkt in die Form setzen, sondern in - als Beispiel - einer Klasse Turnier verwalten, also das User-Interface von der eigentlichen Programmfunktionalität trennen.
 
  • #15
Hi Dings

Also wie meinst du es genau?
Ich möchte das es so aufgebaut wird:

1. Schritt Namen - Manager

- Mannschaften erfassen
- Kategorien erfassen

Dieser Manager läuft schon

2. Schritt Turnier Manager

- Gruppen erstellen
- Mannschaften auswählen und in die Gruppe zuteilen

Diese Maske hast du mir ja mal gemacht falls du dich noch erinnern kannst

3. Schritt Ergebnisse eingeben

Hier kommt jetzt warscheinlich das schwierigste an der ganzen Sache, beim öffnen des programms muss der User daten (Datum, Spielbeginn, Spielende, Anzahl Spielfelder) eingeben in einer Maske. Diese Daten werden danach in einer datenbank abgespeichert.

Ich habe es mir so vorgestellt das ich eine Combobox habe und dort die Gruppen angezeigt werden die ich im Schritt 2 erstellt habe. Beim auswählen der einzelnen Gruppe wird dann der Sielplan angezeigt für jede Gruppe anhand der Daten die in der Datenbank abgelegt wurden.


Hoffe du kannst mir helfen :)
 
Thema:

Drag and Drop C#

ANGEBOTE & SPONSOREN

Statistik des Forums

Themen
113.838
Beiträge
707.961
Mitglieder
51.491
Neuestes Mitglied
haraldmuc
Oben