Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Anzahl Checkbox checked als Wert für for Schleife
Tommylik
myCSharp.de - Member



Dabei seit:
Beiträge: 51
Herkunft: Löwenstadt

Themenstarter:

Anzahl Checkbox checked als Wert für for Schleife

beantworten | zitieren | melden

Guten Abend,

Ich komme einfach nicht weiter mit meinem Problem.

Damit bekomme ich die Gesamtanzahl der Checkboxen auf der tabPage.


CheckBox[] controls = tpFileSave.Controls.OfType<CheckBox>().ToArray();

Und controls.Length kann ich auch für die For Schleife nutzen.


private void BtnTest_Click(object sender, EventArgs e)
        {
            CheckBox[] controls = tpFileSave.Controls.OfType<CheckBox>().ToArray();        

            for (int i = 0; i < controls.Length; i++)
            {
                Control[] c1 = this.Controls.Find("txtSourceFilePathApp" + i, true);

                string sourceFilePath = c1[0].Text;
                
                Control[] c2 = this.Controls.Find("txtFileNameApp" + i, true);

                string fileName = c2[0].Text;

...
...


Ich brauche aber nicht die Gesamtanzahl der Checkboxen sondern die Anzahl der Checkboxen die Checked sind.
Und das möchte ich der For Schleife übergeben.

Hiermit bekomme ich den Wert weiß aber nicht wie ich das der Schleife übergeben kann,
weil ich daraus nicht Length entnehmen kann.


int i = tpFileSave.Controls.OfType<CheckBox>().Count(c => c.Checked);

Wer ist bereit mir bei meinem Problem zu helfen?

Vielen Dank

Grüße Tommylik





private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16098

beantworten | zitieren | melden

Du verlierst leider kein Wort, ob Du WPF oder WinForms verwendest und hast auch nicht im entsprechenden Forenbereich den Thread erstellt.
Magst den Helfern nicht nen paar mehr Infos geben?

Meine Frage gleich vorweg: wieso verwendest Du nicht einfach Data Binding, was man immer tun sollte?

Das Zusammenbauen von Control-Namen ist eher so nen Anti-Ding. Und immer auch so nen kleiner Hinweis, dass man die Architektur / das Konzeptverständnis nich ganz so im Griff hat ;-)
[FAQ] Variablennamen zur Laufzeit zusammensetzen / Dynamisches Erzeugen von Controls
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
BerndFfm
myCSharp.de - Team

Avatar #nZo9Gyth4VPDSxGqM4sT.jpg


Dabei seit:
Beiträge: 3777
Herkunft: Frankfurt a.M.

beantworten | zitieren | melden


Ich würde das mit einem if machen :


CheckBox[] checkboxes = ...;
for (int i = 0; i < checkboxes.Length; i++)
    if (checkboxes[i].Checked)
    {
         ....
    }

Grüße Bernd
Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3
private Nachricht | Beiträge des Benutzers
Tommylik
myCSharp.de - Member



Dabei seit:
Beiträge: 51
Herkunft: Löwenstadt

Themenstarter:

beantworten | zitieren | melden

Hallo Abt,

Vielen Dank für deine Antwort.
Zitat
wieso verwendest Du nicht einfach Data Binding, was man immer tun sollte?

Jetzt meine Frage vorweg: Wie kommst du auf Data Binding wenn ich so wenig Infos gebe?

Tut mir Leid das ich den Thread im falschen Forenbereich geschrieben habe. Kannst du es ändern oder ändern lassen?
Damit ich dazu lerne warum ist es der falsche Forenbereich?

Also es ist eine WinForms. Ich habe ein tabControl mit 3 tabPages.
Die eine tabPage heißt tpFileSave. Auf diesem tabPage sind mehrer Textboxen untereinander angeordnet.
Vorne an erste Stelle ist immer eine Checkbox die diese Textboxen sozusagen aktiviert.
Die Anzahl der Schleifendurchgänge werden durch die angeklickten Checkboxen bestimmt.
Vorher hatte ich zu jeder Checkbox auch einen Button und somit auch die entsprechenden Methoden.
Bis auf einen Button habe ich alle anderen gelöscht. Jetzt soll das alles mit einem Button ablaufen.

Ich hoffe diese Info ist ausreichend.

Grüße Tommylik

private Nachricht | Beiträge des Benutzers
Papst
myCSharp.de - Experte



Dabei seit:
Beiträge: 385
Herkunft: Kassel

beantworten | zitieren | melden

Zitat von Tommylik
Jetzt meine Frage vorweg: Wie kommst du auf Data Binding wenn ich so wenig Infos gebe?
Die Antwort hat Abt dir gleich mitgegeben: Weil man das immer tun sollte

Mit Databinding würdest du jetzt einfach die ViewModel Instanzen zählen, bei denen die IsChecked Property true ist.

Verstehe ich richtig, dass du nur über die Checkboxen iterieren willst Checked sind, aber deren Index brauchst um Controlnamen zusammenzubauen?
Dann kannst du entweder die Lösung von BerndFfm nehmen oder auf etwas Linq zurückgreifen. Databinding wäre aber trotzdem zu empfehlen - damit würdest du die Logik auch anschaulicher bekommen.


CheckBox[] checkboxes = ...;
var boxes =  checkboxes.Select((checkbox, idx) => new { Index = idx, Box = checkbox }).Where(checkbox => checkBox.Box.Checked);
foreach (var box in boxes)
{

}

private Nachricht | Beiträge des Benutzers
BerndFfm
myCSharp.de - Team

Avatar #nZo9Gyth4VPDSxGqM4sT.jpg


Dabei seit:
Beiträge: 3777
Herkunft: Frankfurt a.M.

beantworten | zitieren | melden

Ich verstehe auch nicht was da im Code genau gemacht werden soll.

Ich denke das kann man viel eleganter oder einfacher machen.


string sourceFilePath = ""; if (cbSourceFile.Checked) sourceFilePath = txtSourceFilePath.Text;
string fileName = "";       if (cbFileNameApp.Checked) fileName = txtFileNameApp.Text;
...

Das wären 30 Zeilen bei 30 Checkboxen.

Grüße Bernd
Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3
private Nachricht | Beiträge des Benutzers
Tommylik
myCSharp.de - Member



Dabei seit:
Beiträge: 51
Herkunft: Löwenstadt

Themenstarter:

beantworten | zitieren | melden

Hallo Bernd,

Vielen Dank für deine Antwort.

Dein Beispiele schaue ich mir mal an mal sehen ob ich es vervollständigen kann.

@Papst

Auch dir vielen Dank für deine Hilfe.
Zitat
Mit Databinding würdest du jetzt einfach die ViewModel Instanzen zählen, bei denen die IsChecked Property true ist.
Data Binding muss ich mir erstmal anschauen weiß ich noch gar nichts drüber.
Zitat
Verstehe ich richtig, dass du nur über die Checkboxen iterieren willst Checked sind, aber deren Index brauchst um Controlnamen zusammenzubauen?

Ja:
Wie viele Checkboxen sind aktiviert und der Wert soll dann der For Schleife übergeben werden.


​for (int i = 0; i < "AnzahlCheckboxen.checked".Length; i++)

Nein:
Ich weiß jetzt nicht genau was du mit Controlnamen zusammenzubauen meinst aber
ich würde dazu sagen das der String-Wert aus der TextBox "txtSourceFilePathApp" + #Index der Checkbox die aktiviert ist, an die string Variable "sourceFilePath" übergeben wird.


Control[] c1 = this.Controls.Find("txtSourceFilePathApp" + i, true);
                string sourceFilePath = c1[0].Text;             


Hier nochmal der ganze Code.


private void BtnTest_Click(object sender, EventArgs e)
        {          
           ======================================
            Das kommt weg weil Gesamtanzahl kann ich nicht gebrauchen.
            CheckBox[] controls = tpFileSave.Controls.OfType<CheckBox>().ToArray();            
            
            ======================================

            for (int i = 0; i < "AnzahlCheckboxen.checked".Length; i++)
            {
                Control[] c1 = this.Controls.Find("txtSourceFilePathApp" + i, true);
                string sourceFilePath = c1[0].Text;                

                Control[] c2 = this.Controls.Find("txtFileNameApp" + i, true);
                string fileName = c2[0].Text;                

                Control[] c3 = this.Controls.Find("txtExtApp" + i, true);
                string ext = c3[0].Text; 

                ComponentResult cr = LeakResult();

                string praegeCodeNrFileName = cr.PraegeCode;
                string praegeCodeNrFolderName = cr.FolderName;          
                string targetPath = txtChooseTargetPath.Text;

                MoveFiles(sourceFilePath, targetPath, praegeCodeNrFolderName);
                DummyDatei(praegeCodeNrFolderName, praegeCodeNrFileName, fileName, targetPath, ext);
            }

        }

Zitat
oder auf etwas Linq zurückgreifen

Ich denke wenn du auch schon Databinding empfiehlst sollte ich nicht mit Linq anfangen.
Was bedeuten eigentlich diese beiden Pfeile? Ich habe nachgelesen es sind Lambda Expression aber was sagen sie aus?

nochmal
@Bernd

Ich hoffe du verstehst es jetzt besser.

Vielen Dank nochmal für Eure Hilfe.

Grüße Tommylik





Attachments
private Nachricht | Beiträge des Benutzers
chilic
myCSharp.de - Experte



Dabei seit:
Beiträge: 2135

beantworten | zitieren | melden

Zitat
Hiermit bekomme ich den Wert weiß aber nicht wie ich das der Schleife übergeben kann, weil ich daraus nicht Length entnehmen kann.
Ist nicht das i das du hier erhältst schon genau diese Anzahl?

Nächster Punkt. Dein Code sieht für mich aus als bräuchtest du nicht nur die Zahl der angehakten Checkboxen, sondern solltest auch wissen welche das sind.
Also solltest du trotzdem alle durchlaufen und in der Schleife aber nur diejenigen berücksichtigen die Checked sind.
Sonst würdest du bei einer angehakten Checkbox mit dem Zähler 1 in deine Schleife gehen und *immer* nur Textbox 0 ansprechen, *egal welche Checkbox* angehakt ist.

Statt dem Gebastel mit den Namen könntest du alle Checkboxen und Textboxen jeweils in ein Array oder eine Liste packen. Dann kannst du mit Index auf diese Elemente zugreifen und brauchst nicht ständig mit Controls.Find hantieren.

Dann *irgendwann später* wenn du verstanden hast was du da tust und wie man Listen, Array etc. benutzt, kannst du dir ansehen was Databinding und Linq ist.
Aber bitte alles der Reihe nach verstehen. Kein Arbeitgeber will von dir hören dass du weißt wie man Linq schreibt und deshalb nicht mehr wissen musst was ein Array ist.
private Nachricht | Beiträge des Benutzers
ClaraSoft
myCSharp.de - Member



Dabei seit:
Beiträge: 35

beantworten | zitieren | melden

Zitat von Tommylik
Zitat
oder auf etwas Linq zurückgreifen

Ich denke wenn du auch schon Databinding empfiehlst sollte ich nicht mit Linq anfangen.
Was bedeuten eigentlich diese beiden Pfeile? Ich habe nachgelesen es sind Lambda Expression aber was sagen sie aus?

Mit den geposteten Linqquery kannst alle unchecked Checkbox aus dem Array herausfiltern, so dass nur noch die Checkboxen mit dem entsprechenden Index übrig bleiben, die checked sind.
Wenn dir die Lösung zu komplizierst ist, dann hat Bernd auch schon eine gepostet. Du kannst auch einfach über die Checkbox iterieren und prüfen ob eine Checkbox checked ist oder nicht nicht. Ein Objekt vom Typ Checkbox bsitzt eine boolean Variable Checked, die true oder false sein. Ist der Wert true ist die Checkbox markiert und false dann unmarkiert.
Zitat von BerndFfm

Ich würde das mit einem if machen :


CheckBox[] checkboxes = ...;
for (int i = 0; i < checkboxes.Length; i++)
    if (checkboxes[i].Checked)
    {
         ....
    }

Grüße Bernd

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von ClaraSoft am .
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4132

beantworten | zitieren | melden

Der ganze Ansatz mittels X per Designer erstellten Check- und TextBoxen ist schon falsch (unprofessionell). Stattdessen würde man passende Container-Controls (z.B. DataGridView oder TableLayoutPanel) benutzen oder aber ein User-Control (für eine "Zeile") dafür entwickeln und diese dann dynamisch erzeugen und in einer Liste ablegen (beachte wirklich den von Abt verlinkten Artikel dazu).

PS: @BerndFfm, dein 2. Code paßt nicht zu der Anforderung.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am .
private Nachricht | Beiträge des Benutzers
JimStark
myCSharp.de - Member

Avatar #dOpLzh7hN1az1g0eGRc0.jpg


Dabei seit:
Beiträge: 292

beantworten | zitieren | melden

Solche Magic Strings solltest du sowieso vermeiden, am besten mit den Methoden die oben genannt sind.
Änderst du im Designer einen Namen,... wird es erst zur Laufzeit krachen.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16098

beantworten | zitieren | melden

Zitat von Tommylik
Data Binding muss ich mir erstmal anschauen weiß ich noch gar nichts drüber.
Data Binding ist ein Grundkonzept.
In WinForms basteln leider viele ihre UI wie Du zusammen, statt eben solches zu verwenden, weil WinForms im Gegensatz zu WPF einen dazu nicht zwingt.
Trotzdem - wie Du hier an der Resonanz der Helfer auch erkennen kannst - ist Binding der richtige Weg, der Dir vor allem in der Zukunft viel Stress und Codeaufwand ersparen und viel Logik erleichtern wird.
Es bietet sich daher immer an die Konzepte der Technologie, die man verwendet, mal durchzulesen, bevor man loslegt :-)

