none
WPF Wie kann ich vom UserControl eine Methode der Eltern-Page aufrufen? RRS feed

  • Frage

  • Hi,

    ich rufe von einer Page aus ein UserControl auf.
    Wenn der User Daten im im UserControl ändert (RadioButton, TextBox),
    so soll in der Page eine Methode aufgerufen werden.

    Zwei Möglichkeiten sehe ich:

    1.) Die Page an das UserControl übergeben und dann page.Methode() aufrufen oder

    2.) Einen EventHandler installieren (auf Page) installieren und auf UserControl aufrufen.

    Ich denke dass die zweite Variente die bessere ist. Aber leider konnte ich nicht herausfinden, wie ich einen EventHandler baue. Bei google finde ich immer nur, wie ich einen EventHandler für zB. Button nachträglich anbinde.
    Kann mir jemand zeigen, wie man ein Event Handler erstellt oder einen Link senden?!


    www.mehlhop.com

    Montag, 13. Januar 2014 13:30

Antworten

  • Hallo,
    ja, die 2. Möglichkeit ist die bessere. Denn so bleibt das UserControl unabhängig von der Page.

    Um Daten mit einem Event zu übertragen benötigst du als erstes eine Klasse zum transportieren. Diese muss sich von EventArgs ableiten:

    class MyEventArgs : EventArgs{
      public string MyData{get;set;}
      public MyEventArgs(string data){
        this.MyData = data;
      }
    }

    Nun kannst du ein Event deklarieren:

    public event EventHandler<MyEventArgs> StringChanged;

    Dieses Event kannst du nun wie folgt auslösen:

    var evt = StringChanged;
    if(evt != null)
        evt(this, new MyEventArgs(textBox1.Text));

    Dabei wird geprüft ob das Event abonniert ist und nur dann ausgelöst. Der Umweg über var ist wichtig, damit kein Fehler auftritt, sollte das Event zwischen if-Abfrage und senden deabonniert werden.

    Das Abonnieren läuft nun wie gewohnt:

    uc.StringChanged += uc_StringChanged;
    
    void uc_StringChanged;(object sender, MyEventArgs e)
    {
      //e.MyData enthält nun den String
    }

    Es gibt noch mehr möglichkeiten. U.a. über selbst geschriebene Delegaten. Ich finde diesen Weg aber am schnellsten und unkompliziertesten. Außerdem besitzen die Eventhandler die gleiche Syntax wie fast alle anderen auch.
    Unter Ereignisse (C#-Programmierhandbuch) erfährst du mehr.

    In WPF kannst du auch RoutedEvents erstellen. Diese benötigst du aber nur in den seltensten Fällen. Siehe auch: Übersicht über Routingereignisse und Eigenes Event (Frage).




    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    • Als Antwort markiert frank me Montag, 13. Januar 2014 15:52
    Montag, 13. Januar 2014 13:41

Alle Antworten

  • Hallo,
    ja, die 2. Möglichkeit ist die bessere. Denn so bleibt das UserControl unabhängig von der Page.

    Um Daten mit einem Event zu übertragen benötigst du als erstes eine Klasse zum transportieren. Diese muss sich von EventArgs ableiten:

    class MyEventArgs : EventArgs{
      public string MyData{get;set;}
      public MyEventArgs(string data){
        this.MyData = data;
      }
    }

    Nun kannst du ein Event deklarieren:

    public event EventHandler<MyEventArgs> StringChanged;

    Dieses Event kannst du nun wie folgt auslösen:

    var evt = StringChanged;
    if(evt != null)
        evt(this, new MyEventArgs(textBox1.Text));

    Dabei wird geprüft ob das Event abonniert ist und nur dann ausgelöst. Der Umweg über var ist wichtig, damit kein Fehler auftritt, sollte das Event zwischen if-Abfrage und senden deabonniert werden.

    Das Abonnieren läuft nun wie gewohnt:

    uc.StringChanged += uc_StringChanged;
    
    void uc_StringChanged;(object sender, MyEventArgs e)
    {
      //e.MyData enthält nun den String
    }

    Es gibt noch mehr möglichkeiten. U.a. über selbst geschriebene Delegaten. Ich finde diesen Weg aber am schnellsten und unkompliziertesten. Außerdem besitzen die Eventhandler die gleiche Syntax wie fast alle anderen auch.
    Unter Ereignisse (C#-Programmierhandbuch) erfährst du mehr.

    In WPF kannst du auch RoutedEvents erstellen. Diese benötigst du aber nur in den seltensten Fällen. Siehe auch: Übersicht über Routingereignisse und Eigenes Event (Frage).




    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    • Als Antwort markiert frank me Montag, 13. Januar 2014 15:52
    Montag, 13. Januar 2014 13:41
  • Hi Tom,

    Danke zuerst einmal für Deine Ausführung.
    Leider habe ich noch Schwierigkeiten in der Umsetzung.
    Vorab: Einen Übergabe Wert benötige ich gar nicht (new MyEventArgs(textBox.Text)).

    Die Klasse MyEventArgs habe ich (vorerst) in die Page integriert.

        class MyEventArgs : EventArgs {   }

    Den Aufruf evt(this, new MyEventArgs() habe ich in das User Control gepackt.

                var evt = StringChanged;
                if (evt != null)
                    evt(this, new MyEventArgs());


    Und in der Page habe ich:

            private void uctest_StringChanged(object sender, MyEventArgs e)
            {}


    Jetzt komme ich zur Schwierigkeit.

    Da ich allen meinen UserControls Werte mitgeben, habe ich ein Interface geschrieben und alle Controls erben von UserControl und vom Interface.
    Der Aufruf der UserControls sieht in etwa so aus:

    private UCLuerGoHome ucLuerGoHome = new UCLuerGoHome(); private UCLuerDock ucLuerDock = new UCLuerDock(); ... switch (tgbAction) { case "tgbActGoHome": setUserControl(ucGoHome, tgbObject); break; case "tgbActDock": setUserControl(ucTripPipDock, tgbObject); break; ...}

    private void setUserControl(IUserControlProperties userControl, string tgbObjectName)
            {
                userControl.StringChanged += uctest_StringChanged;...}

    Da ich nun nicht mit einem UserControl direkt arbeit sondern mit dem Interface 

    IUserControlProperties 

    Habe ich in das Interface und in das UserControl folgendes geschrieben:

    event EventHandler<MyEventArgs> StringChanged;

    Nun leider funktioniert das nicht. :(

    Ich bekomme die Fehlermeldung:

    'BioSyn.MyUserControls.UCLuerGoHome' implementiert den Schnittstellenmember 'BioSyn.UserControls.IUserControlProperties.StringChanged' nicht. 'BioSyn.MyUserControls.UCLuerGoHome.StringChanged' ist nicht öffentlich und kann daher keinen Schnittstellenmember implementieren.

    Ich habe allerlei Varianten von Modifizierern versucht, aber ich bekomme immer (andere) Fehlermeldungen. So darf ich zB. event EventHandler<MyEventArgs> StringChanged im Interface nicht öffentlich machen: "Der public-Modifizierer ist für dieses Element nicht güldig." 

    Wie muss ich den EventHandler nun in das UserControl implementieren?


    www.mehlhop.com

    Montag, 13. Januar 2014 15:24
  • Hallo,
    alles was in einer Schnittstelle deklariert wrd ist automatisch öffentlich (public). Das public-Schlüsselwort musst du aber in der Implementierung in der Klasse hinzufügen.

    Schnittstelle:

    public interface IUserControlProperties{
      event EventHandler<MyEventArgs> StringChanged;
    //usw.
    }
    Klasse:
    public event EventHandler<MyEventArgs> StringChanged;
    Die Klasse MyEventArgs muss natürlich auch public sein. Sonst kannst du das Event nicht von außerhalb abonnieren. Wenn du keine Wert übergeben willst, kannst du natürlich auch die EventArgs Klasse nutzen. Du brauchst nicht zwingend eine Ableitung davon.


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Montag, 13. Januar 2014 15:31
  • Vielen Dank!

    Mein Fehler war, dass ich vergaß die Klasse öffentlich zu machen. ;)

    Danke! :)


    www.mehlhop.com

    Montag, 13. Januar 2014 15:52