myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » GUI: Windows-Forms » Objekt erstellen in anderen Klasse
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Objekt erstellen in anderen Klasse

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
Xargus Xargus ist männlich
myCSharp.de-Mitglied

Dabei seit: 22.05.2019
Beiträge: 9


Xargus ist offline

Objekt erstellen in anderen Klasse

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Leute,

ich ein Problem beim auslagern diverser Sachen aus der Form1.cs in eine andere cs. ICh möchte zur Lauzeit mein Menu aus der DB laden und deswegen lege ich dynamisch Panel und andere Objekt an. Nun ist das recht viel und ich möchte es in eine extra Klasse (Class2.cs) auslagern.

C#-Code:
using System;
using System.Windows.Forms;

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

    public static Form1 Instance { get { if (_Instance == null) _Instance = new Form1(); return _Instance; } }
    private static Form1 _Instance = null;

    private void Form1_Load(object sender, EventArgs e)
    {
      Class2.Instance.Erstelle_Panel();
    }
  }
  public partial class Class2
  {
    public static Class2 Instance { get { if (_Instance == null ) _Instance = new Class2(); return _Instance; } }
    private static Class2 _Instance = null;

    public void Erstelle_Panel()
    {
      Panel HP = (Panel)Form1.Instance.panelHaupt;
      Panel p = new Panel();
      p.Name = "Panel";
      p.Top = 10;
      p.Left = 0;
      p.Width = HP.Width;
      p.Height = 20;
      p.BackColor = System.Drawing.Color.Red;
      p.Parent = HP;
      p.Visible = true;
      p.Show();
    }
  }
}

Dabei fällt mir auf, dass in der drittletzen Zeile "p.Parent" einfach p.visible auf false gesetzt wird. Und in der vorletzten Zeile wird visible = true einfach ignoriert.

Wer kann mir helfen, den Fehler zu beheben?
Danke schon mal im Voraus.

Xargus
Neuer Beitrag 14.07.2019 14:13 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 13.052
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

"einfach so" über Magie passiert nichts im Code.
Warum Visible also false sein soll, das ergibt sich hier im Code nicht.

Code wird auch niemals "einfach so" ignoriert.
Schau Dir also das Verhalten im Debugger an.
 [Artikel] Debugger: Wie verwende ich den von Visual Studio?

PS: eine saubere Singleton Implementierung macht man i.d.R. über die Lazy<T> Klasse.
Neuer Beitrag 14.07.2019 14:49 Beiträge des Benutzers | zu Buddylist hinzufügen
MrSparkle MrSparkle ist männlich
myCSharp.de-Team

avatar-2159.gif


Dabei seit: 16.05.2006
Beiträge: 5.199
Herkunft: Leipzig


MrSparkle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von Xargus:
ICh möchte zur Lauzeit mein Menu aus der DB laden und deswegen lege ich dynamisch Panel und andere Objekt an.

Genau für solche Zwecke bietet sich DataBinding geradezu an. Dann könntest du dir das manuelle Erstellen und Positionieren im Code ersparen.

Du fügst das neu erstellte Panel übrigens nirgendwo hinzu, daher kann es auch nicht angezeigt werden.

Zwei Klassen als Singleton zu definieren, damit sie miteinander kommunizieren, ist nicht die richtige Herangehensweise. Siehe dazu:  [FAQ] Kommunikation von 2 Forms

Es gibt übrigens für Windows Forms ein eigenes Unterforum, ich habe den Beitrag dorthin verschoben.
Neuer Beitrag 14.07.2019 16:06 Beiträge des Benutzers | zu Buddylist hinzufügen
Xargus Xargus ist männlich
myCSharp.de-Mitglied

Dabei seit: 22.05.2019
Beiträge: 9

Themenstarter Thema begonnen von Xargus

Xargus ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Danke für die Antworten.

Ich verstehe das

Zitat:
"Du fügst das neu erstellte Panel übrigens nirgendwo hinzu, daher kann es auch nicht angezeigt werden."

nicht.
Ich gebe doch den Parent an. und das ist das Hauptpanel in der Form1.

Wie kann ich das denn beheben?
Könntest du mir da ein Code-Beispiel geben oder noch besser, meinen Code korrigieren?

Danke Xargus
Neuer Beitrag 14.07.2019 18:28 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 13.052
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Neuer Beitrag 14.07.2019 18:31 Beiträge des Benutzers | zu Buddylist hinzufügen
Xargus Xargus ist männlich
myCSharp.de-Mitglied

Dabei seit: 22.05.2019
Beiträge: 9

Themenstarter Thema begonnen von Xargus

Xargus ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

hi,

lasse ich ein Singleton weg, weiss er in Klasse2 nicht die width und das parent-object.
wenn ich durchstepe zeigt er mir das Panel ja an in der control-liste. auch wenn ich es über databindings mache. aber angezeigt wird es trotzdem nicht.

