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
BerndFfm
myCSharp.de - Team

Avatar #nZo9Gyth4VPDSxGqM4sT.jpg


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

beantworten | zitieren | melden

Hallo Tommy,

die Namen der Controls zur Laufzeit zusammensetzen, was Du ursprünglich machen wolltest, ist oft keine gute Lösung. Zum einen kann der Compiler nicht gut optimieren, zum anderen können Laufzeitfehler auftreten die der Compiler nicht beim Übersetzen merken kann.

Die Übertragung der angelegten Controls in ein Array, wie oben von Th69 vorgeschlagen, finde ich auch die beste Lösung : Anlegen der Controls im Designer und trotzdem Zugriff über eine Schleife.

Ich schreibe nochmal wie das aussehen kann :


TextBox[] tb = new TextBox[] { textBox1, textBox2, textBox3 };
CheckBox[] cb = new CheckBox[] { checkBox1, checkBox2, checkBox3 };
for (int i = 0; i < cb.Length; i++) tb[i].Enabled = cb[i].Checked;

Kürzer geht es kaum.

Wenn jemand eine Checkbox wieder auf unchecked setzt soll dann das zugehörige Textfeld wieder disabled werden ? Das fehlt in deinem Code.

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,

Vielen Dank für die Antworten und für den Code-Snippet.

Ich tue mich sehr schwer damit, weil ich auch nicht weiß wann was genau wo hin muss.
Jetzt habe ich wieder eine neue Variante. Funktioniert, aber ob das richtig ist weiß ich nicht.
Also nach den Programmier Regeln.


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

        private void Test_Click(object sender, EventArgs e)
        {
                TextBox[] tb = new TextBox[] { txtLocalAppName1, txtLocalAppName2, txtLocalAppName3, txtLocalAppName4, 
                txtLocalAppName5, txtLocalAppName6, txtLocalAppName7, txtLocalAppName8 };

                for (int i = 0; i < cb.Length; i++)
                {
                  tb[i].Enabled = (cb[i].Checked || string.IsNullOrEmpty(tb[i].Text));                 
                }
        }
Zitat
Wenn jemand eine Checkbox wieder auf unchecked setzt soll dann das zugehörige Textfeld wieder disabled werden ? Das fehlt in deinem Code.

Die Textboxen werden mit einem anderen Button (speichern) auf disable gesetzt wenn sie Text enthalten damit nichts geändert werden kann.
Das sind sozusagen Konfigurationstextboxen die einmal beschrieben werden.
Der TestButton wird ein Loginbutton der die Textboxen auf Enabled setzt wenn man Änderungen machen muss.

So funktioniert es wie ich es möchte. Ob es richtig ist und auch sinnvoll kann ich nicht beurteilen.

Mal eine Frage, wenn ich eine Liste erstelle und die Textboxen da rein schreibe kann ich doch über den Index auf die einzelnen
Textboxen zugreifen oder ?
Wenn ich mehrere Textboxen in einer Reihe habe plus eine Checkbox und daraus ein User Control machen würde
und dann dieses User Control (erstmal mit dem Designer) mehrmals untereinander auf der Form platziere und
dann diese User Controls in eine Liste packe, wie spreche ich dann die Textboxen in dem User Control an?
Und was wäre wenn da noch ein TabControl dazwischen liegt?

Ich werde das mal ausprobieren ich hoffe es klappt.

Ihr habt ja gesagt das ich noch einiges über die OOP lernen muss.
Es gibt sehr viel hier im I-Net und wie ich schon mal gesagt habe wird das meistens mit der Klasse Auto erklärt.
Ich werde hauptsächlich mit Verzeichnissen und Dateien arbeiten und verstehe nicht wie man OOP mit
solchen Elementen in Verbindung bringen kann. Ich hoffe ihr versteht mich was ich sagen möchte.
Ich habe schon einige Videos über OOP geschaut aber keines von den Videos kann mir behilflich sein
mit dem was ich machen möchte.
Gibt es vielleicht ein Buch was ich kaufen könnte mit dem ich OOP besser verstehen lerne?

Vielen Dank nochmal für Eure Hilfe.

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



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

Themenstarter:

beantworten | zitieren | melden

Servus,