Da haben sich paar Leute wirklich Mühe gegeben Docs dazu zu schreiben.
Das darf man durchaus honorieren, indem man diese liest :-)
Datenbindung - Windows Forms .NET Framework

Klar, bei kurz hingeklatschen Mini-Tools wägt man immer ab, wie sauber man alles macht.
Aber ernst gemeinten Anwendungen sollte man das schon anwenden.
Zitat von Tommylik
Ich weiß jetzt nicht genau was du mit Controlnamen zusammenzubauen meinst aber
ich würde dazu sagen das der String-Wert aus der TextBox "txtSourceFilePathApp" + #Index der Checkbox die aktiviert ist, an die string Variable "sourceFilePath" übergeben wird.
Und genau das macht man nicht. Deswegen hab ich Dir den Link gegeben, in dem erklärt wird, wieso das eine schlechte Idee ist.
Magst den nicht lesen, mh? :-)
Zitat von Tommylik
Ich denke wenn du auch schon Databinding empfiehlst sollte ich nicht mit Linq anfangen.
Was bedeuten eigentlich diese beiden Pfeile? Ich habe nachgelesen es sind Lambda Expression aber was sagen sie aus?
Linq / Lambda hat nichts mit Data Binding zutun sondern ist ein Syntaxzucker, mit dem sich Abfragen vereinfachen lassen.
Ist seit >15 Jahren in der C# Sprache enthalten und sollte wirklich zum absoluten Grundfähigkeiten gehören.

