Autor |
Beitrag |
Talemantros
Beiträge: 444
Erhaltene Danke: 2
Win7 Proff 64bit
C# (VS2013)
|
Verfasst: Mo 28.12.15 17:34
Hallo zusammen,
ich habe da mal wieder ein kleines Problem, welches ich leider nicht gelöst bekomme.
Wo ich noch Forms benutzt habe um Steuerelemente anzuzeigen war es kein Problem mit
C#-Quelltext
dieses zu schließen.
Nun zeige ich ja die Steuerelemte in einem UserControl an, welches geladen wird.
Wie kann ich einem Button nun sagen, dass er beim Klick das Form unter dem UserControl schließen soll?
Danke.
Viele Grüße
|
|
Ralf Jansen
Beiträge: 4705
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Di 29.12.15 15:09
Da stellt sich die Frage wieso der Button auf einem UserControl liegt. Ein Button dessen Aufgabe das schließen der Form ist auf einem UserControl zu haben richt etwas nach Designfehler.
Wenn der Button da aus irgendeinem mir nicht ersichtlichen Grund hin muss dann würde ich vom UserControl ein entsprechendes Event veröffentlichen damit ich den passenden Code dann auf der Form ausführen kann. Also den Click Event des Button den entsprechenden Event des UserControls ausführen lassen damit dort das passende auf der Form ausgeführt werden kann.
|
|
Talemantros
Beiträge: 444
Erhaltene Danke: 2
Win7 Proff 64bit
C# (VS2013)
|
Verfasst: Mi 30.12.15 17:09
Hey,
also aus meiner Sicht gab es dazu keinen Grund.
Ich dachte, dass wäre so, dass man auf der Form nichts mehr hat, da das UserControl ja mit Dock.Fill geladen wird und der Button dann nicht sichtbar ist?
Daher implizierte ich, dass auch der Schließen Button da hin gehört.
Gruß
EDIT:
bzw. wenn die Form sich selber schließen soll, nach bestimmten Aktivitäten in der UserControl müsste ich vermutlich wieder mit Events arbeiten?
|
|
C#
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Mi 30.12.15 17:56
Tach,
quick and dirty kannst du das Fenster so schließen:
C#-Quelltext 1:
| ((Form)this.Parent).Close(); |
Aber wie Ralf bereits geschrieben hat, sollte ein UserControl nicht die Form manipulieren.
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
Ralf Jansen
Beiträge: 4705
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mi 30.12.15 18:57
Zitat: | Ich dachte, dass wäre so, dass man auf der Form nichts mehr hat, da das UserControl ja mit Dock.Fill geladen wird und der Button dann nicht sichtbar ist? |
Du mußt das UserControl nicht direkt auf die Form werfen. Zum Beispiel wäre es ein leichtes die Form mit 2 Panel zu strukturieren. Ein Panel für die Buttons zum steuern der Form (mit Dock.Bottom) und ein 2.tes (mit Dock.Fill) um darauf dann wieder verschiedene UserControl platzieren zu können. Wenn du dann Dock.Fill des UserControls setzt füllt es ja nur die Fläche seines Parents also des Panels.
@C# Das der Parent eine Form ist wäre eher Zufall. Auf jedenfall wäre solcher Code unglücklich weil man das UserControl in seiner Nutzung soweit einschränkt das es nur funktioniert wenn man es direkt auf eine Form wirft. Quick and Dirty ist da schon mehr als eine Untertreibung
Zitat: | bzw. wenn die Form sich selber schließen soll, nach bestimmten Aktivitäten in der UserControl müsste ich vermutlich wieder mit Events arbeiten? |
Müssen musst du nicht. Ich würde es aber höchstwahrscheinlich als den richtigen Weg bezeichnen.
|
|
C#
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Mi 30.12.15 21:17
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
Talemantros
Beiträge: 444
Erhaltene Danke: 2
Win7 Proff 64bit
C# (VS2013)
|
Verfasst: Mi 30.12.15 21:53
Schon mal danke euch beiden
Bisher habe ich erst einmal ein Event geschrieben und das ist ewig her
Da ich dies sicher nich öfter brauche würde ich mir dies gern genauer anschauen.
Auch die Idee mit den Panels werde ich aufnehmen.
Würdet ihr mir Hilfestellung geben mit dem Event?
Ich wüsste gerade nicht wie ich anfangen sollte.
Versuche mal das alte Event irgendwie zu nutzen.
|
|
Ralf Jansen
Beiträge: 4705
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mi 30.12.15 22:34
|
|
Talemantros
Beiträge: 444
Erhaltene Danke: 2
Win7 Proff 64bit
C# (VS2013)
|
Verfasst: Mi 30.12.15 23:49
Leider finde ich keinen Anfang
Beim letzten hatte ich TextEventArgs verwendet, gibt's da jetzt ButtonEventArgs oder woher weiß ich wie ich da starte ?
|
|
Ralf Jansen
Beiträge: 4705
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Do 31.12.15 00:11
Zitat: | Leider finde ich keinen Anfang |
Für was? Wenn du keine speziellen EventArgs brauchst nimm einfach die EventArgs Klasse.
|
|
C#
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Do 31.12.15 02:37
Also ich würde ein eigenes event für das UserControl erstellen. So etwas wie
public event EventHandler<DeineEventArgs> OnCloseRequest;
@Ralf
Einloggen, um Attachments anzusehen!
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
Talemantros
Beiträge: 444
Erhaltene Danke: 2
Win7 Proff 64bit
C# (VS2013)
|
Verfasst: Do 31.12.15 11:47
Guten Morgen,
es tut mir sehr leid, aber leider komme ich nicht klar.
Ich habe versucht, das einzige Event in meinem Tool noch mal zu verstehen und selbst das gelingt mir gerade nicht mehr.
Wenn ich im UserControl anfange:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| public event EventHandler<ButtonEventArgs> CloseRequest;
protected virtual void OnCloseRequest(ButtonEventArgs e) { EventHandler<ButtonEventArgs> ev = CloseRequest; if (ev != null) ev(this, e); } |
Vorausgesetzt, dass oben stehende würde stimmen müsste ich nach abarbeiten des UserControls, wenn es sich schließen soll dies aufrufen
C#-Quelltext
Wie bzw. was muss ich den jetzt in der Form machen, damit diese weiß, wie sie das Event fängt und dann eine Aktion ausführt.
Danke
Gruß
|
|
Th69
Beiträge: 4777
Erhaltene Danke: 1054
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 31.12.15 12:34
So wie bei anderen Ereignisse aus: in deiner Form-Klasse abonnierst du das Event und in der aufgerufenen Eventmethode führst du dann die Aktion aus.
Auch bzgl. deiner anderen Frage Methode einer anderen Form kann ich dich nur (wieder) auf meinen Artikel Kommunikation von 2 Forms hinweisen.
Du scheinst Ereignisse noch nicht (richtig) verinnerlicht zu haben. Der Sinn besteht ja darin, daß die untergeordnete Klasse nicht die übergeordnete (andere) Klasse kennen muß, sondern einfach nur signalisiert: "hier ist etwas passiert und in den EventArgs stehen weitere Infos dazu". Was die andere Klasse (bzw. anderen Klassen) dann damit macht, ist der Klasse, welche das Ereignis wirft, dann völlig egal.
Erst im Gesamtzusammenhang ergibt sich dann der komplette Programmablauf (die Ereignisse und Methodenaufrufe anderer Klassen sind dann die Bindeglieder).
|
|
Talemantros
Beiträge: 444
Erhaltene Danke: 2
Win7 Proff 64bit
C# (VS2013)
|
Verfasst: Do 31.12.15 14:55
Danke noch mal für die ausführliche Erläuterung.
Ich habe dies tatsächlich noch nicht richtig begriffen
Ich bleib dran und versuche dass hier morgen mal anzugehen.
Edit:
Ich habe jetzt folgendes und es funktioniert.
Würde euch mal bitten zu gucken, ob es so gelassen werden kann.
Im UserControl habe ich folgendes deklariert
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| public event EventHandler<ButtonEventArgs> CloseRequest;
protected virtual void OnCloseRequest(ButtonEventArgs e) { EventHandler<ButtonEventArgs> ev = CloseRequest; if (ev != null) ev(this, e); }
public class ButtonEventArgs : EventArgs { public ButtonEventArgs() { } } |
Und rufe es wie folgt auf
C#-Quelltext 1:
| OnCloseRequest(new ButtonEventArgs()); |
Im Form selber habe ich
C#-Quelltext 1: 2: 3: 4: 5:
| BarcodeNeuUserControl controlNeu = new BarcodeNeuUserControl(employee); controlNeu.BarcodeText = barcodeText; controlNeu.CloseRequest += CloseForm; controlNeu.Dock = DockStyle.Fill; Controls.Add(controlNeu); |
Und hiermit ist es abonniert
C#-Quelltext 1: 2: 3: 4:
| private void CloseForm(object sender, BarcodeNeuUserControl.ButtonEventArgs e) { this.Close(); } |
Danke fürs prüfen und im Allgemeinen für die Hilfe
Gruß
|
|
Ralf Jansen
Beiträge: 4705
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Do 31.12.15 15:27
Sieht korrekt aus.
Der Sinn von ButtonEventArgs ergibt sich mir nicht (und was soll Button im Namen? Wenn schon CloseRequest dann würde ich das eher auch CloseRequestEventArgs nennen). Warum benutzt du nicht einfach EventArgs? Eine eigene Klasse brauchst du erst wenn du mit denn EventArgs auch Daten zum Auswerten im Event transportieren willst.
|
|
Th69
Beiträge: 4777
Erhaltene Danke: 1054
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Fr 01.01.16 17:24
Hallo Talemantros,
zuerst einmal "Frohes Neues Jahr".
Genauso meinte ich es (aber den Anmerkungen von Ralf stimme ich auch zu ;- )
Wichtig ist aber zu wissen und zu verstehen, wie man eigene EventArgs benutzt, wenn man sie denn wirklich braucht.
|
|
C#
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Fr 01.01.16 17:50
Ein frohes Neues auch von mir.
Eigene EventArgs machen nur Sinn, wenn du zusätzliche Informationen bereitstellen willst. Angenommen du willst den Grund weitergeben, warum die Form geschlossen werden soll, dann machst du dir ein Enum mit den möglichen Gründen, z.B.:
C#-Quelltext 1: 2: 3: 4: 5: 6:
| enum CloseReasons { None, UserForced, ControlNeedsReload, } |
Um diesen Grund jetzt and deine subs weiterzuleiten, musst du eine eigene EventArgs-Klasse erstellen:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| public class CloseEventArgs : EventArgs { public CloseReason Reason {get; private set;} public CloseEventArgs(CloseReason reason) { Reason = reason; } } |
Dann wird dein Event so aussehen:
C#-Quelltext 1:
| public event EventHandler<CoseEventArgs> CloseRequest; |
Deine Helfermethode sieht dann so aus:
C#-Quelltext 1: 2: 3: 4:
| protected virtual void OnCloseRequest(CloseEventArgs e) { if (CloseRequest != null) CloseRequest(this, e); } |
In den subs kannst du dann die Infos verwenden:
C#-Quelltext 1: 2: 3: 4: 5:
| private void CloseForm(object sender, CloseEventArgs e) { if (e.Reason != CloseReason.None) this.Close(); else MessageBox.Show("No given close reason."); } |
Wenn du keine zusätzlichen Infos weitergeben möchtest bei deinen Events, reicht die EventArgs-Klasse. Dein event sieht dann so aus:
C#-Quelltext 1:
| public event EventHandler<EventArgs> CloseRequest; |
oder etwas kürzer
C#-Quelltext 1:
| public event EventHandler CloseRequest; |
Auslösen tust du das Event dann mit:
C#-Quelltext 1:
| OnCloseRequest(new EventArgs()) |
oder mit
C#-Quelltext 1:
| OnCloseRequest(EventArgs.Empty) |
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
Talemantros
Beiträge: 444
Erhaltene Danke: 2
Win7 Proff 64bit
C# (VS2013)
|
Verfasst: Sa 02.01.16 14:03
Hallo zusammen und auch von mir ein "Frohes neues Jahr"
Danke für die weiteren Erläuterungen.
Ich habe diese eben noch mal bei mir umgesetzt.
Daraus ergibt sich jetzt noch eine Frage:
Im Moment abonniert ja die Form das Event, des UserControls.
Die Form selber ist eine Form die von der Hauptanwendung aus gestartet wurde.
Wenn ich jetzt wollte, dass das Hauptfenster der Anwendung dies abonniert wie wäre das dann?
Müsste dann die Form, die es aktuell abonniert wieder ein Event auslösen, welches von der Hauptanwendung gefangen wird?
Zum Beispiel bei einem MouseOver über ein Steuerelement soll in der Statusleiste der Hauptanwendung ein InfoText dazu stehen?
Vielen Dank
Gruß
|
|
Ralf Jansen
Beiträge: 4705
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Sa 02.01.16 15:06
Ja und ein bisschen nein
Ja wenn du tatsächlich die Anforderung hast eine reine Userinteraktion einer Form an eine andere weiterzuleiten wird meist ein Event der günstigste Weg sein.
Aber diese Art der Anforderung erscheint mir eher fragwürdig. Wenn sich Formen etwas teilen sind es eher Daten und in dem Fall wäre es eher so das das Model Events wirft das von den betroffenen Formen gefangen wird, die Formen würden dann untereinander nicht direkt kommunizieren. Unabhängigkeit der Einzelteile ist ein hohes gut in einer Anwendung gerade der UI daher ist es üblich das die UI Bestandteile untereinander so wenig wie möglich (eben nur da wo absolut nötig) miteinander direkt kommunizieren.
In deinem Beispiel mit dem MouseOver wäre wohl der Weg über eine Event ok. Wenn das aber ein übliches Problem dieser Anwendung ist (Dinge die irgendwo passieren sollen auf der Mainform visualisiert werden) dann würde ich über ein richtiges Anwendungspattern wie zum Beispiel einen Message Broker nachdenken. Also einen Service an den alle Formen/Controls einer Anwendung Nachrichten senden können, der Message Broker würde dann die Informationen aller Formen sammeln (loggen, priorisieren oder was auch immer sonst noch nötig wäre) und diese dann an die Mainform zu Darstellung weitergeben.
|
|
Talemantros
Beiträge: 444
Erhaltene Danke: 2
Win7 Proff 64bit
C# (VS2013)
|
Verfasst: Sa 02.01.16 23:17
Hallo Ralf,
War ja wieder klar , dass es nicht so einfach ist.
Kennst mich bestimmt schon gut genug um zu wissen, dass ich mich zum weiter entwickeln eher für den Message Broker interessiere.
Ich versuche da im Netz mal was zu finden.
Mache den Eintrag hier erst mal zu um keine Verwirrung zu stiften und dann zum Message Broker einen neuen auf, wenn ich es mal alleine versucht habe.
Gruß
|
|