2008-10-02 7 views
10

Gibt es eine Möglichkeit, dass das Hauptformular Ereignisse abfangen kann, die auf einem Untersteuerelement eines Benutzersteuerelements ausgelöst werden?Wie greife ich Ereignisse von Untersteuerelementen auf einem Benutzersteuerelement in einer WinForms-App?

Ich habe eine benutzerdefinierte Benutzersteuerung in das Hauptformular meiner Anwendung eingebettet. Das Steuerelement enthält verschiedene Untersteuerelemente, die Daten bearbeiten, die wiederum von anderen Steuerelementen im Hauptformular angezeigt werden. Was ich möchte ist, wenn das Hauptformular irgendwie informiert werden könnte, wenn der Benutzer Untersteuerungen ändert, so dass ich die Daten und die entsprechende Anzeige an anderer Stelle aktualisieren könnte.

Gerade jetzt betrüge ich. Ich habe einen Delegierten an das Fokus-Verlassen-Ereignis der Untersteuerungen angeschlossen. Dieser Delegat ändert eine Eigenschaft des Benutzersteuerelements, das ich nicht anderweitig verwende (in diesem Fall CausesValidation). Ich habe dann einen Delegaten im Hauptformular definiert, wenn sich die CausesValidation-Eigenschaft des Benutzersteuerelements ändert, was dann die App anweist, die Daten zu aktualisieren und anzuzeigen.

Ein Problem entsteht, weil ich auch einen Delegaten eingerichtet habe, wenn der Fokus die Benutzersteuerung verlässt, weil ich die Felder in der Benutzersteuerung überprüfen muss, bevor ich dem Benutzer erlauben kann, etwas anderes zu tun. Wenn der Benutzer jedoch nur zwischen Untersteuerungen wechselt, möchte ich nicht überprüfen, da die Bearbeitung möglicherweise nicht erfolgt.

Grundsätzlich möchte ich, dass die Daten aktualisiert werden, wenn der Benutzer die Untersteuerungen wechselt ODER die Benutzersteuerung behält, aber nicht validiert. Wenn der Benutzer das Steuerelement verlässt, möchte ich es aktualisieren und validieren. Wenn Sie jetzt die Benutzersteuerung verlassen, wird die Validierung zweimal ausgelöst.

+0

Was ist falsch daran, das Hauptformular an die verschiedenen Ereignisse der Steuerelemente zu binden? Es gibt eine Menge Ereignisse, die für die meisten Winform-Steuerelemente ausgelöst werden. – Sekhat

+0

Ich denke, ich verstehe einfach nicht, was du erreichen willst: P – Sekhat

+0

