Laden...

Funktionsaufruf über Verschachtelte Controls

Erstellt von Martin-FFB vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.655 Views
M
Martin-FFB Themenstarter:in
8 Beiträge seit 2014
vor 4 Jahren
Funktionsaufruf über Verschachtelte Controls

Hi,

ich habe im Moment ein vermutlich total einfaches Problem, sehe aber gerade den Wald vor lauter Bäumen nicht...

ich habe ein Table-Layout-Panel in welchem ich 2 Reihen a 8 Spalten habe... in diesen habe ich dann jeweils ein Panel eingefügt und das Panel enthält ein Custom Form Control.

Jedes Custom Control enthält ein Bild, welches über die öffentliche Funktion "UpdateStatus()" in regelmäßigen abständen aktualisiert werden soll...

Erstellen tu ich das ganze so:

TableLayoutPanel TLP = new TableLayoutPanel();
Panel l = new Panel();
l.Controls.Add(new Light(uControl, new Size(l.Width, l.Height)));
TLP.Controls.Add(I, IDCOL - 1, IDROW);

Das Status-Update versuche ich dann so aufzurufen:

foreach (Control ELEMENT in PanelList[CurGrid].Controls)
{
                try { ELEMENT.Controls[0].Controls[0].UpdateStatus(); } catch { }
}

Da bekomme ich dann aber folgenden Fehler:
Fehler CS1061 "Control" enthält keine Definition für "UpdateStatus", und es konnte keine zugängliche UpdateStatus-Erweiterungsmethode gefunden werden, die ein erstes Argument vom Typ "Control" akzeptiert (möglicherweise fehlt eine using-Direktive oder ein Assemblyverweis)

Hier ist das Usercontrol:

public partial class Light : UserControl
{
        ConfigHelper INIFile = new ConfigHelper("config.ini");
        private DateTime Startzeit1 = new DateTime();
        private Size xSize = new Size(0, 0);

        private string IPAddress;
        private int Port;


        public Light(string INFOText, Size ControlSize)
        {
            InitializeComponent();

            IPAddress = INIFile.getValue(INFOText, "IP", false);
            Port = Convert.ToInt32(INIFile.getValue(INFOText, "RELAY", false));
            lbl_info.Text = INIFile.getValue(INFOText, "TITLE", false);

            xSize = ControlSize;
            IMG_01.Image = Properties.Resources.lichtaus;            
            chgSize(this, new EventArgs());
        }

        private void chgSize(object sender, EventArgs e)
        {
            this.Size = xSize;
            lbl_info.Location = new Point((int)((this.Width - lbl_info.Width) / 2), (int)(this.Height - 30));
        }

        public void UpdateStatus()
        {
            if (GetRelay(IPAddress, Port)){IMG_01.Image = Properties.Resources.lichtan;}else{IMG_01.Image = Properties.Resources.lichtaus;}
            IMG_01.Refresh();
        }

        private bool GetRelay(string queryIP, int queryPort)
        {
            try
            {
                WebRequest RelayRequest = WebRequest.Create("http://" + queryIP + ":80/relays.cgi"); RelayRequest.Credentials = new NetworkCredential("admin", "admin"); RelayRequest.Method = "POST";RelayRequest.ContentType = "";RelayRequest.ContentLength = 0;RelayRequest.Timeout = 1000;
                Stream RelayStream = RelayRequest.GetResponse().GetResponseStream();RelayStream.ReadTimeout = 1000;
                StreamReader Relayreader = new StreamReader(RelayStream, Encoding.UTF8);string RelayContent = Relayreader.ReadToEnd();Relayreader.Close();
                string Status = RelayContent.Substring(RelayContent.IndexOf("Status:") + 8, 18);
                switch (queryPort)
                {
                    case 1: if (Status.Substring(0, 1) == "1") { return true; } else { return false; }
                    case 2: if (Status.Substring(2, 1) == "1") { return true; } else { return false; }
                    case 3: if (Status.Substring(5, 1) == "1") { return true; } else { return false; }
                    case 4: if (Status.Substring(7, 1) == "1") { return true; } else { return false; }
                    case 5: if (Status.Substring(10, 1) == "1") { return true; } else { return false; }
                    case 6: if (Status.Substring(12, 1) == "1") { return true; } else { return false; }
                    case 7: if (Status.Substring(15, 1) == "1") { return true; } else { return false; }
                    case 8: if (Status.Substring(17, 1) == "1") { return true; } else { return false; }
                }
                return false;
            }
            catch
            {
                return false;
            }            
        }

}