So, ich habe noch weiter gemacht und musste feststellen das, was ich Euch beim letzten Mal geschrieben habe, ist Blödsinn,
weil ich so ja nur in dem Test_Click Event die Arrays nutzen kann.
Ich habe das jetzt mal so umgebaut das ich es auf die ganze Mainform anwenden konnte. Habe einige hundert Zeilen
Code herausschmeißen können, weil ich viele Schleifen nutzen konnte.
Ich hänge die Datei mal an, weil sie trotzdem ich sie verkleinert habe noch über 800 Zeilen hat.
Wenn Ihr möchtet, könnt Ihr mir mal Eure Meinung sagen.

Was könnten meine Fehler sein das ein User Control größer wird wie die Vorlage?
Beim Erstellen des User Controls hat es genau die gleichen Maße wie die Steuerelemente auf meiner Form.
(3 Textboxen und 2 Checkboxen in einer Reihe angeordnet.)
Ziehe ich dann, dass User Control aus der Toolbox auf die Form, ist es fast doppelt so groß.

Eine Frage hätte ich noch.
Es sind viele Zeilen Code für die Propperties.Settings in der angehängten Datei.
Könnte man das auch verkleinern? Oder sogar in eine Klasse auslagern?

Wenn ja, gehe ich weiter auf die Suche.

Vielen Dank für Eure Hilfe.

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

Avatar #dOpLzh7hN1az1g0eGRc0.jpg


Dabei seit:
Beiträge: 292

beantworten | zitieren | melden

Zitat von Tommylik
Es sind viele Zeilen Code für die Propperties.Settings in der angehängten Datei.
Könnte man das auch verkleinern? Oder sogar in eine Klasse auslagern?

Eine elegantere Alternative wäre mit dem Microsoft.Extensions.Configuration-Namespace zuarbeiten. Das kann man dann mit dem Optionspattern machen Optionsmuster in .NET oder als anderes Beispiel
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von JimStark am .
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16110

beantworten | zitieren | melden

Sorry um das zu sagen JimStark, und ich seh auch, dass das Dein Blog ist, den Du verlinkt hast, aber das ist kein gutes Beispiel.
Da sind Fehler drin wie zB static option naming, was ein Anti-Pattern ist ;-)
Siehe auch Optionsmusterleitfaden für .NET-Bibliotheksautoren
- 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: 4136

beantworten | zitieren | melden

Hallo Tommylik,

wenn du dir die Settings.Designer.cs mal (mit einem Texteditor) anschaust, dann siehst du, daß intern einfach nur der Index-Operator Item[String] der Basisklasse ApplicationSettingsBase benutzt wird, d.h. diesen kannst du also einfach selber nutzen, z.B.


for (int i = 0; i< tbLocalAppName.Length; i++) // die Arrays solltest du besser im Plural benennen: tbLocalAppNames
    tbLocalAppName[i].Text = (string)Properties.Settings.Default["LocalAppName" + (i+1)]; // für "LocalAppName" etc. könntest du dir auch Konstanten anlegen

Edit: Alternativ dazu könntest du eine eigene "Settings.cs" anlegen (ruhig auch im Unterordner Properties) mit


namespace <ProjectNamespace>.Properties
{
    internal sealed partial class Settings
    {
       // ...
    }
}
welche die Funktionalität um Methoden erweitert, z.B.


public string GetLocalAppName(int nIndex)
{
   return (string)["LocalAppName" + (nIndex+1)];
}
und diese dann aufrufen:


tbLocalAppName[i].Text  = Properties.Settings.Default.GetLocalAppName(i + 1);
(ich benutze dafür auch immer using Properties;, damit ich Properties nicht mehr explizit schreiben muß).

----

Und auch deine Click-Methoden kannst du stark verkürzen, z.B.


var textBox = sender as TextBox;
if (textBox != null)
  if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
      textBox.Text = folderBrowserDialog1.SelectedPath;
(bwz. mittels sender is TextBox textbox, s.a. [FAQ] Casten aber richtig: Boxing/Unboxing - () / is / as / Pattern Matching)

PS: Auch deine Settings-Werte könntest du als Array ablegen (anstatt individuell) - aber das machen wir im nächsten Schritt, wenn du obigen Umbau erledigt hast...
Dieser Beitrag wurde 2 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 an alle,

Vielen Dank für Eure Antworten.

@TH69

Vielen Dank für die Code Beispiele. Dadurch sind nochmal ein haufen Codezeilen rausgeflogen.
Zitat
wenn du dir die Settings.Designer.cs mal (mit einem Texteditor) anschaust, dann siehst du, daß intern einfach nur der Index-Operator Item[String] der Basisklasse ApplicationSettingsBase benutzt wird, d.h. diesen kannst du also einfach selber nutzen, z.B.