Wenn Du nicht weißt was die Pfeile bedeuten, dann les doch einfach nach. Dafür gibts doch Dokumentation.
Macht doch kein Sinn, dass wir Dir nun quasi die Sätze aus den Docs rauskopieren :-)
Sprachintegrierte Abfrage (Language-Integrated Query, LINQ) in C#
Lambda expressions - C# reference

- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
BerndFfm
myCSharp.de - Team

Avatar #nZo9Gyth4VPDSxGqM4sT.jpg


Dabei seit:
Beiträge: 3777
Herkunft: Frankfurt a.M.

beantworten | zitieren | melden

Zitat von Th69
PS: @BerndFfm, dein 2. Code paßt nicht zu der Anforderung.

Ich habe erst nach längerem Studium des Source Codes verstanden dass er die Checked Checkboxes durchgehen will um dann den Namen eines Controls zusammenzubasteln um dann einen Wert zuzuweisen, mit if abgefragt.

Deshalb würde ich die Schleife und das Zusammenbasteln des Control Namens einfach weglassen und nur das if verwenden :

if (cbFileNameApp.Checked) fileName = txtFileNameApp.Text;

oder wenn das benutzt werden soll zum Verschieben von Dateien noch einfacher :

if (cbFileNameApp.Checked) MoveFiles(sourceFilePath, targetPath, praegeCodeNrFolderName);

Grüße Bernd

PS.: ich verstehe aber noch nicht genau was der Code oben genau machen soll. Es wäre gut wenn der Autor mal beschreiben würde was er überhaupt machen will.


Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4132

beantworten | zitieren | melden

Er hat X CheckBoxen mit jeweils zugehörigen TexteBoxen und möchte für jede 'checked' CheckBox eine Aktion ausführen (und da er sie anscheinend einzeln im Designer platziert und benannt hat, benutzt er dafür jetzt Controls.Find(...)).

Und alleine schon die Reihenfolge der CheckBoxen muß ja nicht zwingend zu den Indizes passen...
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am .
private Nachricht | Beiträge des Benutzers
Tommylik
myCSharp.de - Member



Dabei seit:
Beiträge: 51
Herkunft: Löwenstadt

Themenstarter:

beantworten | zitieren | melden

Guten Morgen,

Ich sage mal Danke an alle die mir geschrieben haben.

@TH69
Zitat
Stattdessen würde man passende Container-Controls (z.B. DataGridView oder TableLayoutPanel) benutzen

Ich habe mir die Mühe gemacht und habe ein TableLayoutPanel erstellt genauso wie ich es schon auf der tpSaveFile habe. Siehe Bilder.
Ich habe in beiden Fällen 4 Textboxen auf 10 Reihen mit der Checkbox vorne dran.
Damit das Tool überhaupt was machen kann, braucht man 1 aktivierte Zeile (Checkbox) mit den 4 ausgefüllten Textboxen.

Textbox1 = Applikationsname - Nur informativ, weil es möglich sein kann eine App mehrmals zu nutzen. Für den Ablauf uninteressant.
Textbox2 = Filename to save - Unter welchen Namen möchtest du die Dummy Dateien speichern.
Textbox3 = File SourcePath - Wo sind die Quelldateien die verschoben werden.
Textbox4 = Welche Dateiendung haben die Dateien.

So das muss man für jede Zeile machen die man aktiviert. Es ist ein Individuelles zusammenstellen der Strings.
Ein Beispiel von einer unserer Anlagen die 5 verschiedene Applikationen hat.
-Dadurch habe ich 5 unterschiedliche Dateinamen für die Dummy-Dateien
- 5 Quellverzeichnisse
- 3 verschiedene und 2 gleiche Dateiendungen.

Ob mit TableLayoutPanel oder ohne ich muss die Strings über die Textboxen zusammenstellen damit der Anwender
die Freiheit hat die Bezeichnungen zu nutzen wie er es möchte. Bei mir bekommen die Dummy Dateien den App-Namen.
Ein anderer Anwender möchte sie aber anders benennen dann soll er das dürfen.
Zitat
Der ganze Ansatz mittels X per Designer erstellten Check- und TextBoxen ist schon falsch (unprofessionell).

In meinem Fall jetzt, wie kann mir das TableLayoutPanel dabei behilflich sein das es besser wird.


@ JimStark

Kannst du mir sagen was für dich Magic Strings sind damit ich weiß, was ich nicht tun sollte?

@ Abt
Zitat
Magst den nicht lesen, mh? :-)

