Autor Beitrag
avoid
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 230
Erhaltene Danke: 4

MSDos, WinXP32, Win764, Win10, Android, Debian
msl (mIRC edit), html & php & Java (DreamweaverMX), Basic (picaxe PE6), C (Arduino IDE), C# (vs2010,2015,2017,2019,Unity,Android Studio)
BeitragVerfasst: Sa 11.04.20 04:01 
ich möchte Control Namen "dataGridView1" dynamisch ersetzen,
damit ich den selben code für alle meine DataGridView Controls verwenden kann.

Ich hab euch hier mal ein zusammengekürztes Beispiel meines Code erstellt.
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
private Control mainsender;
private void datagridview_MouseClick(object sender, MouseEventArgs e){
    string editcontrol;
    mainsender = (Control)sender;
    if (mainsender.Name.Contains("dataGridView")){
        editcontrol = mainsender.Name;
    }
    else{
        editcontrol = "";
    }
    ContextMenu m = new ContextMenu();
    m.MenuItems.Add(new MenuItem("Löschen"new EventHandler(GridViewMenu_click)));
    m.Show(dataGridView1, new Point(e.X, e.Y));
}

private void GridViewMenu_click(object sender, EventArgs e){
    MenuItem mi = sender as MenuItem;
    if (mi.Text == "Löschen"){
        try{
            dataset_entry_Delete();
        }
        catch{
            MessageBox.Show("Kein Eintrag ausgewählt.");
        }
        dataGridView1.ClearSelection();
        dataGridView1.CurrentCell = null;
    }
}

private void dataset_entry_Delete(){
    dataSet1.Tables["Bauteile"].Rows[dataGridView1.CurrentRow.Index].Delete();
}

ein erster schritt um heraus zu finden wie ich an die nötigen daten komme war der versuch "mainsender = (Control)sender;".
damit kann ich schon mal im ersten Event das control abfragen.

nun brauche ich aber eure Hilfe um heraus zu finden wie ich "mainsender" formatieren muss um es an die stelle von "dataGridView1" im code zu bekommen.
oder kann ich evtl. sogar den Namensstring aus "editcontrol" verwenden?
und wenn das klappt muss ich noch herausfinden welche Datasettabelle im angeklickten datagridview eingebunden ist.
ich verwende dazu für jedes datagridview ein eigenes BindingSource.
im Beispiel habe ich die Tabelle "Bauteile" welche dann dynamisch ausgefüllt werden soll.

ich hoffe ihr habt wieder ein bis zwei Ideen für mich.

Moderiert von user profile iconTh69: Beitragsformatierung überarbeitet.
Moderiert von user profile iconTh69: C#-Tags hinzugefügt
Moderiert von user profile iconTh69: Titel geändert ("Frage:" entfernt).

_________________
Gute Fragen sind wie ein wissenschaftliches Experiment. Sie setzen eine Menge Wissen bereits voraus.
bitcoin:1J5dgQQp8eUy8wkUxyztBUVCkCpo5MQEQs?label=Danke
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 11.04.20 09:02 
Vergiss den Ansatz mit dem Namen, was du brauchst ist einfach nur eine passende Referenz auf das Control.
Der Ansatz mittels Control mainsender ist daher schon mal richtig, aber du benötigst ein spezielles Control, daher
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
private DataGridView dataGridView;

private void datagridview_MouseClick(object sender, MouseEventArgs e)
{
  dataGridView = sender as DataGridView; // besser als direktes Casten!
  if (dataGridView != null)
  {
    // ...
    m.Show(dataGridView, new Point(e.X, e.Y)); // <- beachte hier "dataGridView" (nicht "dataGridView1")!
  }
}

Nun kannst du in den weiteren Methoden einfach auf das DataGridView-Objekt dataGridView zugreifen (anstatt dataGridView1).