Die Items sind die "propertyName" die ich in der Settings.settings angelegt habe.

Ich habe jetzt für alle eine Schleife angelegt.


public void GetLocalPathConfigSettings()
        {
            this.txtChooseTargetPath.Text = Properties.Settings.Default.TargetPath;

            for (int i = 0; i < tbLocalAppNames.Length; i++)
            {
                tbLocalAppNames[i].Text = (string)Properties.Settings.Default["LocalAppName" + (i + 1)];
            }

            for (int i = 0; i < tbSourceFilePathLocalApps.Length; i++)
            {
                tbSourceFilePathLocalApps[i].Text = (string)Properties.Settings.Default["LocalAppFilePath" + (i + 1)];
            }

            for (int i = 0; i < tbSetPointFileLocalApps.Length; i++)
            {
                tbSetPointFileLocalApps[i].Text = (string)Properties.Settings.Default["SetPointLocalApp" + (i + 1)];
            }

            for (int i = 0; i < cbActivateLocalApps.Length; i++)
            {
                cbActivateLocalApps[i].Checked = (bool)Properties.Settings.Default["LocalAppAktiv" + (i + 1)];
            }

            for (int i = 0; i < cbActivateCode2LocalApps.Length; i++)
            {
                cbActivateCode2LocalApps[i].Checked = (bool)Properties.Settings.Default["ActivateCode2LocalApp" + (i + 1)];
            }         
          
        }

Für die Save Methoden auch.


public void SaveLocalPathConfigSettings()
        {
            Properties.Settings.Default.TargetPath = this.txtChooseTargetPath.Text;


            for (int i = 0; i < tbLocalAppNames.Length; i++)
            {
                Properties.Settings.Default["LocalAppName" + (i + 1)] = tbLocalAppNames[i].Text;
            }

            for (int i = 0; i < tbSourceFilePathLocalApps.Length; i++)
            {
                Properties.Settings.Default["LocalAppFilePath" + (i + 1)] = tbSourceFilePathLocalApps[i].Text;
            }

            for (int i = 0; i < tbSetPointFileLocalApps.Length; i++)
            {
                Properties.Settings.Default["SetPointLocalApp" + (i + 1)] = tbSetPointFileLocalApps[i].Text;
            }

            for (int i = 0; i < cbActivateLocalApps.Length; i++)
            {
                Properties.Settings.Default["LocalAppAktiv" + (i + 1)] = cbActivateLocalApps[i].Checked;
            }

            for (int i = 0; i < cbActivateCode2LocalApps.Length; i++)
            {
                Properties.Settings.Default["ActivateCode2LocalApp" + (i + 1)] = cbActivateCode2LocalApps[i].Checked;
            }

            Properties.Settings.Default.Save();
        }
Zitat
Edit: Alternativ dazu könntest du eine eigene "Settings.cs" anlegen (ruhig auch im Unterordner Properties) mit
namespace <ProjectNamespace>.Properties

Das habe ich gemacht aber das war es schon dafür brauche ich sehr viel Zeit.
Mein Problem ist zu verstehen wo was hingehört.

Es gibt zum Beispiel die Regel das man aus einer Klasse nicht auf die Controls zugreifen soll sondern Events dafür nutzt.
Man ist das kompliziert.
In der SPS zum Beispiel wenn ein Baustein zu groß wird kann ich einfach einen Teil raus nehmen
und in einen anderen Baustein packen und den Baustein dann aufrufen.

Unter anderem bin ich dabei dies hier zu lesen.
[FAQ] Kommunikation von 2 Forms
und das hier.
Zugriff von anderer Klasse auf Window Control

Aber es wäre toll wenn ich es schaffen würde alles was mit den Properties.Settings zu tun hat in die Settings.cs auszulagern.
Zitat
(ich benutze dafür auch immer using Properties;, damit ich Properties nicht mehr explizit schreiben muß).

Darüber finde ich kein Beispiel das mir das erklärt.
Zitat
Und auch deine Click-Methoden kannst du stark verkürzen, z.B.

Da hast du mir ja die Arbeit netter Weise abgenommen vielen Dank.


private void ChooseSourcePathLocalApp_Click(object sender, EventArgs e)
        {
            var textBox = sender as TextBox;

            if (textBox != null)
            {
                if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
                {
                    textBox.Text = folderBrowserDialog1.SelectedPath;
                }
            }
        }