Ich habe den gelesen und jetzt schon 2 Mal, nachdem TH69 das auch erwähnt hatte.
Und du hast bestimmt auch recht, dass das der beste Weg ist. Wie du schon gesagt hast,
gehört das, was ich hier zusammen bastle zu den hingeklatschen Tools.
Es sind um die 1500 Zeilen Spaghetti Code, weil ich alles 10 Mal angelegt habe. Jede Zeile die aktiviert wird, ruft eine Methode auf.
Aber egal dafür, das ich keine Ahnung habe, bin ich aber stolz darauf, was ich geschafft habe.
Zitat
Trotzdem - wie Du hier an der Resonanz der Helfer auch erkennen kannst - ist Binding der richtige Weg, der Dir vor allem in der Zukunft viel Stress und Codeaufwand ersparen und viel Logik erleichtern wird.


Ich denke das es Angst ist das ich es nicht wieder zum Laufen bekomme, wenn ich das jetzt umbaue mit List-Controls, Linq und Data-Binding nutze was sehr kompliziert aussieht.
Das Programm ist wirklich Mini. Es verbindet sich mit der SPS. Bekommt von der SPS ein Signal.
Und verschiebt alle Dateien (aktivierte Checkbox), die im Quellverzeichnis sind in das Zielverzeichnis.


@ BerndFfm

Zitat
Es wäre gut, wenn der Autor mal beschreiben würde, was er überhaupt machen will.

Das was ich zusammengebastelt habe funktioniert ja schon.
Ich wollte die 10 Methoden, die ich aufrufe auf eine Methode einkürzen.

Dafür wollte ich nur wissen wie ich die Anzahl der gecheckten Checkboxen mit Lenght in einer For-Schleife nutzen kann.


   
      for (int i = 0; i < "AnzahlCheckboxen.checked".Length; i++)                      


So das wärs jetzt vielen Dank für die Hilfe.

Grüße Tommylik
Attachments
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4132

beantworten | zitieren | melden

Wie schon geschrieben, nützt dir die Anzahl der gecheckten CheckBoxen gar nichts, da du dann ja immer noch nicht die zugehörigen Indizes weißt (ich hoffe, du verstehst, wie unlogisch dies daher ist?).

Sind denn die 10 Reihen fix oder kann es auch mehr oder weniger geben?
Aber alleine schon das manuelle Erzeugen der einzelnen Controls im Designer ist doch viel zu aufwendig (insb. falls mal Änderungen erfolgen sollen).

Erzeuge eine Methode zum Hinzufügen einer Reihe (d.h. eine CheckBox und die vier TextBoxen - welche auch wieder mittels einer Methode implementiert sein sollte) und rufe dann in einer Schleife diese auf.

Wenn du nicht genau weißt, wie der Code dafür aussehen soll, dann schau dir in der bisherigen zugehörigen "designer.cs"-Datei den Code dafür an und kopiere ihn.

Und dann kannst du beim TableLayoutPanel die Methode GetControlFromPosition in einer Schleife aufrufen, um an die einzelnen Check- und TextBoxen zu gelangen (d.h. entsprechend casten).

Die im Designer erzeugten Sub-Controls löschst du dann wieder (außer evtl. das TableLayoutPanel).
So sollte der Gesamtcode dann wirklich minimal sein (und viel flexibler und wartbarer).

PS: Bei meinen Spielen (s. WinForms-Framework für (2-Personen) Karten-/Brettspiele) benutze ich ganz selten den Designer (nur für Dialoge oder UserControls), die Controls der MainForm erstelle ich immer dynamisch.

PPS: Magic Strings sind die hartcodierten Namen deiner Controls (d.h. wenn man im Designer mal den falschen Namen oder Index angibt, knallt dein Code).
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16098

beantworten | zitieren | melden

Zitat von Tommylik
Aber egal dafür, das ich keine Ahnung habe, bin ich aber stolz darauf, was ich geschafft habe.
Das spricht Dir auch absolut niemand ab, das darf man ruhig sein :-)

Die Helfer zeigen Dir hier, wie Du Dein Ziel besser / überhaupt lösen kannst - und dass der Ansatz von Dir vielleicht nicht der beste ist.
Aktuell hast Du ein Vorgehen (zB über den Designer) und schreibst halt sehr viel Code, der nicht notwendig ist bzw. sogar im Weg stehen kann.
Es lohnt sich also durchaus sich die entsprechenden Hinweise anzuschauen / zu verfolgen.

Kein Satz fällt hier, der Dich von der Zielerreichung abhalten soll; im Gegenteil ;-)

- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
Tommylik
myCSharp.de - Member



Dabei seit:
Beiträge: 51
Herkunft: Löwenstadt

Themenstarter:

beantworten | zitieren | melden

Hallo TH69,

Zitat
Wie schon geschrieben, nützt dir die Anzahl der gecheckten CheckBoxen gar nichts, da du dann ja immer noch nicht die zugehörigen Indizes weißt (ich hoffe, du verstehst, wie unlogisch dies daher ist?).
Leider verstehe ich es nicht. Aber, wenn du sagst, es nützt mir nicht dann will ich den Weg gar nicht weiter verfolgen.
Zitat
Sind denn die 10 Reihen fix oder kann es auch mehr oder weniger geben?
Aber alleine schon das manuelle Erzeugen der einzelnen Controls im Designer ist doch viel zu aufwendig (insb. falls mal Änderungen erfolgen sollen).
Ja die sind Fix. Aber du hast recht, es ist mühselige Feinarbeit.
Zitat
Erzeuge eine Methode zum Hinzufügen einer Reihe (d.h. eine CheckBox und die vier TextBoxen - welche auch wieder mittels einer Methode implementiert sein sollte) und rufe dann in einer Schleife diese auf.
Wenn du nicht genau weißt, wie der Code dafür aussehen soll, dann schau dir in der bisherigen zugehörigen "designer.cs"-Datei den Code dafür an und kopiere ihn.
Die eine CheckBox und die vier TextBoxen kann ich mit einem Usercontrol machen oder ist das Usercontrol schon zu viel?
Die Methode "Steuerelemente_hinzufügen füttere ich mit dem Code aus dem Designer, um es mir leicht zu machen.
Das Aufrufen mit der Schleife verstehe ich nicht so richtig da ich ja nicht weiß, wo oder wie ich den Wert für den Schleifenzähler festlegen soll.
Zitat
Und dann kannst du beim TableLayoutPanel die Methode GetControlFromPosition in einer Schleife aufrufen, um an die einzelnen Check- und TextBoxen zu gelangen (d.h. entsprechend casten).
Danke für den Link muss ich mir anschauen habe ich noch nicht gemacht.
Funktioniert die Methode auch noch wenn das TableLayoutPanel auf einem Tabcontrol platziert ist??
Zitat
PPS: Magic Strings sind die hartcodierten Namen deiner Controls (d.h. wenn man im Designer mal den falschen Namen oder Index angibt, knallt dein Code).
Meinst du mit hartkodierten Namen, wenn ich einem Steuerelement einen anderen Namen gebe als der Designer?
z.B. button1 vom Designer und ich Schreibe btnVerschiebeDateien?