Muss ich da n Interface für bauen??? Ne einfache Methode wäre mir lieber....

Ich dachte auch schon daran, das Timergesteuerte Update jeweils im Usercontrol auszuführen (was auch geht), das würde dann aber auch laufen, wenn die Gridview im Moment inaktiv ist und nicht benötigt wird....

Vielen Dank schon mal für Euer Feedback
Liebe Grüße
Martin

4.931 Beiträge seit 2008
vor 4 Jahren

Hallo und willkommen,

bitte packe deinen Code in C#-Tags, sonst wird sich keiner den Code genauer anschauen.

Tipp: [FAQ] Casten aber richtig: () / is / as

M
Martin-FFB Themenstarter:in
8 Beiträge seit 2014
vor 4 Jahren

Danke für den Tipp... ist geändert. Hatte die Tag-Buttons nicht im Blick...
LG
Martin

3.170 Beiträge seit 2006
vor 4 Jahren

Hallo,

innerhalb der Controls-Auflistung eines übergeordneten Elements sind Deine Objekte nur als Control bekannt, und da gibt es die Methode UpdateStatus eben nicht.

Wie Th69 schon angedeutet hat, musst Du das dann auf Deinen Typen zurück casten.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

463 Beiträge seit 2009
vor 4 Jahren
  
                switch (queryPort)  
                {  
                    case 1: if (Status.Substring(0, 1) == "1") { return true; } else { return false; }  
                    case 2: if (Status.Substring(2, 1) == "1") { return true; } else { return false; }  
                    case 3: if (Status.Substring(5, 1) == "1") { return true; } else { return false; }  
                    case 4: if (Status.Substring(7, 1) == "1") { return true; } else { return false; }  
                    case 5: if (Status.Substring(10, 1) == "1") { return true; } else { return false; }  
                    case 6: if (Status.Substring(12, 1) == "1") { return true; } else { return false; }  
                    case 7: if (Status.Substring(15, 1) == "1") { return true; } else { return false; }  
                    case 8: if (Status.Substring(17, 1) == "1") { return true; } else { return false; }  
                }  
}  

TIPP: Geht einfacher:


                switch (queryPort)
                {
                    case 1: return(Status.Substring(0 , 1) == "1");
                    case 2: return(Status.Substring(2 , 1) == "1");
                    case 3: return(Status.Substring(5 , 1) == "1");
                    case 4: return(Status.Substring(7 , 1) == "1");
                    case 5: return(Status.Substring(10, 1) == "1");
                    case 6: return(Status.Substring(12, 1) == "1");
                    case 7: return(Status.Substring(15, 1) == "1");
                    case 8: return(Status.Substring(17, 1) == "1");
                }
}
4.931 Beiträge seit 2008
vor 4 Jahren

Oder noch einfacher:


switch (queryPort)
{
    case 1: return Status[0] == '1';
    // ...
}

Aber statt dem switch würde ich persönlich ein Array benutzen (DRY):


int indices[] = { 0, 0, 2, 5, 7, 10, 12, 15, 17 };

if (queryPort >= 1 && queryPort < indices.Length)
{
    int index = indices[queryPort];
    return Status[index] == '1';
}

return false;

M
Martin-FFB Themenstarter:in
8 Beiträge seit 2014
vor 4 Jahren

Hallo und willkommen,

bitte packe deinen Code in C#-Tags, sonst wird sich keiner den Code genauer anschauen.

Tipp:
>

Wie Geil! Kaum macht man es richtig, schon Funzts…