Aber vielen Dank für die tolle Hilfe und die Code-Snippets

Grüße Tommylik
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Tommylik am .
Attachments
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4136

beantworten | zitieren | melden

Ja, so sieht dein Code doch schon viel übersichtlicher aus.
Zitat von "Tommylik"
Aber es wäre toll wenn ich es schaffen würde alles was mit den Properties.Settings zu tun hat in die Settings.cs auszulagern.
Den ganzen Code wirst du nicht direkt auslagern können, da du ja auf die Controls der Form-Klasse zugreifst. Du könntest jedoch das jeweilige Array als Methodenparameter übergeben, so daß der Aufruf nur noch so aussieht:


var settings = Properties.Settings.Default;

settings.SetControlTexts(tbLocalAppNames, "LocalAppName");
settings.SetControlTexts(tbSourceFilePathLocalApps, "LocalAppFilePath");
// ...
settings.SetCheckBoxes(cbActivateLocalApps, "LocalAppAktiv");
// ...
Die Methodenparameter für die ausgelagerten Methoden dann als Control[] bzw. CheckBox[] deklarieren und die Schleife entsprechend anpassen.
Und ähnliche Methoden dann zum Setzen der Settings-Werte, z.B. SaveControlTexts(...).

Alternativ oben in deiner Datei


namespace PDE
{
    using Properties; // <-- hier einfügen

    // ...
}
und dann nur noch Settings.Default benutzen, anstatt (jedesmal) Properties.Settings.Default (das meinte ich mit "damit ich Properties nicht mehr explizit schreiben muß").
Durch meine obige Variable settings habe ich jedoch auch den Code entsprechend verkürzt.

Im Designer für die Settings-Werte (Settings.Designer.cs) gibt es oben den Button "View Code", welcher eine entsprechende Settings.cs in deinem Projekt anlegt (mit etwas auskommentierten Code), in der du dann zusätzlich diese Methoden implementieren kannst.

PS: Zum Thema "Zugriff von anderer Klasse auf Window Control" kannst du dir auch mal meinen längeren Artikel Kommunikation von 2 Forms durchlesen.
private Nachricht | Beiträge des Benutzers
Tommylik
myCSharp.de - Member



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

Themenstarter:

beantworten | zitieren | melden

Hallo TH69,

Vielen Dank für deine tolle Hilfe.
Zitat
PS: Zum Thema "Zugriff von anderer Klasse auf Window Control" kannst du dir auch mal meinen längeren Artikel Kommunikation von 2 Forms durchlesen.

Denn habe ich mir durchgelesen und deshalb denke ich das ich es nicht richtig umgesetzt habe.
Ich denke das mir der Eventhandler fehlt. Und wer weiß was sonst noch.
Was halt blöd ist, das es funktioniert trotzdem das ich es falsch umgesetzt habe.

Tut mir leid, dass es mit mir so schwierig ist.

Hier meine Umsetzung:

Settings.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PDE.Properties
{
    internal sealed partial class Settings
    {
        
        internal void GetLocalAppNames(TextBox[] tbLocalAppNames, string v)
        {
            for (int i = 0; i < tbLocalAppNames.Length; i++)
            {
                tbLocalAppNames[i].Text = (string)Settings.Default[v + (i + 1)];
            }

            //throw new NotImplementedException();
        }

        internal void GetSourceFilePathLocalApps(TextBox[] tbSourceFilePathLocalApps, string v)
        {
            for (int i = 0; i < tbSourceFilePathLocalApps.Length; i++)
            {
                tbSourceFilePathLocalApps[i].Text = (string)Settings.Default[v + (i + 1)];
            }

            //throw new NotImplementedException();
        }

        internal void GetSetPointFileLocalApps(TextBox[] tbSetPointFileLocalApps, string v)
        {
            for (int i = 0; i < tbSetPointFileLocalApps.Length; i++)
            {
                tbSetPointFileLocalApps[i].Text = (string)Settings.Default[v + (i + 1)];
            }

            //throw new NotImplementedException();
        }

        internal void GetActivateLocalApps(CheckBox[] cbActivateLocalApps, string v)
        {
            for (int i = 0; i < cbActivateLocalApps.Length; i++)
            {
                cbActivateLocalApps[i].Checked = (bool)Settings.Default[v + (i + 1)];
            }

            //throw new NotImplementedException();
        }

        internal void GetActivateCode2LocalApps(CheckBox[] cbActivateCode2LocalApps, string v)
        {
            for (int i = 0; i < cbActivateCode2LocalApps.Length; i++)
            {
                cbActivateCode2LocalApps[i].Checked = (bool)Settings.Default[v + (i + 1)];
            }

            //throw new NotImplementedException();
        }       

        internal void SaveLocalAppNames(TextBox[] tbLocalAppNames, string v)
        {
            for (int i = 0; i < tbLocalAppNames.Length; i++)
            {
                Settings.Default[v + (i + 1)] = tbLocalAppNames[i].Text;
            }
            //throw new NotImplementedException();
        }

        internal void SaveSourceFilePathLocalApps(TextBox[] tbSourceFilePathLocalApps, string v)
        {
            for (int i = 0; i < tbSourceFilePathLocalApps.Length; i++)
            {
                Settings.Default[v + (i + 1)] = tbSourceFilePathLocalApps[i].Text;
            }
            //throw new NotImplementedException();
        }

        internal void SaveSetPointFileLocalApps(TextBox[] tbSetPointFileLocalApps, string v)
        {
            for (int i = 0; i < tbSetPointFileLocalApps.Length; i++)
            {
                Settings.Default[v + (i + 1)] = tbSetPointFileLocalApps[i].Text;
            }
            //throw new NotImplementedException();
        }

        internal void SaveActivateLocalApps(CheckBox[] cbActivateLocalApps, string v)
        {
            for (int i = 0; i < cbActivateLocalApps.Length; i++)
            {
                Settings.Default[v + (i + 1)] = cbActivateLocalApps[i].Checked;
            }
            //throw new NotImplementedException();
        }

        internal void SaveActivateCode2LocalApps(CheckBox[] cbActivateCode2LocalApps, string v)
        {
            for (int i = 0; i < cbActivateCode2LocalApps.Length; i++)
            {
                Settings.Default[v + (i + 1)] = cbActivateCode2LocalApps[i].Checked;
            }
            //throw new NotImplementedException();
        }      
    }
}

MainForm.cs



using PDE.Properties;


namespace PDE
{
    public partial class MainForm : Form
    {
        public void GetLocalPathConfigSettings()
        {
            this.txtChooseTargetPath.Text = Settings.Default.TargetPath;

            var settings = Settings.Default;

            settings.GetLocalAppNames(tbLocalAppNames, "LocalAppName");
            settings.GetSourceFilePathLocalApps(tbSourceFilePathLocalApps, "LocalAppFilePath");
            settings.GetSetPointFileLocalApps(tbSetPointFileLocalApps, "SetPointLocalApp");
            settings.GetActivateLocalApps(cbActivateLocalApps, "LocalAppAktiv");
            settings.GetActivateCode2LocalApps(cbActivateCode2LocalApps, "ActivateCode2LocalApp");          
     }


public void SaveLocalPathConfigSettings()
        {
            var settings = Settings.Default;

            settings.SaveLocalAppNames(tbLocalAppNames, "LocalAppName");
            settings.SaveSourceFilePathLocalApps(tbSourceFilePathLocalApps, "LocalAppFilePath");
            settings.SaveSetPointFileLocalApps(tbSetPointFileLocalApps, "SetPointLocalApp");
            settings.SaveActivateLocalApps(cbActivateLocalApps, "LocalAppAktiv");
            settings.SaveActivateCode2LocalApps(cbActivateCode2LocalApps, "ActivateCode2LocalApp");

            Settings.Default.TargetPath = this.txtChooseTargetPath.Text;          

            Settings.Default.Save();
        }

Zitat
PS: Zum Thema "Zugriff von anderer Klasse auf Window Control" kannst du dir auch mal meinen längeren Artikel Kommunikation von 2 Forms durchlesen.
Ich will mal dieses Beispiel ausprobieren zum lernen:
Zitat
Für das Beispiel, daß eine SubForm den Label-Text der MainForm aktualisieren soll (z.B. um einen Status anzuzeigen) sieht der Code dann so aus:


class SubForm : Form
{
  // ...

  public class TextEventArgs : EventArgs
  {
    public TextEventArgs(string text)
    {
      Text = text; // Eigenschaft setzen
    }

    public string Text { get; set; } // Text als Eigenschaft definieren
  }

  public event EventHandler<TextEventArgs> UpdateText; // Ereignis deklarieren