Vielen Dank nochmal für deine Hilfe.

Grüße Tommylik


private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4132

beantworten | zitieren | melden

Beim TableLayoutPanel brauchst du kein UserControl, da ja jedes Control in eine eigene Zelle platziert wird (bei einem UserControl würde man eine Zeile davon erzeugen und dann jeweils in eine einspaltige TableLayoutPanel oder aber in ein Panel packen).

Und deine eigene CreateRow-Methode rufst du dann in einer Schleife 10 mal auf (am besten im Form-Konstruktor nach InitializeComponent!).
Du übergibst am besten dann die Referenz auf das TableLayoutPanel an diese Methode (oder nicht ganz so flexibel benutzt direkt das auf der TabPage platzierte TableLayoutPanel).

Wenn du dir unsicher mit dem Code dafür bist, dann kannst du ja mal deinen Versuch hier reinstellen.
Vom Prinzip aber einfach


void CreateRow(TableLayoutPanel tableLayoutPanel, int row)
{
  var checkBox = new CheckBox()
    {
         //Parent = TableLayoutPanel; // Edit: Merke gerade, daß dieses hier überflüssig ist, da es implizit durch SetCellPosition gesetzt wird
         // weitere Eigenschaften
    };
   
    panel.SetCellPosition(checkBox, new TableLayoutPanelCellPosition(0, row); // 0 ist der Spaltenindex (d.h. diesen dann in dem unteren Code entsprechend ändern!)

   // gleiches wie oben dann für die 4 TextBoxen
   // ...
]
Ob du die 10 Zeilen schon initial anlegst oder dynamisch in der Methode mußt du selbst entscheiden.

Ich hoffe, daß du dann dieses Prinzip verinnerlicht hast und bei einem nächsten Projekt (oder auch noch für andere Teile dieses Projekts) dann sofort diesen Weg benutzt, anstatt mühselig im Designer X-mal die gleichen Controls anzulegen.

Und dann wäre der nächste Schritt halt "Data Binding", d.h. daß man einem Control nur noch die Daten (als Liste o.ä.) gibt und dieses selbständig diese Daten anzeigt. Dafür eignet sich bei WinForms am besten das DataGridView - aber dann solltest du dafür ein eigenständiges Textprojekt zum Herumexperimentieren anlegen.

Viel Erfolg noch!

PS: Bzgl. der Logik: Wenn z.B. die erste und letzte CheckBox "gecheckt" sind (d.h. die Indizes 0 und 9), was nützt dir dann die Info, daß die Anzahl davon 2 ist? Die Schleife würde dann ja nur von 0 - 1 zählen.

PPS: Es geht bei den MagicStrings um die Angabe für die Controls.Find-Methode (da vom Compiler nicht überprüft werden kann, ob du die ganzen Controls auch so im Designer angelegt hast). Es gibt halt im Framework manche Methoden, welche man besser nicht (oder nur selten) nutzen sollte. Bei dieser Methode müssen ja jeweils immer alle auf der Form platzierten Controls auf Namensgleichheit überprüft werden - und das kostet auch Performance).
Dieser Beitrag wurde 4 mal editiert, zum letzten Mal von Th69 am .
private Nachricht | Beiträge des Benutzers
BerndFfm
myCSharp.de - Team

Avatar #nZo9Gyth4VPDSxGqM4sT.jpg


Dabei seit:
Beiträge: 3777
Herkunft: Frankfurt a.M.

beantworten | zitieren | melden

Ich glaube ja immer noch dass Dir die Anzahl der angeklickten Checkboxen überhaupt nichts nützt.
Das was Du oben beschrieben hast würde ich so machen :


if (checkbox1.Checked) ExecLine(txtSourceFilePathApp1, txtFileNameApp1, txtExtApp1);
if (checkbox2.Checked) ExecLine(txtSourceFilePathApp2, txtFileNameApp2, txtExtApp2);
if (checkbox3.Checked) ExecLine(txtSourceFilePathApp3, txtFileNameApp3, txtExtApp3);
if (checkbox4.Checked) ExecLine(txtSourceFilePathApp4, txtFileNameApp4, txtExtApp4);
if (checkbox5.Checked) ExecLine(txtSourceFilePathApp5, txtFileNameApp5, txtExtApp5);
if (checkbox6.Checked) ExecLine(txtSourceFilePathApp6, txtFileNameApp6, txtExtApp6);
if (checkbox7.Checked) ExecLine(txtSourceFilePathApp7, txtFileNameApp7, txtExtApp7);
if (checkbox8.Checked) ExecLine(txtSourceFilePathApp8, txtFileNameApp8, txtExtApp8);
if (checkbox9.Checked) ExecLine(txtSourceFilePathApp9, txtFileNameApp9, txtExtApp9);
if (checkbox10.Checked) ExecLine(txtSourceFilePathApp10, txtFileNameApp10, txtExtApp10);

Wenn es unbedingt eine Schleife sein muss :


for (int i = 1; i < 11; i++)
    if (((CheckBox)this.Controls("checkbox1" + i.ToString()).)Checked)
        ExecLine(this.Controls("txtSourceFilePathApp" + i.ToString()), this.Controls("txtFileNameApp1" + i.ToString()), this.Controls("txtExtApp1" + i.ToString()));

oder


for (int i = 1; i < 11; i++) ExecLine(i);

Hier besteht die Gefahr dass wenn ein Controlname falsch geschrieben ist es erst zur Laufzeit einen Fehler gibt.

Ich bin immer für die einfache Lösung.

Grüße Bernd
Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3
private Nachricht | Beiträge des Benutzers
Tommylik
myCSharp.de - Member



Dabei seit:
Beiträge: 51
Herkunft: Löwenstadt

Themenstarter:

beantworten | zitieren | melden

Guten Abend,

@ TH69
Vielen Dank für die Menge an Informationen. Es ist sehr interessant und macht viel Spaß das jetzt rauszufinden.

Hier meine ersten geh versuche mit Dynamischen Laden. Ich habe die Checkbox und die vier Textboxen genommen.
Das TabelLayoutPanel habe ich mal weggelassen. Funktioniert noch nicht so richtig.
Es wird die Checkbox angezeigt und die letzte Textbox. Die 3 Textboxen da zwischen fehlen.

Ich dachte es liegt vielleicht daran das ich das nicht im Form-Konstruktor nach InitializeComponent aufrufe,
sondern mit Button aufgerufen habe. Aber das ist egal.