vielen Dank!!! Es tut nun!

            foreach (Control ELEMENT in PanelList[CurGrid].Controls)
            {
                try
                {
                    Control MyControl = ELEMENT.Controls[0].Controls[0];
                    if (MyControl is Light)
                    {
                        Light myLight = (Light)MyControl;
                        myLight.UpdateStatus();
                    }
                }
                catch { }
            }
M
Martin-FFB Themenstarter:in
8 Beiträge seit 2014
vor 4 Jahren

TIPP: Geht einfacher:

  
                switch (queryPort)  
                {  
                    case 1: return(Status.Substring(0 , 1) == "1");  
                    case 2: return(Status.Substring(2 , 1) == "1");  
                    case 3: return(Status.Substring(5 , 1) == "1");  
                    case 4: return(Status.Substring(7 , 1) == "1");  
                    case 5: return(Status.Substring(10, 1) == "1");  
                    case 6: return(Status.Substring(12, 1) == "1");  
                    case 7: return(Status.Substring(15, 1) == "1");  
                    case 8: return(Status.Substring(17, 1) == "1");  
                }  
}  

Stimmt. Cool Vielen Dank!

M
Martin-FFB Themenstarter:in
8 Beiträge seit 2014
vor 4 Jahren

Oder noch einfacher:

  
switch (queryPort)  
{  
    case 1: return Status[0] == '1';  
    // ...  
}  
  

Hm... Interessant... also quasi den String direkt über einen Index zerlegen... Hatte ich noch nicht auf dem Schirm... muss ich mir mal ansehen... Danke!

Oder noch einfacher:
Aber statt dem switch würde ich persönlich ein Array benutzen (DRY):

  
int indices[] = { 0, 0, 2, 5, 7, 10, 12, 15, 17 };  
  
if (queryPort >= 1 && queryPort < indices.Length)  
{  
    int index = indices[queryPort];  
    return Status[index] == '1';  
}  
  
return false;  
  

Weil es schneller ist? Andererseits belegt es mehr Speicher, oder?

Vielen Dank
Liebe Grüße
Martin

4.931 Beiträge seit 2008
vor 4 Jahren

Weder noch, sondern wegen dem Stichwort Don't repeat yourself (DRY).

Es ist performancetechnisch (in etwa) gleich gut.
Bei Codeänderung (bzw. Erweiterung) braucht man nur eine Stelle (im Array) verändern, ohne jedesmal eine neue Codezeile hinzufügen (welche ja auch Speicher benötigt)!
Ich persönlich trenne in meinem Code soweit es geht Daten und Funktionalität (Methoden), so daß der Code selbst besser wiederverwendbar ist.

PS: Und die Indexabfrage, weil dies kürzer zu schreiben (und besser zu lesen) ist, als einen Substring-Aufruf von einem Zeichen zu benutzen.

M
Martin-FFB Themenstarter:in
8 Beiträge seit 2014
vor 4 Jahren

Weder noch, sondern wegen dem Stichwort
>
.

Es ist performancetechnisch (in etwa) gleich gut.
Bei Codeänderung (bzw. Erweiterung) braucht man nur eine Stelle (im Array) verändern, ohne jedesmal eine neue Codezeile hinzufügen (welche ja auch Speicher benötigt)!
Ich persönlich trenne in meinem Code soweit es geht Daten und Funktionalität (Methoden), so daß der Code selbst besser wiederverwendbar ist.

PS: Und die Indexabfrage, weil dies kürzer zu schreiben (und besser zu lesen) ist, als einen Substring-Aufruf von einem Zeichen zu benutzen.

Prima Erklärung. Vielen Dank...
Ich werde mir das versuchen zu Herzen zu nehmen. Ist ja auch einleuchtend… Ist aber halt immer so, das man doch aus seinen alten eingefahrenen Wegen schwer rauskommt... wenn man dann eine Sprache wechselt, sucht man sich nicht die bessere Funktion sondern meist die ähnlichere und nutzt die bis zur Rente 😃 Aber ich versuche daran zu arbeiten...

Vielen Dank
Liebe Grüße
Martin (noch 13 Jahre bis zur Rente...)