Um die erste Frage zu beantworten, durch den Designer (was ich, relativ neu in C#, verwendet für meine GUI-Bearbeitung), hat mein Formular nur Zugriff auf die Ereignisse, die vom Benutzersteuerelement ausgelöst werden, und nicht seine Untersteuerungen. Woran ich mich nicht erinnern konnte ist, dass ich meine eigenen Ereignisse feuern und mit denen umgehen kann. –

Antwort

15

Die beste Vorgehensweise besteht darin, Ereignisse auf dem UserControl zu offenbaren, die die Ereignisse bis zum übergeordneten Formular sprudeln lassen. Ich bin voran gegangen und habe ein Beispiel für dich zusammengestellt. Hier finden Sie eine Beschreibung, was dieses Beispiel bietet.

  • UserControl1
    • erstellen UserControl mit TextBox1
    • eine öffentliche Veranstaltung auf der
    • Im UserControl registrieren einen Event-Handler für die TextBox1 TextChangedEvent
    • Im TextChangeEvent Handler ControlChanged genannt UserControl Registrieren Funktion rufe ich die ControlChanged Ereignis zu sprudeln an die Mutterform
  • Form1
    • Tropfen eine Instanz UserControl1 auf dem Designer
    • einen Ereignishandler für MouseLeave und für ControlChanged
auf UserControl1 Registrieren

Hier ist ein Screenshot, der das Ereignis ControlChanged darstellt dass ich über die UserControl definiert wurde, ist über das UX in Visual Studio auf dem übergeordneten Windows-Formular verfügbar.

Event Handlers for User Control http://friendfeed.s3.amazonaws.com/0d5a3968cb785625c8afb3974a8d84894c476291

+0

Danke, das ist, was ich getan habe, außer statt MouseLeave, habe ich FocusLeave verwendet, da potentielle Fehler jedes Mal, wenn der Benutzer seine Maus bewegt, irritierend werden könnte. Auch, danke, dass Sie die ganze Arbeit dafür erledigt haben! –

+0

Wenn Sie also viele verschiedene Steuerelemente haben (sagen wir, ein Textfeld, eine Schaltfläche, ein Kontrollkästchen und eine Beschriftung), und dass alle relevanten/tatsächlichen Ereignisse dieses Steuerelements innerhalb des Benutzersteuerelements behandelt werden (eigenständiges Benutzersteuerelement), und Sie wollten ein einzelnes Ereignis (zB MyControl.OnClick) in das Container-Formular einblenden, könnten Sie alle Untersteuerungs-Ereignisse über eine einzige Methode/Mechanismus "entführen", um das Ereignis "Einfaches Klicken" zu verpuffen, oder müssten Sie das noch tun manuell jedes Subcontrol-Ereignis verdrahten und die Sprudeln für sich selbst behandeln? – MaxOvrdrv

+1

Der Link funktioniert nicht. Der Code sollte als Text in der Antwort und nicht als Link zum Herunterladen einer Zip-Datei verwendet werden. – ardila

2

Das beste Modell für diese Art von Sache wird benutzerdefinierte Ereignisse in Ihrem Benutzersteuerelement erstellen und sie zu den entsprechenden Zeiten erhöhen.

Ihr Szenario ist ziemlich komplex, aber nicht unbekannt. (Ich bin in einem meiner aktuellen Projekte tatsächlich in einem sehr ähnlichen Modus.) Die Art und Weise, wie ich mich annähme, ist, dass das Benutzersteuerelement für seine eigene Validierung verantwortlich ist. Ich verwende keine CausesValidation; Stattdessen führe ich am entsprechenden Benutzerkontrollpunkt eine Validierung durch eine Überschreibung von ValidateChildren() durch. (Dies geschieht normalerweise, wenn der Benutzer für mich auf "Speichern" oder "Weiter" auf dem Benutzer-Steuerelement klickt.)

Nicht vertraut mit Ihrem Benutzer Steuerelement Benutzeroberfläche, die möglicherweise nicht 100% der richtige Ansatz für Sie ist. Wenn Sie jedoch benutzerdefinierte Ereignisse auslösen (möglicherweise mit einem benutzerdefinierten EventArgs, das angibt, ob eine Überprüfung durchgeführt werden soll oder nicht), sollten Sie in der Lage sein, dorthin zu gelangen, wo Sie hin möchten.

2

Sie müssen die Ereignisse verkabeln Sie sorgen in Ihrem Benutzerkontrolle über die Erfassung und veröffentlichen sie durch einige benutzerdefinierte Ereigniseigenschaften auf der Benutzersteuerung selbst. Ein einfaches Beispiel wäre eine Schaltfläche Click-Ereignis werden Verpackung:

// CustomControl.cs 
// Assumes a Button 'myButton' has been added through the designer 

// we need a delegate definition to type our event 
public delegate void ButtonClickHandler(object sender, EventArgs e); 

// declare the public event that other classes can subscribe to 
public event ButtonClickHandler ButtonClickEvent; 

// wire up the internal button click event to trigger our custom event 
this.myButton.Click += new System.EventHandler(this.myButton_Click); 
public void myButton_Click(object sender, EventArgs e) 
{ 
    if (ButtonClickEvent != null) 
    { 
    ButtonClickEvent(sender, e); 
    } 
} 

Dann in der Form, dass die Steuerung verwendet, verkabeln Sie das Ereignis wie jedes andere bis:

// CustomForm.cs 
// Assumes a CustomControl 'myCustomControl' has been added through the desinger 
this.myCustomControl.ButtonClickEvent += new System.EventHandler(this.myCustomControl_ButtonClickEvent); 
myCustomControl_ButtonClickEvent(object sender, EventArgs e) 
{ 
    // do something with the newly bubbled event 
} 
+0

Vielleicht irre ich mich oder ich verstehe die Idee nicht wirklich, aber sollte es nicht sein new MyProject.CustomControl.ButtonClickHandler() 'anstelle von' new System.EventHandler() 'in' CustomForm.cs'? – MRM

0

Ich mag würde zu läuten Sie darin, dass es wie beschrieben klingt, als würden Sie einen roten Hering jagen. Während es scheint, als ob Sie eine Situation haben, in der das Fehlen von Ereignissen in WinForms Ihnen Ärger bereitet, ist die Realität, dass eine schlechte Architektur Sie dazu zwingt, Event-Sprudeln zu benötigen, wenn Sie es nicht sollten.

Wenn Sie Ihr Design so umstrukturieren/restrukturieren können, dass die Steuerelemente mit einem gemeinsamen Datenmodell arbeiten (MVC/MVP sind offensichtliche Optionen), können Sie einfach gängige WinForms-Muster wie PropertyChanged-Ereignisse auf das Modell anwenden, um Ihr Hauptformular anzugeben und alle anderen Steuerelemente, die diese Daten verbrauchen, um sich selbst zu aktualisieren.

Kurz gesagt, die anderen Antworten sind insofern sinnvoll, als sie die gestellte Frage beantworten. Aber vom Standpunkt der Codequalität denke ich, dass die bessere Antwort darin besteht, Ihre Daten von der Benutzeroberfläche zu trennen.

1

Falls sich jemand noch fragt, wie man Ereignisblasen in WinForm simulieren kann, ist die Methode Application.AddMessageFilter ein guter Ort, um sie zu betrachten.

Mit dieser Methode können Sie einen eigenen Filter installieren, der alle Nachrichten überwacht, die in der Nachrichtenwarteschlange des aktuellen Threads gepostet werden.

Sie sollten wissen, dass gesendete Nachrichten (nicht veröffentlicht) von diesem Filter nicht behandelt werden können.Vierundvierzig, die meisten interessanten Ereignisse (wie Klickereignisse) werden gepostet und nicht gesendet und können daher von diesem Filter überwacht werden.