public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // Variable Textboxen
        private TextBox[] myTextBoxes;
        
        private void button2_Click(object sender, EventArgs e)
        {
             CheckBox checkBox1 = new CheckBox();

            // 
            // checkBox1
            // 
            checkBox1.AutoSize = true;
            checkBox1.Location = new System.Drawing.Point(10, 115);
            checkBox1.Name = "checkBox1";
            checkBox1.Size = new System.Drawing.Size(15, 15);
            checkBox1.TabIndex = 1;
            checkBox1.Text = "checkBox1";
            checkBox1.UseVisualStyleBackColor = true;

            myTextBoxes = new TextBox[4];
            for (int i = 0; i < myTextBoxes.Length; i++)
            {

                // Neue TextBoxen erzeugen
                myTextBoxes[i] = new TextBox();

                // 
                // txtAppName
                // 
                myTextBoxes[i].Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                myTextBoxes[i].Location = new System.Drawing.Point(33, 107);
                myTextBoxes[i].Name = "txtAppName" + i;
                myTextBoxes[i].Size = new System.Drawing.Size(250, 26);
                myTextBoxes[i].TabIndex = 2;

                // 
                // txtFileNameApp
                //                 
                myTextBoxes[i].Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                myTextBoxes[i].Location = new System.Drawing.Point(292, 107);
                myTextBoxes[i].Name = "txtFileNameApp" + i;
                myTextBoxes[i].Size = new System.Drawing.Size(200, 26);
                myTextBoxes[i].TabIndex = 3;

                // 
                // txtSourceFilePathApp
                // 
                myTextBoxes[i].Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                myTextBoxes[i].Location = new System.Drawing.Point(500, 107);
                myTextBoxes[i].Name = "txtSourceFilePathApp" + i;
                myTextBoxes[i].Size = new System.Drawing.Size(280, 26);
                myTextBoxes[i].TabIndex = 4;

                // 
                // txtExtApp
                // 
                myTextBoxes[i].Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                myTextBoxes[i].Location = new System.Drawing.Point(788, 107);
                myTextBoxes[i].Name = "txtExtApp" + i;
                myTextBoxes[i].Size = new System.Drawing.Size(80, 26);
                myTextBoxes[i].TabIndex = 5;
                

                Controls.Add(checkBox1);
                // TextBox auf dem Formular plazieren
                Controls.Add(myTextBoxes[i]);

            }
        }
    }

Was ist falsch an diesem Code? Ich bekomme ja keinen Fehler. Irgendetwas mit dem Zeichnen passt da nicht.

@ BerndFfm

Vielen Dank auch dir für die ganzen Code Snippets.

Zitat
Ich glaube ja immer noch dass Dir die Anzahl der angeklickten Checkboxen überhaupt nichts nützt.
Das was Du oben beschrieben hast würde ich so machen :

Ja, das ist richtig und hat ja TH69 auch schon gesagt.

Was bedeutet ExecLine? In Google finde ich nichts was mir das erklären könnte. Visual Studio kennt es auch nicht.

Vielen Dank an alle für die tolle Hilfe.

Grüße Tommylik

private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4132

beantworten | zitieren | melden

Du verwendest für die Eigenschaften der 4 Textboxen ja immer dieselbe Variable myTextBoxes[i] (deren Werte du jeweils überschreibst), so daß du letztendlich 4 mal die letzte TextBox erzeugst.

Bei 4 individuellen TextBoxen (mit jeweils unterschiedlicher Position und Größe) solltest du 4 getrennte Aufrufe machen:


myTextBoxes = new TextBox[4];
for (int i = 0; i < myTextBoxes.Length; i++)
{
     // Neue TextBoxen erzeugen
     myTextBoxes[i] = new TextBox();
}

//
// txtAppName
//
myTextBoxes[0].Font = new Font("Consolas", 12F, FontStyle.Regular, GraphicsUnit.Point, (byte)0);
myTextBoxes[0].Location = new Point(33, 107);
//myTextBoxes[0].Name = "txtAppName" + i; // Name benötigst du für dynamisch erzeugte nicht mehr
myTextBoxes[0].Size = new Size(250, 26);
myTextBoxes[0].TabIndex = 2;

// ... analog für die weiteren TextBoxen [1]-[3]
// ...

for (int i = 0; i < myTextBoxes.Length; i++)
{
     // TextBox auf dem Formular plazieren
     Controls.Add(myTextBoxes[i]);
}

Eleganter ginge es noch mit einer eigenen Methode CreateTextBox(...) sowie den verschiedenen Positionen, Größen etc. in jeweils einem eigenen Array:


Point[] locations = { new Point(33, 107), /* ... */ };
Size[] sizes = { new Size(250, 26), /* ... */ };

for (int i = 0; i < myTextBoxes.Length; i++)
{
     myTextBoxes[i] = CreateTextBox(locations[i], size[i], /* ... */);

    Controls.Add(myTextBoxes[i]);
}
So hältst du Methoden und Daten getrennt voneinander.

PS: Mit ExecLine(...) ist einfach eine Methode gemeint, welche die Daten dann verarbeitet.
Ich halte den Code von @BerndFfm trotzdem für Frickelcode.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am .
private Nachricht | Beiträge des Benutzers
Tommylik
myCSharp.de - Member



Dabei seit:
Beiträge: 51
Herkunft: Löwenstadt

Themenstarter:

beantworten | zitieren | melden

Hallo TH69,

Ich war leider einige Zeit Arbeitstechnisch wo anders eingesetzt so das ich keine Zeit hatte.

Vielen Dank für deine letzte Antwort.
Das muss ich mir noch alles genauer anschauen und noch mehr lesen.

Aber ich habe jetzt erstmal deine Vorschlag mit dem Herumexperimentieren in angriff
genommen und will erstmal mehr mit Listen und Arrays machen.
Es bringt mir nicht Steuerelemente dynamisch erstellen zu können, wenn ich doch noch
nicht weiß wie ich z.B. alle Textboxen die auf einem TabPage sind in eine Liste bekomme.

Und ich denke das ist hier jetzt mein Problem.

Ich möchte folgendes mit einer Liste und for Schleife erledigen.


private void Test_Click(object sender, EventArgs e)
        {           
                 if (chkActivateLocalApp1.Checked)
                {
                    txtLocalAppName1.Enabled = true;                    
                }

                if (chkActivateLocalApp2.Checked)
                {
                    txtLocalAppName2.Enabled = true;                   
                }

                if (chkActivateLocalApp3.Checked)
                {
                    txtLocalAppName3.Enabled = true;                   
                }

                if (chkActivateLocalApp4.Checked)
                {
                    txtLocalAppName4.Enabled = true;                   
                }

                if (chkActivateLocalApp5.Checked)
                {
                    txtLocalAppName5.Enabled = true;                  
                }

                if (chkActivateLocalApp6.Checked)
                {
                    txtLocalAppName6.Enabled = true;                   
                }

                if (chkActivateLocalApp7.Checked)
                {
                    txtLocalAppName7.Enabled = true;                   
                }

                if (chkActivateLocalApp8.Checked)
                {
                    txtLocalAppName8.Enabled = true;                  
                }       
        }

