none
FireEvent1 ist nicht als abstrakt, extern oder partiell gekennzeichnet und muss daher einen Text deklarieren RRS feed

  • Frage

  • Salü alle zusammen

    Ich verstehe die Fehlermledung nicht, was will sie mir sagen?

    Ich bin am Versuch ein Ereignis zu programmieren aber das gelingt mir noch nicht ganz.

      public class MyEventArgs : EventArgs
      {
        public Boolean aUser = false;
        public Boolean aTraders = false;
      }
    
      public partial class UserNew : Window
      {
        public event MyNewAdress NeuerUser;
        public void FireEvent1(MyEventArgs e) { // <-- Fehlerhafte Zeile
          if (NeuerUser != null)
          {
            NeuerUser(this, e);
          }
        }
    
    
    
      public delegate void MyNewAdress(object sender, MyEventArgs e);
    
      public partial class MainWindow : Window
      {
    
        public void OnNewAdress(object sender, MyEventArgs e)
        {
          MessageBox.Show("Neue Adresse gefeuert");
        }
        public MainWindow(UserNew usrn)
        {
          MyNewAdress mna = new MyNewAdress(OnNewAdress);
        }
    
    

     Jedoch erhalte ich die Fehlermeldung:

    FireEvent1 ist nicht als abstrakt, extern oder partiell gekennzeichnet und muss daher einen Text deklarieren. 

    Ich habe mich an das Beispiel in http://www.c-sharpcorner.com/UploadFile/ddutta/EventHandlingInNetUsingCS11092005052726AM/EventHandlingInNetUsingCS.aspx , Event handlers in C# gehalten.

    Aber ich verstehe nicht was diese Fehlermeldung aussagen möchte.

    Vielen Dank für Hinweise welche zur Lösung führen.

     

    Mein Ziel ist es, in der Klasse UserNew das Ereignis NeuerUser auszulösen welches dann in der Klasse  MainWindow die Funktion OnNewAdress auslöst.

    Lieber Gruss, Sabrina

    Montag, 27. Dezember 2010 22:33

Antworten

  • Hallo Sabrina,

    zunächst solltest Du Dir etwas stringentere Namenskonventionen zulegen,
    denn ansonsten verliert man schnell den Überblick (passiert mir schon bei Deinen paar Zeilen ;-)

    Eine Einführung in die Erstellung von Ereignissen findest Du unter: Ereignisse (C#-Programmierhandbuch)
    Und dort wird auch das Erstellen beschrieben:
    Gewusst wie: Veröffentlichen von Ereignissen, die den .NET Framework-Richtlinien entsprechen (C#-Programmierhandbuch)

    Und so könnte Dein UserNewWindow (das Window ist für mich zur Übersicht notwendig) wie folgt aussehen:

    using System;
    using System.Windows;
    
    namespace WpfApplication1
    {
      public partial class UserNewWindow : Window
      {
        public UserNewWindow()
        {
          InitializeComponent();
        }
    
        // Vermeidet zusätzliche Delegaten
        public event EventHandler<NeuerUserEventArgs> NeuerUser;
    
        // Ereignisse feuert man nur aus der Klasse selbst (oder ggf. in abgeleiteteten),
        // deswegen protected (virtual) oder auch private
        protected virtual void FireNeuerUser(NeuerUserEventArgs e)
        {
          var handler = this.NeuerUser;
          if (handler != null)
          {
            handler(this, e);
          }
        }
    
    
        private void button1_Click(object sender, RoutedEventArgs e)
        {
          // Ereignis auslösen.
          FireNeuerUser(new NeuerUserEventArgs(true, false));
        }
      }
    
    
      public class NeuerUserEventArgs : EventArgs
      {
        public NeuerUserEventArgs(bool isUser, bool isTraders)
        {
          this.IsUser = isUser;
          this.IsTraders = isTraders;
        }
    
        // Besser (automatische) Eigenschaften als Felder
        // Und nur veränderbar bei Ereignissen, wenn auch wirklich verwendet
        public bool IsUser { get; private set; }
        public bool IsTraders { get; private set; }
      }
    }
    
    

    Und ein Konsument MainWindow könnte das Ereignis wie folgt abbonnieren, in dem man sich hält an
    Gewusst wie: Abonnieren von Ereignissen und Kündigen von Ereignisabonnements (C#-Programmierhandbuch)

    using System;
    using System.Windows;
    
    namespace WpfApplication1
    {
      /// <summary>
      /// Interaktionslogik für MainWindow.xaml
      /// </summary>
      public partial class MainWindow : Window
      {
        public MainWindow()
        {
          InitializeComponent();
        }
    
        UserNewWindow userNewWindow;
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
          if (this.userNewWindow == null)
          {
            userNewWindow = new UserNewWindow();
            userNewWindow.NeuerUser += UserNewWindow_NeuerUser;
            userNewWindow.Closed += UserNewWindow_Closed;
            userNewWindow.Show();
          }
          else
          {
            this.userNewWindow.Activate();
          }
        }
    
    
        private void UserNewWindow_NeuerUser(object sender, NeuerUserEventArgs e)
        {
          MessageBox.Show("Neue Adresse gefeuert");
        }
    
        private void UserNewWindow_Closed(object sender, EventArgs e)
        {
          MessageBox.Show("Fenster geschlossen");
          // Ereignisse abmelden
          this.userNewWindow.NeuerUser -= UserNewWindow_NeuerUser;
          this.userNewWindow.Closed -= UserNewWindow_Closed;
          this.userNewWindow = null;
        }
      }
    }
    
    
    Ich habe zudem das Closed Ereignis abbonniert und nutze es auch zum Abmelden der Ereignisse.

    Beachte, dass man bei WPF auch mit Routed Events arbeitet, die das Ereigniskonzept erweitern.
    Was ich hier unterlassen habe, da es für dieses Beispiel nicht erforderlich war
    (und ich erst einmal keine weitere Verwirrung stiften möchte).

    Gruß Elmar

    Dienstag, 28. Dezember 2010 00:39
    Beantworter

Alle Antworten

  • Hallo Sabrina,

    zunächst solltest Du Dir etwas stringentere Namenskonventionen zulegen,
    denn ansonsten verliert man schnell den Überblick (passiert mir schon bei Deinen paar Zeilen ;-)

    Eine Einführung in die Erstellung von Ereignissen findest Du unter: Ereignisse (C#-Programmierhandbuch)
    Und dort wird auch das Erstellen beschrieben:
    Gewusst wie: Veröffentlichen von Ereignissen, die den .NET Framework-Richtlinien entsprechen (C#-Programmierhandbuch)

    Und so könnte Dein UserNewWindow (das Window ist für mich zur Übersicht notwendig) wie folgt aussehen:

    using System;
    using System.Windows;
    
    namespace WpfApplication1
    {
      public partial class UserNewWindow : Window
      {
        public UserNewWindow()
        {
          InitializeComponent();
        }
    
        // Vermeidet zusätzliche Delegaten
        public event EventHandler<NeuerUserEventArgs> NeuerUser;
    
        // Ereignisse feuert man nur aus der Klasse selbst (oder ggf. in abgeleiteteten),
        // deswegen protected (virtual) oder auch private
        protected virtual void FireNeuerUser(NeuerUserEventArgs e)
        {
          var handler = this.NeuerUser;
          if (handler != null)
          {
            handler(this, e);
          }
        }
    
    
        private void button1_Click(object sender, RoutedEventArgs e)
        {
          // Ereignis auslösen.
          FireNeuerUser(new NeuerUserEventArgs(true, false));
        }
      }
    
    
      public class NeuerUserEventArgs : EventArgs
      {
        public NeuerUserEventArgs(bool isUser, bool isTraders)
        {
          this.IsUser = isUser;
          this.IsTraders = isTraders;
        }
    
        // Besser (automatische) Eigenschaften als Felder
        // Und nur veränderbar bei Ereignissen, wenn auch wirklich verwendet
        public bool IsUser { get; private set; }
        public bool IsTraders { get; private set; }
      }
    }
    
    

    Und ein Konsument MainWindow könnte das Ereignis wie folgt abbonnieren, in dem man sich hält an
    Gewusst wie: Abonnieren von Ereignissen und Kündigen von Ereignisabonnements (C#-Programmierhandbuch)

    using System;
    using System.Windows;
    
    namespace WpfApplication1
    {
      /// <summary>
      /// Interaktionslogik für MainWindow.xaml
      /// </summary>
      public partial class MainWindow : Window
      {
        public MainWindow()
        {
          InitializeComponent();
        }
    
        UserNewWindow userNewWindow;
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
          if (this.userNewWindow == null)
          {
            userNewWindow = new UserNewWindow();
            userNewWindow.NeuerUser += UserNewWindow_NeuerUser;
            userNewWindow.Closed += UserNewWindow_Closed;
            userNewWindow.Show();
          }
          else
          {
            this.userNewWindow.Activate();
          }
        }
    
    
        private void UserNewWindow_NeuerUser(object sender, NeuerUserEventArgs e)
        {
          MessageBox.Show("Neue Adresse gefeuert");
        }
    
        private void UserNewWindow_Closed(object sender, EventArgs e)
        {
          MessageBox.Show("Fenster geschlossen");
          // Ereignisse abmelden
          this.userNewWindow.NeuerUser -= UserNewWindow_NeuerUser;
          this.userNewWindow.Closed -= UserNewWindow_Closed;
          this.userNewWindow = null;
        }
      }
    }
    
    
    Ich habe zudem das Closed Ereignis abbonniert und nutze es auch zum Abmelden der Ereignisse.

    Beachte, dass man bei WPF auch mit Routed Events arbeitet, die das Ereigniskonzept erweitern.
    Was ich hier unterlassen habe, da es für dieses Beispiel nicht erforderlich war
    (und ich erst einmal keine weitere Verwirrung stiften möchte).

    Gruß Elmar

    Dienstag, 28. Dezember 2010 00:39
    Beantworter
  • Salü Elmar

    Wow, supervielen Dank für Deinen Code. Die UserNew Klasse konnte ich anpassen. Mehrheitlich verstehe ich es auch. Wenn ich es dann mal durchtracen kann, werde ich es vermutlich ganz verstehen.

    Aber die MainWindow Klasse, die habe ich noch nicht geschafft. Und zwar, weil mein UserNewWindow nicht aus dem MainWindow aufgerufen wird. Vermutlich wird das jetzt doch eine Routed Events Geschichte, obwohl ich so viel Freude hatte, dass Du nicht noch mehr Verwirrung bei mir stifen wolltest.

    Auf dem MainWindow habe ich ein UserControl und dieses erst ruft UserNewWindow auf. Somit vermute ich, dass der Code der private void Button_Click in das UserControl hinein gehört, dort wo ich das UserNewWindow aufrufe.

        public void subUserNew()
        {
          UserNew usr = new UserNew();
          usr.ShowDialog();
    
        }
    
        private void UserNew_NeuerUser(object sender, NeuerUserEventArgs e)
        {
          MessageBox.Show("Neue Adresse gefeuert");
        }

    Und es feuert sogar. Ich bin mächtig stolz auf mich und Dir dankbar, lieber Elmar.

     

    Nun habe ich also mein MainWindow.xaml als Klasse MainWindow und ein ucEditData.xaml als Klasse ucEditDate.

    Habe Deinen Link Routed Events angeschaut und festgestellt, dass ich also ein Bubble Event habe, das von ucEditData nach MainWindow bubbelt.

    Im Beispiel Routed Events steht immer ein Button an dem ich das Event anhänge, das verstehe ich nicht. 

    Wo müsste ich in Meinem/Deinem Beispiel das Bubbeling ansetzen damit ich in der Klasse MainWindow auf das Ereignis aus der Klasse ucEditDate reagieren kann? 

     

    Vielen Dank für Deine Hilfestellung
    Gruss Sabrina

     

    PS: Ja das mit den Namenskonventionen da hast Du wirklich recht. Da falle ich auch immer wieder drüber. Ich vermute, das kommt daher dass ich bei zu vielen Beispielen abschreibe und dann ein misch zwischen meiner Situation und dem gegebenen Beispiel mache. Bin mir auch selbst nicht immer sicher, wie ich die Dinge nennen soll.

    <p> </p>
    
    Dienstag, 28. Dezember 2010 09:25
  • Sorry, hier nochmals der Code aus vorherigem Post...

        public void subUserNew()
        {
          UserNew usr = new UserNew();
          usr.NeuerUser += UserNew_NeuerUser;
          usr.ShowDialog();
        }
    
        private void UserNew_NeuerUser(object sender, NeuerUserEventArgs e)
        {
          MessageBox.Show("Neue Adresse gefeuert");
        }
    

     

    Gruss

     

     

    Dienstag, 28. Dezember 2010 09:30
  • Hallo Sabrina,

    bevor wir auf der Schiene Routed Events weiterfahren, sollten wir klären, worum es sich bei UserNew handelt.

    Denn in Deiner letzten Antwort wird aus dem Window von gestern ein ucEditData.xaml als Klasse ucEditDate.
    Was mich - übliche Namenskonventionen angelegt - zuerst an ein U serC ontrol
    und der Rest an ein eigenständiges Steuerelement zur Bearbeitung von Datumsangaben denken lässt.

    Womit ich zumindest etwas verwirrt bin...

    Denn ein [User]Control würde man nicht mit Show[Dialog] anzeigen,
    sondern im XAML des MainWindows einfügen oder aber zur Laufzeit einbinden.

    Zum P.S.:
    Meine Verwirrung sollte zeigen, dass Code Konventionen ein Verständnis zwischen Entwicklern fördern können.
    Als Grundlage kannst Du Dir mal anschauen:
    All-In-One Code Framework Coding Guideline (Download ), die mehrere Sprachen abdeckt (VB.NET machst Du ja wohl auch)
    und von den Microsoft Supportern als Grundlage verwendet wird.
    Für .NET als Grundlage auch: Entwurfsrichtlinien zum Entwickeln von Klassenbibliotheken .

    Wobei man die grösste Vorlage täglich vor der Nase hat: Die Klassen des .NET Framework selbst.
    Die von Dir verwendete ungarische Notation (in der VB Variante) findet man im .NET Framework
    gar nicht mehr, weil sie dort keine Vorteile bietet und eher das Lesen von Code behindert
    (und wenn, müsste man sie schon konsequent anwenden, sonst wirds richtig anstrengend ;-)

    Gruß Elmar

    Dienstag, 28. Dezember 2010 10:17
    Beantworter
  • Salü Elmar

    Vielen lieben Dank für Deine Rückfrage.

    Bei mir ist UserNew ein WPF Fenster.

    MainWindow ist ebenfalls ein WPF Fenster.

    ucEditData ist wirklich ein UserControl welches ich in WPF auf dem MainWindow sitzen habe. Und DU hast recht, ich rufe das UserControl nicht mit show auf, sondern im ucEditData rufe ich das UserNew mit Show auf.

    Es tut mir leid, Elmar, dass ich Dich so sehr verwirre... hoffe aber inständigst, dass ich das Gewirr auch entwirren konnte...

    Viele liebe Grüsse
    Sabrina

    Die Codekonventionen schau ich mir liebend gerne an und bin sicher, dass mich das sehr viel weiter bringt. Danke Dir für den Link.

    Dienstag, 28. Dezember 2010 11:44
  • Hallo Sabrina,

    da Dein Ereignis - so wie ich es anhand der Eigenschaften interpretiere -
    nicht mit WPF interagiert, ist es weniger für ein Routed Event geeignet.
    Routed Events verwendet man eher dort, wo sich dadurch die visuelle Darstellung
    ändert und Steuerelemente im visuellen / logischen Baum angesprochen werden müssen -
    nur dann ergibt das Routen (und tunneln wie bubbeln) einen Nutzen.

    Eine weitere Übersicht (neben der MSDN) gibt der ARtikel von Brian Noyes:
    Understanding Routed Events and Commands In WPF

    Setzt man das MVVM Muster bei WPF ein, würde man es aus dem
    Fenster selbst weglassen, sondern im View Model platzieren.

    Gruß Elmar

     

    Dienstag, 28. Dezember 2010 20:24
    Beantworter
  • Guten Abend Elmar

    Wenn ich Dich und den Artikel richtig verstehe, heisst das also, dass ich in meinem Fenster UserNew.xaml kein Ereignis erzeugen kann, welches ich in meinem MainWindow.xaml.cs abfangen kann?

    In meinem MainWindow.xml habe ich folgenden Code:

              <DockPanel LastChildFill="false">
                <DataGrid DockPanel.Dock="Top" Height="300" Name="dgUserManager" SelectionChanged="dgUserManager_SelectionChanged"></DataGrid>
                <my:ucEditDate EditBereich="users" x:Name="ucEditUser" />
              </DockPanel>
    
    

    im ucEditDate.xaml.cs habe ich folgenden Code:

        public void subUserNew()
        {
          UserNew usr = new UserNew();
          usr.NeuerUser += UserNew_NeuerUser;
          usr.dpValidFrom.SelectedDate = DateTime.Now;
          usr.dpValidTo.SelectedDate = new DateTime(2099, 12,31);
          usr.dlgTyp = "a";
          usr.ShowDialog();
        }
    
        private void UserNew_NeuerUser(object sender, NeuerUserEventArgs e)
        {
          MessageBox.Show("Neue Adresse gefeuert");
        }
    
    

    Und wenn ich einen neuen Benutzer erfasse, dann feuert UserNew_NeuerUser auch wirklich, die MessageBox erscheint.

    Wie kann ich jetzt eine Funktion aufrufen lassen, welche sich im MainWindow.xaml.cs befindet? Am liebsten würde ich einfach die private void UserNew_NeuerUser(...) vom ucEditDate.xaml.cs ins MainWindow.xaml.cs verschieben, dann wäre meine Sorge gelöst...

    Viele liebe Grüsse
    Sabrina (traurig)

     

     

     

    Dienstag, 28. Dezember 2010 21:06
  • Hallo Sabrina,

    kein Grund zur Traurigkeit ;-)

    Wenn Du für die Eingabe einen Dialog (ShowDialog ) verwendest, so gibt das Ereignis keinen richtigen Sinn.
    Bei einem Dialog wird die Bearbeitung im aufrufenden Fenster unterbrochen und es besteht
    auch keine direkte Beziehung zum Aufrufer (siehe Dokumentation zu ShowDialog ).

    Auch sollte ein Dialog die Möglichkeit zum Abbruch haben, was man über den DialogResult mitteilt.
    Und wenn der Wahr ist, kann man den Wert über eine Eigenschaft abrufen, die man dem Dialog zweisen sollte,
    und die hier den neu angelegten Benutzer (als Klasse) zurückliefert.

    Willst Du wiederum einen "Zwitter", d. h. einen Dialog, in dem Du z. B. mehrere Benutzer
    hintereinander erfassen willst, so kannst Du das Ereignis so verwenden, wie oben gezeigt.
    Denn Einfluss auf das aufrufende Fenster selbst hat es nicht (und würde als RoutedEvent nicht mehr leisten).

    Wo wiederum die Methode steht, die mit der Du das Ereignis abhandelst, ist nebensächlich.
    Du kannst das UserNew_NeuerUser genauso ins MainWindow verlagern (dann als internal oder public)
    und den Delegaten darauf verweisen lassen, solange Du einen Verweis auf MainWindow hast, z. B.:

      // in MainWindow.cs
      internal void UserNew_NeuerUser(object sender, NeuerUserEventArgs e)
      {
       MessageBox.Show("Neue Adresse gefeuert");
      }
    
    
      // in ucEditDate
    
      private MainWindow mainWindow;
    
      public void subUserNew()
      {
       UserNew usr = new UserNew();
    
       usr.NeuerUser += mainWindow.UserNew_NeuerUser;
     
       // ...
       usr.ShowDialog();
      }
    
    
    
    Gruß Elmar

    Dienstag, 28. Dezember 2010 22:12
    Beantworter
  • Lieber Elmar

    Ganz mega herzlich vielen Dank für Deine Zeilen. Du kannst Dir nicht vorstellen, was ich in den vergangenen 30 Minuten durch gemacht habe. Zuerst habe ich mich total enttäsucht ins Bett gelegt und dachte dass ich mein Programm nie schaffen werde. Dann konnte ich nicht schlafen bin wieder aufgestanden und habe Dein Post gesehen. Total voller Freude über Deinen Code habe ich ihn eingebaut und freude gehabt, dass ichdas ja sogar verstehe. Doch dann... Kompiliert nicht. Grübel und Studier. Habe schon an meinem Job gezweifelt und mir überlegt, was ich morgen sagen will.. Doch dann habe ich probiert:

        public void subUserNew()
        {
          MainWindow mw = new MainWindow();
          UserNew usr = new UserNew();
          usr.NeuerUser += UserNew_NeuerUser;
          usr.NeuerUser += mw.UserNew_NeuerUser;
          usr.dpValidFrom.SelectedDate = DateTime.Now;
          usr.dpValidTo.SelectedDate = new DateTime(2099, 12,31);
          usr.dlgTyp = "a";
          usr.ShowDialog();
        }
    
    

    Und ich habe gewonnen. Es funktioniert. Es kommt die anzeuge aus UserNew und aus MainWindow. So super. Ich danke Dir total vielmals für Deine tolle Unterstützung.

    Nun versuche ich nochmals eine Runde mit dem Kissenhorchdienst. Wobei ich glaube, dass ich so aufgewühlt bin, dass dies weider nicht klappen wird.

    Wünsche Dir eine angenehme Nacht.

    Viele Grüsse
    Sabrina

    Dienstag, 28. Dezember 2010 23:18
  • Lieber Elmar
    Liebe alle anderen Leser

    in obigem Code Aboniere ich mit usr.NeuerUser +mw.UserNew_NeuerUser; ein Ereignis. Der Dialog (eigenes WPF Fenster) wird angezeigt. Weiter oben hat Elmar einmal geschrieben, er würde auch ein Ereignis Close zum Abmelden der Ereignisse schreiben.

    A) wenn der Anwender auf abbrechen um usr Dialog klickt, dann wird der Dialog geschlossen (this.close). Sind dann nicht automatisch alle Ereignisse abgemeldet und der für usr benötigte Speicher frei gegeben?

    B) wäre es sinnvoll nach usr.ShowDialog(); das angemeldete Ereignis abzumelden mit usr.NeuerUser -= mw.UserNew_User;?

    Viele liebe Grüsse
    Sabrina

    Mittwoch, 29. Dezember 2010 08:42