  void button_Click(object sender, EventArgs e)
  {
    // ...
    
    OnUpdateText(new TextEventArgs("Test")); // Ereignis-Methode aufrufen
  }

  protected virtual void OnUpdateText(TextEventArgs e)
  {
    EventHandler<TextEventArgs> ev = UpdateText;
    if (ev != null)
      ev(this, e); // abonnierte Ereignismethode(n) aufrufen
  }
}

Zitat
Und nun muß im MainForm dann noch dieses Ereignis abonniert (zugewiesen) werden:


class MainForm : Form
{
  void button_Click(object sender, EventArgs e)
  {
    SubForm subForm = new SubForm();
    subForm.UpdateText += UpdateLabelText; // Ereignis abonnieren
    subForm.ShowDialog(this);
  }

  void UpdateLabelText(object sender, SubForm.TextEventArgs e)
  {
    labelText.Text = e.Text; // Zugriff auf Eigenschaft des Ereignisses
  }
}

Ich muss es doch schaffen diesen aha-Efekt zu bekommen.

Vielen Dank nochmal für deine besondere Hilfe.

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

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4136

beantworten | zitieren | melden

Mir scheint, du machst dir immer mehr Arbeit als nötig ist.
Du brauchst doch nicht für jedes konkrete Array eine eigene Methode (dafür sind doch die Parameter da), sondern (bisher) nur zwei verschiedene: für den Zugriff auf Text und Checked. Daher auch meine allgemeinen Namen: SetControlTexts und SetCheckBoxes.
(Du könntest jedoch weitere Hilfsmethoden erstellen, welche die Namen der Settings-Werte intern benutzen, um sie nicht beim Afurf kennen zu müssen - oder alternativ als String-Konstanten zur Verfügung stellen).

Und da du ja die Variable settings übernommen hast, kannst du diese auch für deine anderen Aufrufe (anstatt Settings.Default) benutzen - damit der Code einheitlich und übersichtlicher ist (und ein ganz, ganz kleiner Performance-Gewinn, da nicht jedesmal die Eigenschaft Default ausgelesen werden muß - aber das ist wirklich nur sekundär).

Und beim SubForm-Beispiel sollte der Aha-Effekt darin bestehen, daß diese SubForm keine Abhängigkeit zur MainForm hat, d.h. diese also nicht kennt.
So kannst du diese Klasse (bzw. Datei) auch von einer anderen Form aus aufrufen (oder sogar in einem anderen Projekt verwenden).

Und nach diesem Prinzip (Vermeidung von Abhängigkeiten bzw. Trennung von Zuständigkeiten) sollte möglichst jedes Projekt aufgebaut sein.

Ich hoffe, ich überfordere dich nicht zu sehr, aber es freut mich, daß du meine Tipps umsetzt. ;-)

Bei deinem jetzigen Code könnte man noch mehr Code einsparen (optimieren), z.B. sind deine beiden Methoden ScanLocalPathes_Tick und ScanNetPathes_Tick doch inhaltlich fast identisch, so daß du auch daraus eine Methode mit entsprechenden Parametern erzeugen könntest.
Ähnlich einige deiner anderen Methoden bzw. Copy und Move bzw. Local und Net - dafür wäre es aber hilfreich, wenn du Delegates (welche die Grundlage von Ereignissen (event) sind) verstanden hast.
private Nachricht | Beiträge des Benutzers
Tommylik
myCSharp.de - Member



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

Themenstarter:

beantworten | zitieren | melden

Hallo TH69,

Vielen Dank für deine Antwort und da muss ich dir gleich antworten.

Zitat
Mir scheint, du machst dir immer mehr Arbeit als nötig ist.

Das ist ja kein wunder da ich ja oft nicht weiß was ich tue.
Zitat
Du brauchst doch nicht für jedes konkrete Array eine eigene Methode (dafür sind doch die Parameter da), sondern (bisher) nur zwei verschiedene: für den Zugriff auf Text und Checked. Daher auch meine allgemeinen Namen: SetControlTexts und SetCheckBoxes.

Ok aber damit ich es besser verstehe und damit ich weiß wo ich ansetzen muss, das was ich umgesetzt habe ist falsch?
Verstehe ich dich richtig das ich die ganzen Methoden in der Settings.cs auf 2 Methoden einkürzen kann?
Ich tue mich halt schwer damit das was du mir als Hilfe zur Verfügung stellst an den richtigen stellen einzusetzen.
Zitat
Ich hoffe, ich überfordere dich nicht zu sehr, aber es freut mich, dass du meine Tipps umsetzt. ;-)