Aber Achtung: du solltest bedenken, daß so jeweils nur das zuletzt angeklickte DataGridView in der Membervariablen gespeichert wird. Wenn du den Code in einer Klasse hast, dann sollte nur jeweils 1 DataGridView das MouseClick-Ereignis abonnieren.
Eine andere Möglichkeit zumindestens für das ContextMenu ist es mittels der Eigenschaft SourceControl auf das Control zuzugreifen (und auch hier wieder passend per as casten). Dann solltest du der dataset_entry_Delete()-Methode das DataGridView als Parameter (Referenz) übergeben.

Und zu deiner 2 Frage:
Mittels DataSource hast du ja das DataSet (bzw. indirekt über BindindSource) eingebunden, d.h. auch hier kannst du wieder umgekehrt zurück-casten:
ausblenden C#-Quelltext
1:
DataSet dataSet = dataGridView.DataSource as DataSet;					

(oder eben zweiteilig über BindingSource)

PS: Beim "MenuItemClick" hast du ja auch schon den as-Operator passend benutzt (auch wenn du nicht auf null überprüft hast!).
Aber du solltest dort nicht den Menü-Namen abfragen, sondern jedes MenuItem (wie z.B. "Löschen") sollte seine eigene Ereignismethode erhalten (falls du mehrere dort verwenden möchtest) - und dann benötigst du keine Abfrage mehr.

Für diesen Beitrag haben gedankt: avoid
avoid Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 230
Erhaltene Danke: 4

MSDos, WinXP32, Win764, Win10, Android, Debian
msl (mIRC edit), html & php & Java (DreamweaverMX), Basic (picaxe PE6), C (Arduino IDE), C# (vs2010,2015,2017,2019,Unity,Android Studio)
BeitragVerfasst: Sa 11.04.20 11:45 
Der Hammer, genau das hat mir gefehlt! :D
Und sogar noch was gelernt dabei. ;)

keine sorge, ich hab ja nur eine Maus und kann nur einen klick zur gleichen zeit ausführen.
beim "MenuItemClick" prüfe ich aktuell nicht auf null weil die Einträge genau die sind die es gibt.
aber du hast recht, wenn der Focus durch irgendwas geklaut wird kann wer weiß was passieren, dann fange ich das lieber sauber ab.

So ist das leider wenn man mit Halbwissen codequellen anderer verwendet und keine Ahnung hat warum es klappt.
Ja das mit "MenuItem mi = sender as MenuItem;" macht wohl etwas ähnliches wie "Control mainsender = (Control)sender;".
Hab ich das richtig verstanden das eine (mit as) ist eine Referenz (also wie die Verknüpfung zu einer Datei) und das andere eine Kopie?
Falls nicht, kannst du mir evtl. den Unterschied für doofe erklären?

Verstehe, die ContextMenu Eigenschaft SourceControl ruft das Steuerelement ab, das das Kontextmenü anzeigt.
Also bekomme ich wiederum das DataGridView zurück.

Und wenn ich dann die Referenz auf das DataGridView habe welches angeklickt wurde und auf dem das ContextMenu angezeigt wird, dann kann ich dort die DataSource abfragen und bekomme die BindingSource raus.
Bei der brauche ich dann nur den DataMember für das ansprechen der richtigen Tabelle verwenden.

und Touchdown! :lol:

Zitat:
Aber du solltest dort nicht den Menü-Namen abfragen, sondern jedes MenuItem (wie z.B. "Löschen") sollte seine eigene Ereignismethode erhalten (falls du mehrere dort verwenden möchtest) - und dann benötigst du keine Abfrage mehr.

Hab ich nicht genau das wenn der klick auf das MenuItem "Löschen" die dataset_entry_Delete()-Methode auf ruft?
Genau so habe ich auch die anderen MenuItem gemacht, jedes hat eine eigene Methode.

Ich behandele nur den Mausklick auf alle datagridview in einer Methode und das erzeugen der ContextMenu in einer eigenen die für alle datagridview gilt.

Ich werde jetzt mal sehen wie weit ich mit deiner Hilfe komme.
Vielen Dank schon mal.