vielleicht reden wir ja an einander vorbei. Vielleicht wäre ein änderung an meinem Code hilfreich.zumindest wenn ihr ihn hier postet, so dass ich ihn sehen kann.

hab die Links durchgelesen und das meiste davon ist meckern oder kritisieren oder irgendwelche wörter in den raum geschmissen mit dennen niemand (ausser ihr) was anfangen könnt. Oder ihr streitet euch darüber ob das Sinn macht oder nicht.

Mal ein richtige Codebespiel wäre echt toll.
Danke im Voraus
Neuer Beitrag 14.07.2019 20:32 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 13.052
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Naja, wir schreiben Dir jetzt nicht Deinen Code. Das Sinn eines Forums ist die Hilfe zur Selbsthilfe.
Das heisst, wir geben Dir Hilfestellung, damit Du verstehst, woran das Problem liegt, es selbst identifizieren und selbst lösen kannst.

Dein Code hat eben zwei Defizite: das Singleton, das in der Form nicht notwendig ist.
Und dass Du das Control nicht über Add() hinzufügt. Mir zumindest wäre neu, dass das über das Parent geht.
Weiß auch nicht, woher Du das hast - die Doku zeigt das nicht.

Zitat:
lasse ich ein Singleton weg, weiss er in Klasse2 nicht die width und das parent-object.

Du wendest den Singleton auch missbräuchlich an. Ein Singleton hat einen ganz anderen Zweck.

In  [FAQ] Kommunikation von 2 Forms (direkt in diesem Thema) ist beschrieben, wie sich zwei Forms kennen sollen.
In  Zugriff auf Steuerelement aus Klasse [ink. Codebeispiel für die Kommunikation zwischen zwei Forms] gibt es Beispielcode.
Bisher hat dieses Thema tausenden Leuten erfolgreich geholfen.

Damit kannst Du 1:1 den Singleton ersetzen.
Neuer Beitrag 14.07.2019 21:08 Beiträge des Benutzers | zu Buddylist hinzufügen
Xargus Xargus ist männlich
myCSharp.de-Mitglied

Dabei seit: 22.05.2019
Beiträge: 9

Themenstarter Thema begonnen von Xargus

Xargus ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

hi Abt,

ich lasse jetzt den einen Singleton weg. übergebe das gewünschte Panel direkt mit.
Adde das neue Panel und es wird trotzdem nicht angezeigt.

C#-Code:
    public Panel p = new Panel();
    public void Erstelle_Panel(Panel HP)
    {
      HP.Controls.Add(p);
      p.Name = "Panel";
    }

Wenn ich mir die Links anschaue dann lese ich immer nur event und Komunikation zweier Forms. Das brauche ich doch garnicht.

ich möchte lediglich Panels erstellen und diese in eine andere *.cs auslagern.

erstelle ich die Panels in der Form1.cs dann geht das wunderbar. Nur möchte ich die ganze Menu-Erstellung und deren Funktionalitäten der Übersicht halber auslagern.
Neuer Beitrag 14.07.2019 21:48 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
MrSparkle MrSparkle ist männlich
myCSharp.de-Team

avatar-2159.gif


Dabei seit: 16.05.2006
Beiträge: 5.199
Herkunft: Leipzig


MrSparkle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich verstehe wirklich nicht, worüber du dich beschwerst. Es ist doch alles in dem verlinkten Artikel erklärt. Da geht es auch ohne Singletons. Das ganze nennt sich Objektorientierte Programmierung, und wenn man einen Begriff noch nicht gehört hat, kann man auch mal bei Google nachschlagen.

Mit deiner Herangehensweise wirst du auf Dauer immer wieder frustriert sein, und auch kaum Hilfe von anderen bekommen können, einfach weil keiner so entwickelt.

Zu deiner letzten Frage: Hast du das Haupt-Panel denn auch dem Fenster hinzugefügt?
Neuer Beitrag 14.07.2019 22:17 Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 13.052
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von Xargus:
ich möchte lediglich Panels erstellen und diese in eine andere *.cs auslagern.

Was Du da baust ist die bidirektionale Kommunikation von zwei Klassen.
Ob das Forms sind oder nicht: das Beispiel gilt trotzdem.

Willst Du keine Kommunikation, was Dein Code suggeriert und evtl. zu Verwirrung beigetragen hat, dann musst Du nochmal komplett mit den OOP Basics beginnen.

Dein Code sieht nämlich aus, dass Du Form1 inhaltlich kopiert hast und Class2 draus gemacht hast.
Hat aber nichts von Auslagern zutun.

In Forms werden dazu gerne Factories verwendet, damit UI Elemente zentral erzeugt werden.
Trotzdem müsstest Du Dich um das Erstellen von Controls nicht kümmern, wenn Du Binding verwenden würdest.
In WinForms ist das generell empfohlen; in WPF wirst Du dazu gezwungen (und das ist gut so).

C#-Code:
namespace WindowsFormsApp11
{
  public partial class Form1 : Form
  {
    private PanelFactory _panelFactory;