Nein, aber es ist auch nicht gerade ein Kinderspiel. Ich möchte halt nicht nicht aufgeben. Es macht mir spaß.
Aber jetzt mal die Gegenfrage wie viel Geduld hast?
Zitat
Bei deinem jetzigen Code könnte man noch mehr Code einsparen (optimieren),

Darüber sollten wir nachdenken wenn ich das Thema Klasse > Form verstanden habe.
Und so aufgebaut ist wie es sein sollte.

Vielen Dank für deine bisherige Hilfe, Mühe und Zeit.

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

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16110

beantworten | zitieren | melden

Zitat von Tommylik
Verstehe ich dich richtig das ich die ganzen Methoden in der Settings.cs auf 2 Methoden einkürzen kann?
Ich tue mich halt schwer damit das was du mir als Hilfe zur Verfügung stellst an den richtigen stellen einzusetzen.

Ja, damit vermeidestb Du doppelten / dreifachen... Code. Das Prinzip nennt sich DRY => Don’t repeat yourself
Du erstellst eine Methode und übergibst Referenzen, auf die dann Aktionen ausgeführt werden und kannst so die Methode entsprechend wiederverwenden.
- 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 Abt,

Vielen Dank für deine Antwort.
Zitat
Das Prinzip nennt sich DRY => Don’t repeat yourself

Das kenne ich und deswegen bin ich ja dabei das mit den Schleifen zu lernen.
Ich möchte ja selber keinen Code der sich wiederholt. Nur die Umsetzung ist halt nicht so einfach.

Dann habe ich noch eine Frage. Ich kann also alles was in der Settings.cs auf 2 Methoden einkürzen.
Ist denn was ich in der MainForm gemacht habe richtig?

Oder muss das so aussehen? Mit SetControlTexts und SetCheckBoxes


public void GetLocalPathConfigSettings()
        {         
            var settings = Settings.Default;

            settings.SetControlTexts(tbLocalAppNames, "LocalAppName");
            settings.SetControlTexts(tbSourceFilePathLocalApps, "LocalAppFilePath");
            settings.SetControlTexts(tbSetPointFileLocalApps, "SetPointLocalApp");

            settings.SetCheckBoxes(cbActivateLocalApps, "LocalAppAktiv");
            settings.SetCheckBoxes(cbActivateCode2LocalApps, "ActivateCode2LocalApp");   
        }


public void SaveLocalPathConfigSettings()
        {
            var settings = Settings.Default;

            settings.SetControlTexts(tbLocalAppNames, "LocalAppName");
            settings.SetControlTexts(tbSourceFilePathLocalApps, "LocalAppFilePath");
            settings.SetControlTexts(tbSetPointFileLocalApps, "SetPointLocalApp");

            settings.SetCheckBoxes(cbActivateLocalApps, "LocalAppAktiv");
            settings.SetCheckBoxes(cbActivateCode2LocalApps, "ActivateCode2LocalApp");           

            Settings.Default.Save();
        }
Zitat
von TH69
Die Methodenparameter für die ausgelagerten Methoden dann als Control[] bzw. CheckBox[] deklarieren

Muss das Control[] sein oder Textbox[]?

Wäre es richtig, wenn ich den folgenden Code aus der Mainform in die Settings.cs übernehme?


        private TextBox[] tbLocalAppNames;
        private TextBox[] tbSourceFilePathLocalApps;
        private TextBox[] tbSetPointFileLocalApps;
        private CheckBox[] cbActivateLocalApps;
        private CheckBox[] cbActivateCode2LocalApps;

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: 4136

beantworten | zitieren | melden

Die Methode GetLocalPathConfigSettings() sieht so korrekt aus. Nur mußt du andere Methoden (Save...) bei SaveLocalPathConfigSettings() verwenden, denn du willst dort ja die Settingswerte speichern (den Code dafür hatte ich dir doch schon gezeigt).

Ich habe extra Control[] genommen, da die Eigenschaft Text dort definiert ist (so ist diese Methode auch für andere Controls außer TextBox nutzbar) - dies ist ja eines der Prinzipien der Objektorientierung.

Die Arrays kannst (bzw. solltest) du nicht auslagern, da du diese ja von der Form-Klasse aus benutzt.
private Nachricht | Beiträge des Benutzers
Tommylik
myCSharp.de - Member



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