_________________
Gute Fragen sind wie ein wissenschaftliches Experiment. Sie setzen eine Menge Wissen bereits voraus.
bitcoin:1J5dgQQp8eUy8wkUxyztBUVCkCpo5MQEQs?label=Danke
avoid Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 230
Erhaltene Danke: 4

MSDos, WinXP32, Win764, Win10, Android, Debian
msl (mIRC edit), html & php & Java (DreamweaverMX), Basic (picaxe PE6), C (Arduino IDE), C# (vs2010,2015,2017,2019,Unity,Android Studio)
BeitragVerfasst: Sa 11.04.20 12:27 
very nice :)
es funktioniert alles wie ich es möchte.

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
private DataGridView mainsender; // angepasst
private void datagridview_MouseClick(object sender, MouseEventArgs e){
    string editcontrol;
    mainsender = sender as DataGridView; // angepasst
    if (mainsender.Name.Contains("dataGridView")){
        editcontrol = mainsender.Name;
    }
    else{
        editcontrol = "";
    }
    ContextMenu m = new ContextMenu();
    m.MenuItems.Add(new MenuItem("Löschen"new EventHandler(GridViewMenu_click)));
    // hier sind noch weitere MenuItems mit der selben EventHandler Methode.
    // hier sollte ich wohl die dataset_entry_Delete() eintragen anstelle von GridViewMenu_click()?
    // der zwischenschritt wirkt nun wirklich unnütz.
    m.Show(mainsender, new Point(e.X, e.Y)); // angepasst
}

private void GridViewMenu_click(object sender, EventArgs e){ // diese Methode kann dann quasi entfallen?
    MenuItem mi = sender as MenuItem;
    if (mi.Text == "Löschen"){
        try{
            dataset_entry_Delete();
        }
        catch{
            MessageBox.Show("Kein Eintrag ausgewählt.");
        }
        mainsender.ClearSelection(); // angepasst
        mainsender.CurrentCell = null// angepasst
    }
}

private void dataset_entry_Delete(){
    BindingSource bs = mainsender.DataSource as BindingSource; // neu dazu gekommen
    dataSet1.Tables[bs.DataMember].Rows[mainsender.CurrentRow.Index].Delete(); // angepasst
}

dann hab ich also wie oben kommentiert die unnütze Methode raus gelassen und nun ist es wie folgt.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
private DataGridView mainsender;
private void datagridview_MouseClick(object sender, MouseEventArgs e){
    string editcontrol;
    mainsender = sender as DataGridView;
    if (mainsender.Name.Contains("dataGridView")){
        editcontrol = mainsender.Name;
    }
    else{
        editcontrol = "";
    }
    ContextMenu m = new ContextMenu();
    m.MenuItems.Add(new MenuItem("Löschen"new EventHandler(dataset_entry_Delete)));
    m.Show(mainsender, new Point(e.X, e.Y));
}

private void dataset_entry_Delete(object sender, EventArgs e){
    try {
        BindingSource bs = mainsender.DataSource as BindingSource;
        dataSet1.Tables[bs.DataMember].Rows[mainsender.CurrentRow.Index].Delete();
    }
    catch {
        MessageBox.Show("Kein Eintrag ausgewählt.");
    }
    mainsender.ClearSelection();
    mainsender.CurrentCell = null;
}

ich bin begeistert. :)

_________________
Gute Fragen sind wie ein wissenschaftliches Experiment. Sie setzen eine Menge Wissen bereits voraus.
bitcoin:1J5dgQQp8eUy8wkUxyztBUVCkCpo5MQEQs?label=Danke
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 11.04.20 14:18 
Bzgl. dem Casten: der Unterschied von as zu (...) besteht nur dadrin, daß bei ersterem im Negativfall eine Null-Referenz zurückgegeben wird (auf die man eben abfragen kann) und bei zweiterem eine InvalidCastException wirft (die man zwar auch mittels try...catch abfangen kann, aber das ist mehr Aufwand).