    public Form1() {
        _panelFactory = new PanelFactory();
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        var panel = _panelFactory.Create();
        this.Controls.Add(panel);
    }
  }

  public class PanelFactory
  {
    public Panel Create()
    {
      Panel p = new Panel();
      p.Name = "Panel";
      p.Top = 10;
      p.Left = 0;
      p.Height = 20;
      p.BackColor = System.Drawing.Color.Red;
      p.Show();

      return p;
    }
  }
}
Neuer Beitrag 14.07.2019 22:22 Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.362
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Nur zur Info:

Zitat von Abt:
Und dass Du das Control nicht über Add() hinzufügt. Mir zumindest wäre neu, dass das über das Parent geht.
Weiß auch nicht, woher Du das hast - die Doku zeigt das nicht.

Das ist aber intern ein und dasselbe (in der WinAPI gibt es nur die Funktion  SetParent dafür).
Im .NET-Code wird dafür beim Setzen von Parent Controls.Add aufgerufen (bzw. Controls.Remove wenn null zugewiesen wird):

C#-Code:
public Control Parent
{
    get
    {
        IntSecurity.GetParent.Demand();
        return this.ParentInternal;
    }
    set
    {
        this.ParentInternal = value;
    }
}

internal virtual Control ParentInternal
{
    get
    {
        return this.parent;
    }
    set
    {
        if (this.parent != value)
        {
            if (value != null)
            {
                value.Controls.Add(this);
            }
            else
            {
                this.parent.Controls.Remove(this);
            }
        }
    }
}

Und Add ruft intern SetParentHandle auf, welches dann schließlich die WinAPI-Funktion aufruft:

C#-Code:
UnsafeNativeMethods.SetParent(new HandleRef(this.window, this.Handle), new HandleRef(null, value));

PS: Und im Code von Xargus sind auch folgende beiden Zeilen äquivalent:

C#-Code:
p.Visible = true;
p.Show();

Das Tückische beim Auslesen von Visible ist, daß man jedesmal false erhält, solange das Control noch nicht wirklich angezeigt wurde (d.h. vor FormShown, also eben auch z.B. im Form.Load):

C#-Code:
public bool Visible
{
    get
    {
        return this.GetVisibleCore();
     }
     set
     {
        this.SetVisibleCore(value);
     }
}

internal const int STATE_VISIBLE = 2;

internal virtual bool GetVisibleCore()
{
    if (!this.GetState(2)) // <- per Reflection erhalten (eigentlich im Code steht STATE_VISIBLE)
    {
        return false;
    }
    return ((this.ParentInternal == null) || this.ParentInternal.GetVisibleCore());
}

Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von Th69 am 15.07.2019 11:46.

Neuer Beitrag 15.07.2019 10:15 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Xargus Xargus ist männlich
myCSharp.de-Mitglied

Dabei seit: 22.05.2019
Beiträge: 9

Themenstarter Thema begonnen von Xargus

Xargus ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

und danke für die Antworten.

Abt so ähnlich hatte ich es erst auch. Aus irgend einen Grund (sicher lag er zwischen MEINEN Ohren) ging es nicht und ich habe angefangen, hier rum zu stöbern. Dabei bin ich ja erst auf die SingleTon´s gestossen und habe diese versucht bei mir einzubauen.

Nach ein paar Stunden Links studieren und 5 hergehauenen Wörtern von euch, wars dann ganz aus und ich hab überhaupt nix mehr kapiert. Ich habs leider nicht so mit Fachbegriffen. Bin halt auch nicht studiert.... :-(

Nun hab ich es noch einmal von Grund auf neu gemacht und dein Beispiel auf meinen Code umgemünzt. Und nun geht das auch so wie ich es wollte.


Danke euch
Grüsse Xargus
Neuer Beitrag 15.07.2019 13:11 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.362
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Noch etwas:

Zitat von Abt:
In Forms werden dazu gerne Factories verwendet, damit UI Elemente zentral erzeugt werden.
Trotzdem müsstest Du Dich um das Erstellen von Controls nicht kümmern, wenn Du Binding verwenden würdest.
In WinForms ist das generell empfohlen; in WPF wirst Du dazu gezwungen (und das ist gut so).

Mit WinForms kann man nur "DataBinding" durchführen (also nur Daten an bestehende Controls binden), keine "Control Templates" (o.ä.), d.h. man muß selber Code (wie z.B. über so eine Factory) schreiben, um Controls zu erzeugen.

Und "gezwungen" halte ich auch für etwas übertrieben, aber es sollte so gemacht werden (bzw. es wird insbesondere mit MVVM so empfohlen:  [Artikel] MVVM und DataBinding).

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am 15.07.2019 14:14.

Neuer Beitrag 15.07.2019 14:11 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 3 Monate.
Der letzte Beitrag ist älter als 2 Monate.
Antwort erstellen


© Copyright 2003-2019 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 14.10.2019 08:56