Themenstarter:

beantworten | zitieren | melden

Hallo Th69,

Vielen Dank für deine Antwort.
Zitat
Die Methode GetLocalPathConfigSettings() sieht so korrekt aus.

Ok wenigstens etwas obwohl es ja dein Verdienst ist.

Ich kapier es nicht wie ich diese 5 Methodenaufrufe aus der Methode GetLocalPathConfigSettings()

MainForm


public void GetLocalPathConfigSettings()
        {
            var settings = Settings.Default;

            settings.SetControlTexts(tbLocalAppNames, "LocalAppName");
            settings.SetControlTexts(tbSourceFilePathLocalApps, "LocalAppFilePath");
            settings.SetControlTexts(tbSetPointFileLocalApps, "SetPointLocalApp");

            settings.SetCheckBoxes(cbActivateLocalApps, "LocalAppAktiv");
            settings.SetCheckBoxes(cbActivateCode2LocalApps, "ActivateCode2LocalApp");
        }


hier in die 2 Methoden reinbringe.

Settings.cs


using System.Windows.Forms;

namespace PDE.Properties
{   
    internal sealed partial class Settings
    {   

#######################################################################  
        Ich denke hier brauche ich noch neue arrays aber ich weiß es nicht und das ist das was mich ärgert.
#######################################################################


        internal void SetControlTexts(Control[] tbLocalAppNames, string v) <-- //tbLocalAppNames muss falsch sein
        {
            ?
        }

        internal void SetCheckBoxes(CheckBox[] ?, string v)
        {
               for (int i = 0; i < ?.Length; i++)
              {
               ?[i].Checked = (bool)Settings.Default[v + (i + 1)];
               }
        }

Es tut mir Leid aber das überfordert mich doch, alles in der Mainform zu machen ist eine Sache
aber mit einer Klasse in Zusammenspiel ist zu viel für mich.

Das ihr Euch das alles merken könnt wo Ihr was braucht (referenzieren, instanziieren, ....usw.)

Da muss ich mir noch viele Beispiele im Internet anschauen. Kennst du ein Beispiel was mir helfen könnte?
Das ich es vielleicht dadurch erarbeiten kann.

Vielen Dank für Deine Hilfe und Geduld.

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

Avatar #avatar-2159.gif


Dabei seit:
Beiträge: 5985
Herkunft: Leipzig

beantworten | zitieren | melden

Beschäftige dich mal mit objektorientierter Programmierung. Steuerelement in der UI und Anwendungs-Einstellungen sind auch nur spezielle Fälle davon. Damit kannst du dich dann beschäftigen, wenn du die Basics beherrschst.

Arbeite am besten mal ein Buch durch, z.B. das kostenlose C#-Buch vom Rheinwerk-Verlag: Visual C# 2012 - Das umfassende Handbuch von Andreas Kühnel.

Das Forum ist besser geeignet, wenn du konkrete Fragen hast. Lernen und üben können wir dir hier nicht abnehmen.

Siehe dazu auch [Hinweis] Wie poste ich richtig?
Weeks of programming can save you hours of planning
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4136

beantworten | zitieren | melden

Die Methode SetCheckBoxes sieht doch schon richtig aus, nur daß du statt ? dort eben einen (allgemeinen) Variablennamen benutzt, z.B. checkboxes. Das konkrete Array wird ja beim Aufruf aus der MainForm-Methode mitgegeben. Und daher benötigst du auch keine weiteren Arrays in der Klasse Settings.

Aber einen kleinen Fehler habe ich jetzt noch (in deinem geänderten Code) entdeckt - innerhalb der Settings-Klasse kann man einfach mit this auf das eigene Objekt zugreifen.
So sollte also die Methode dann aussehen:


internal void SetCheckBoxes(CheckBox[] checkboxes, string settingsName)
{
    for (int i = 0; i < checkboxes.Length; i++)
    {
        checkboxes[i].Checked = (bool)this[settingsName + (i + 1)];
    }
}
(den 2. Parameter habe ich auch mal entsprechend umbenannt)
Und genauso sollte die andere Methode SetControlTexts aussehen, nur daß du dann auf Text zugreifst.

Ich stimme MrSparkle zu, du solltest mal die passenden Abschnitte in einem C#-Buch (Methoden, Parameter, Referenzen, ...) durcharbeiten (mit kleinen Testprogrammen, um das selber nachzuvollziehen).
private Nachricht | Beiträge des Benutzers