Und ich meinte die Abfrage if (mi.Text == "Löschen"), aber die hast du ja jetzt entfernt.
Ich selber würde den Code noch etwas anders schreiben, so daß man nicht mehr die DataGridView-Membervariable benötigen würde, sondern als lokale Variable (mittels MenuItem kommt man an das Parent-Menü und darüber dann an dessen SourceControl).
Du könntest auch das ContextMenu einmalig (im Konstruktor) erzeugen und brauchst es nicht jedesmal wieder im MouseClick neu erzeugen) - und kannst es dir dann in einer Membervariablen speichern (zumindestens solange sich die Einträge nicht jedesmal beim Aufruf ändern).

Btw: Brauchst du jetzt überhaupt noch die Variable editcontrol?

Für diesen Beitrag haben gedankt: avoid
avoid Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 230
Erhaltene Danke: 4

MSDos, WinXP32, Win764, Win10, Android, Debian
msl (mIRC edit), html & php & Java (DreamweaverMX), Basic (picaxe PE6), C (Arduino IDE), C# (vs2010,2015,2017,2019,Unity,Android Studio)
BeitragVerfasst: Sa 11.04.20 14:46 
a so, also bei as genügt dann eine Behandlung von null. ist natürlich schöner als try/catch das stimmt schon.

das ContextMenu immer neu zu erzeugen ist so vermutlich etwas einfacher für mich.
ich benutze es ja sowohl auf Zellen als auch auf dem Hintergrund wenn es keine Einträge gibt.
so funktioniert es sogar auf dem ColumnHeader. Finde ich relativ praktisch.
Muss also nur abfragen ob null oder welche raw und kann dann die benötigten MenuItems anzeigen.
Aber ich schau mir deine Idee trotzdem mal an.

ää die Variable editcontrol brauche ich noch anderweitig, es wird noch andere Controls geben.
dafür brauche ich dann eine Möglichkeit diese zu unterscheiden.

nochmal danke für die Hilfe. :)

dann mache ich mich mal an die nächste Nuss. ;)

_________________
Gute Fragen sind wie ein wissenschaftliches Experiment. Sie setzen eine Menge Wissen bereits voraus.
bitcoin:1J5dgQQp8eUy8wkUxyztBUVCkCpo5MQEQs?label=Danke
avoid Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 230
Erhaltene Danke: 4

MSDos, WinXP32, Win764, Win10, Android, Debian
msl (mIRC edit), html & php & Java (DreamweaverMX), Basic (picaxe PE6), C (Arduino IDE), C# (vs2010,2015,2017,2019,Unity,Android Studio)
BeitragVerfasst: Di 12.05.20 02:31 
user profile iconTh69 hat folgendes geschrieben Zum zitierten Posting springen:
Du könntest auch das ContextMenu einmalig (im Konstruktor) erzeugen und brauchst es nicht jedesmal wieder im MouseClick neu erzeugen) - und kannst es dir dann in einer Membervariablen speichern (zumindestens solange sich die Einträge nicht jedesmal beim Aufruf ändern).

Jetzt hab ich begriffen was du gemeint hast.
Weil ich in einem anderem Tool auch ein Contextmenü brauche hab ich mich nochmal nach einer einfacheren variante umgesehen und ein etwas älteres Video gefunden.
www.youtube.com/watch?v=TgDKcdC7X3E
Durch das Video hab ich verstanden das ich einfach das "menuStrip" Control aus der Toolbox verwenden und einem anderen Control zuweisen kann.
Dachte bisher das damit nur Menüs am oberen Rand der Anwendung erstellt werden können und hab es darum nicht genutzt. ;)

_________________
Gute Fragen sind wie ein wissenschaftliches Experiment. Sie setzen eine Menge Wissen bereits voraus.
bitcoin:1J5dgQQp8eUy8wkUxyztBUVCkCpo5MQEQs?label=Danke