Mein Versuch mit einer Liste und Schleife.
Wenn ich mit dem Debugger und Haltepunkte schaue sind alle Werte vorhanden wie es sein sollte
aber es wird kein Textfeld auf Enabled gesetzt.
Mit der Code Variante oben schon.

Wo ist mein Fehler??


private void Login_Click(object sender, EventArgs e)
        {
                 List<TextBox> txtLocalAppNameList = new List<TextBox>
                {
                new TextBox { Text = txtLocalAppName1.Text },
                new TextBox { Text = txtLocalAppName2.Text },
                new TextBox { Text = txtLocalAppName3.Text },
                new TextBox { Text = txtLocalAppName4.Text },
                new TextBox { Text = txtLocalAppName5.Text },
                new TextBox { Text = txtLocalAppName6.Text },
                new TextBox { Text = txtLocalAppName7.Text },
                new TextBox { Text = txtLocalAppName8.Text }
                };      

                CheckBox[] checkBoxes = new CheckBox[8];

                checkBoxes[0] = chkActivateLocalApp1;
                checkBoxes[1] = chkActivateLocalApp2;
                checkBoxes[2] = chkActivateLocalApp3;
                checkBoxes[3] = chkActivateLocalApp4;
                checkBoxes[4] = chkActivateLocalApp5;
                checkBoxes[5] = chkActivateLocalApp6;
                checkBoxes[6] = chkActivateLocalApp7;
                checkBoxes[7] = chkActivateLocalApp8;

                for (int i = 0; i < checkBoxes.Length; i++)
                {
                    if (checkBoxes[i].Checked == true)
                    {
                        txtLocalAppNameList[i].Enabled = true;                       
                    }
                }
        }

Mit dem 2. Code habe ich keinen Code mehr der sich widerholt aber dennoch viel zu viele Codezeilen.
Wie kann ich das besser machen?

Vielen Dank noch mal für deine Hilfe.

Grüße Tommylik
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16098

beantworten | zitieren | melden

Naja, Du erzeugst die Textboxen schließlich in der Methode auch immer neu und wirfst sie auch immer in eine neue Liste.
So funktioniert halt OOP nicht.

Musst schon mit Klassenvariablen arbeiten und das Zeug auch nur ein mal erzeugen.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4132

beantworten | zitieren | melden

Das steht doch in dem von Abt verlinkten Artikel [FAQ] Variablennamen zur Laufzeit zusammensetzen / Dynamisches Erzeugen von Controls, wie man es richtig macht (sogar passendes Beispiel mit einer List<TextBox>) (unter "Wie kann man - alle Warnungen im Sinn - die Designer Elemente in ein Array übertragen?").

Und genauso kannst du es dann mit den CheckBoxen machen (eigenartigerweise ist dieser Code sogar korrekt, wenn auch nicht so elegant).

Und wie Abt schrieb, wenn du die Listen dann als Klassenmember anlegst (und im Konstruktor - nach InitializeComponent() - füllst), dann werden diese auch nicht jedesmal wieder neu angelegt.

Bei dir scheinen wirklich die Grundlagen der OOP noch nicht zu sitzen.

PS: Trotzdem ist das dynamische Anlegen der Elemente viel eleganter und auch einfacher, als Dutzende von Elementen mit dem Designer zu platzieren (und deren individuellen Eigenschaften zu setzen)...
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am .
private Nachricht | Beiträge des Benutzers
Tommylik
myCSharp.de - Member



Dabei seit:
Beiträge: 51
Herkunft: Löwenstadt

Themenstarter:

beantworten | zitieren | melden

Hallo,

Vielen Dank für Eure Antworten.

Zitat
Bei dir scheinen wirklich die Grundlagen der OOP noch nicht zu sitzen.

Ich habe bisher noch nichts gefunden das mir das erklären könnte.
90% aller Videos oder Tutoriell erklären das mit der Klasse Auto.

Zitat
Und wie Abt schrieb, wenn du die Listen dann als Klassenmember anlegst (und im Konstruktor - nach InitializeComponent() - füllst), dann werden diese auch nicht jedesmal wieder neu angelegt.

Also nach dem InitializeComponent();
Ich habe das jetzt so umgesetzt:


public partial class MainForm : Form
    {      
         List<TextBox> txtLocalAppNameList = new List<TextBox>();   
         CheckBox[] checkBoxes;    

        public MainForm()
        {
            InitializeComponent();

                txtLocalAppNameList = new List<TextBox>();
                
                txtLocalAppNameList.Add(new TextBox { Text = txtLocalAppName1.Text });
                txtLocalAppNameList.Add(new TextBox { Text = txtLocalAppName2.Text });
                txtLocalAppNameList.Add(new TextBox { Text = txtLocalAppName3.Text });
                txtLocalAppNameList.Add(new TextBox { Text = txtLocalAppName4.Text });
                txtLocalAppNameList.Add(new TextBox { Text = txtLocalAppName5.Text });
                txtLocalAppNameList.Add(new TextBox { Text = txtLocalAppName6.Text });
                txtLocalAppNameList.Add(new TextBox { Text = txtLocalAppName7.Text });
                txtLocalAppNameList.Add(new TextBox { Text = txtLocalAppName8.Text });

               checkBoxes = new CheckBox[8]; 
               
                checkBoxes[0] = chkActivateLocalApp1;
                checkBoxes[1] = chkActivateLocalApp2;
                checkBoxes[2] = chkActivateLocalApp3;
                checkBoxes[3] = chkActivateLocalApp4;
                checkBoxes[4] = chkActivateLocalApp5;
                checkBoxes[5] = chkActivateLocalApp6;
                checkBoxes[6] = chkActivateLocalApp7;
                checkBoxes[7] = chkActivateLocalApp8;                     
        }

        private void Test_Click(object sender, EventArgs e)
        {      
                for (int i = 0; i < checkBoxes.Length; i++)
                {
                    if (checkBoxes[i].Checked == true)
                    {
                        txtLocalAppNameList[i].Enabled = true;                       
                    }
                }
          }

So funktioniert es auch nicht keine Ahnung warum.
Ist es wenigstens ein bisschen richtig, weil da würde ich mich echt freuen.
Man ist das kompliziert.

Grüße Tommylik
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16098

beantworten | zitieren | melden

Es ist zumindest bisschen richtiger, was OOP und die Referenzen betrifftt.
Machst das halt immer noch alles relativ statisch, was unnötig ist.

Und ehrlich gesagt ist das eigentlich nicht so super kompliziert, wenn Du das Grundprinzip von OOP und Referenzen verstehst.
Ich mein, im Endeffekt musst auch nur Abtippen was der Link, den wir Dir gegeben haben, so zeigt.

Wenn Du von allen Controls jeweils 8 Stück hast, dann erstell einfach eine For-Schleife mit 8 Durchgängen, die Dir die Controls dynamisch erstellen und auf der Form platzieren.
Über den jeweiligen Index kannst dann auf die Schwester-Controls (TextBox 8 = CheckBox 8) zugreifen; entweder über den Index selbst oder weil Du Dir das zB. in nem extra Dictionary speicherst.

Ich weiß auch ehrlich gesagt gerade nicht, wie man es noch einfacher erklären soll.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4132

beantworten | zitieren | melden

Kannst du nicht einfach mal den (Teil vom) Artikel anschauen?
So soll der Code aussehen:


TextBox[] textBoxes = new TextBox[] { this.textBox1, this.textBox2, this.textBox3 };
bzw. als Klassenmember nur


textBoxes = new TextBox[] { this.textBox1, this.textBox2, this.textBox3 };
(bzw. beides als List<TextBox>)

Das wirst du jetzt ja wohl auf deine beiden Arrays übertragen können (also nix mit neuen TextBoxen anlegen, nur Referenzen eintragen!)...
Zitat von "Tommylik"
Man ist das kompliziert.
Eigentlich nicht!
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am .
private Nachricht | Beiträge des Benutzers
Tommylik
myCSharp.de - Member



Dabei seit:
Beiträge: 51
Herkunft: Löwenstadt

Themenstarter:

beantworten | zitieren | melden

Servus,

Vielen Dank für Eure Antworten.
Zitat
Kannst du nicht einfach mal den (Teil vom) Artikel anschauen?

Habe ich, aber ich verstehe das Beispiel leider nicht wie du vielleicht gehofft hast.


TextBox[] textBoxes = new TextBox[] { this.textBox1, this.textBox2, this.textBox3 };
Keine Ahnung wo das hinkommt im Code, das steht in dem Beispiel nicht mit dabei.

Ich habe es jetzt anders gelöst.


public partial class MainForm : Form
    {
         List<TextBox> txtLocalAppNameList = new List<TextBox>();         

        public MainForm()
        {
            InitializeComponent();

            txtLocalAppNameList.Add(txtLocalAppName1);
            txtLocalAppNameList.Add(txtLocalAppName2);
            txtLocalAppNameList.Add(txtLocalAppName3);
            txtLocalAppNameList.Add(txtLocalAppName4);
            txtLocalAppNameList.Add(txtLocalAppName5);
            txtLocalAppNameList.Add(txtLocalAppName6);
            txtLocalAppNameList.Add(txtLocalAppName7);
            txtLocalAppNameList.Add(txtLocalAppName8);              
        }

        private void Test_Click(object sender, EventArgs e)
        {
                checkBoxes = new CheckBox[8];

                checkBoxes[0] = chkActivateLocalApp1;
                checkBoxes[1] = chkActivateLocalApp2;
                checkBoxes[2] = chkActivateLocalApp3;
                checkBoxes[3] = chkActivateLocalApp4;
                checkBoxes[4] = chkActivateLocalApp5;
                checkBoxes[5] = chkActivateLocalApp6;
                checkBoxes[6] = chkActivateLocalApp7;
                checkBoxes[7] = chkActivateLocalApp8;

                for (int i = 0; i < checkBoxes.Length; i++)
                {
                    if (checkBoxes[i].Checked == true)
                    {
                        txtLocalAppNameList[i].Enabled = true;
                    }
                }
        }

So funktioniert es wenigstens. Button klicken und alle Textboxen sind Enable.
Ich bin aber sehr enttäuscht ich dachte man könnte, wenn man mit Listen und Arrays arbeite, viel mehr Code Zeilen einsparen.
Meine If Konstruktion hat 42 Zeilen (siehe Beispiel oben). Jetzt sind es auch nicht viel weniger.
Na ja es funktioniert das ist die Hauptsache.

Vielen Dank für Eure Hilfe nochmal.

Grüße Tommylik
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16098

beantworten | zitieren | melden

Zitat
Ich bin aber sehr enttäuscht ich dachte man könnte, wenn man mit Listen und Arrays arbeite, viel mehr Code Zeilen einsparen.
Da musst Du aber ehrlich gesagt mit / über Dich selbst enttäuscht sein; denn das liegt eher an Dir als an der Sprache.
Technologisch funktioniert das einwandfrei; Du beachtest halt aber nicht, wie man das generell macht.
Dein Code offenbart einfach, dass Dir noch die Grundlagen fehlen. Da musst einfach noch bisschen lernen, da ist kein Meister vom Himmel gefallen.

zB hat Dein Code nicht eine einzige Umsetzung zu [FAQ] Variablennamen zur Laufzeit zusammensetzen / Dynamisches Erzeugen von Controls, was für Dein Vorhaben aber wichtig ist.
Zitat
Keine Ahnung wo das hinkommt im Code, das steht in dem Beispiel nicht mit dabei.
Dir fehlt da einfach noch das Verständnis, die Brücke aus Beispielen auf Deinen Code anwenden zu können.


TextBox[] textBoxes = new TextBox[] { this.textBox1, this.textBox2, this.textBox3 };
ist nichts anderes als Beispielcode. Du schreibst - ohne es zu merken - es halt mit der Liste.


txtLocalAppNameList.Add(txtLocalAppName1);
txtLocalAppNameList.Add(txtLocalAppName2);
txtLocalAppNameList.Add(txtLocalAppName3);
txtLocalAppNameList.Add(txtLocalAppName4);
txtLocalAppNameList.Add(txtLocalAppName5);
txtLocalAppNameList.Add(txtLocalAppName6);
txtLocalAppNameList.Add(txtLocalAppName7);
txtLocalAppNameList.Add(txtLocalAppName8);

Macht inhaltlich nichts anderes; halt wieder mit mehr Code.
Du könntest auch einfach folgendes schreiben, was dann dem Beispiel entspricht.


TextBox[] textBoxes = new TextBox[] { txtLocalAppName1, txtLocalAppName2, txtLocalAppName3, txtLocalAppName4, ... };
Aber wie gesagt; das ist einfach die Fähigkeit Beispielcode auf realen Code anwenden zu können.
Das kommt mit der Zeit, vor allem wenn man das Verständnis von Quellcode entwickelt und versteht, was man macht.
Das kann Dir leider niemand abnehmen.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers