Entwickler-Ecke

C# - Die Sprache - custom Events


Glowhollow - Di 23.04.19 10:27
Titel: custom Events
Guten Morgen,

ich hoffe ihr hattet ein schönes Ostern.

Momentan beschäftige ich mich mit Custom Events, bin da aber noch nicht ganz durchgestiegen.

Ich zeig euch mal was ich bisher habe.

Im Prinzip möchte ich einen Event abfeuern, der je nach übergebenen Wert (in dem Fall ein Bool) eine Form sichtbar, bzw. unsichtbar macht.

Ich habe im Controller folgendes:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
 public delegate void StatusUpdateHandler(object sender, ProgressEventArgs e);
        public event StatusUpdateHandler SplashShowStatus;



        public SplashController(ISplashScreenView view)
        {
            _view = view;
            view.SetController(this);
        }

        private void _SplashShowStatus(bool status)
        {
            if (SplashShowStatus == nullreturn;
            ProgressEventArgs args = new ProgressEventArgs(status);
            SplashShowStatus(this, args);
        }

        public class ProgressEventArgs : EventArgs
        {
            public bool Status { get; private set; }
            public ProgressEventArgs(bool status)
            {
                Status = status;
            }
        }


und in der Form


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
SplashController _controller;
   
        public Splashscreen()
        {
            InitializeComponent();
            _controller.SplashShowStatus += new SplashController.StatusUpdateHandler(UpdateStatus);

        }

        public bool ViewStatus = false;

        private void UpdateStatus(object sender, ProgressEventArgs e)
        {
            SetStatus(ViewStatus);
        }

       

        private void SetStatus(bool value)
        {
            if(value == true)
            {
                this.Visible = true;
                this.ViewStatus = true;
            }
            else if(value == false)
            {
                this.Visible = false;
                this.ViewStatus = false;
            }
        }


Allerdings wird hier bemängelt, das keine Überladung für "UpdateStatus" stimmt mit dem Delegaten "SplashController.StatusUpdateHandler" überein.

Im Prinzip möchte ich eine Event feuern, das mit einem Bool versehen ist, worauf dann die Form reagiert und sich selbständig unsichtbar bzw. sichtbar schaltet.

Leider komme ich mit der kryptischen Aussage nicht ganz zurecht und weiß jetzt nicht was von mir verlang wird.

Mag mich hier jemand erleuchten ?

Vielen Dank !

Moderiert von user profile iconChristian S.: Code- durch C#-Tags ersetzt


Glowhollow - Di 23.04.19 11:23

Ok, hab herausgefunden woran es lag.

erstens. der SetStatus teil war falsch. Dort habe ich jetzt SetStatus(e.Status).

zudem hatte ich noch einen möglichen unsafe thread in der _SplashShowStatus den ich mit SplashSowStatus?.Invoke(thisnew ProgressEventArgs(status)) korrigieren können.

Jetzt ist es aber so, das ich verschiedene Events habe, die listener setzen und so ist kein Ding. Jedoch müßte ich den ProgressEventArgs erweitern (in dem Falle ists ja nur 1 Event).

Was mache ich aber, wenn ich 10 unterschiedliche Events habe ? Wie kapsele ich das ?

Moderiert von user profile iconTh69: C#-Tags hinzugefügt


Glowhollow - Di 23.04.19 15:44

Gut, konnte meine Problem soweit beheben, das Event wird schon geworfen. Jetzt ist mir hier allerdings einiges unklar.

Im MainFormController

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
public delegate void StatusUpdateHandler(object sender, ProgressEventArgs e);
public event StatusUpdateHandler UpdateTSSLMainConnection;
public void _UpdateTSSLMainConnection(string value)
{
    UpdateTSSLMainConnection?.Invoke(thisnew ProgressEventArgs(value));
}

public class ProgressEventArgs:EventArgs
{
    public string Status { get; private set; }
    public ProgressEventArgs(string value)
    {
        Status = value;
    }
}


in der dazugehörigen MainForm

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
private void UpdateTSSLMainConnection(object sender, MainFormController.ProgressEventArgs e)
{
    SetText(e.Status);
}

private void SetText(string value)
{
    this.TSSLmainconnection.Text = value;
}

Wiegesagt, das Event wird geworfen (laut debugger erreicht er den Code, Parameter sind soweit gut, so wie es sein soll), aber ich erwarte eigentlich, das er in der Mainform, die werte ändert. Da kommt er aber nicht hin. Was muß ich tun, das in der Mainform, der Code ausgeführt wird. Was hab ich übersehen ?

Moderiert von user profile iconTh69: Code- durch C#-Tags ersetzt


Chiyoko - Di 23.04.19 16:53

Erstmal ein par formale Dinge:

1) Bitte benutze cs-Tags , nicht code-Tags. Th69 korrigiert das ständig aber du merkst es nicht.
2) Halte dich an die Microsoftkonventionen [https://docs.microsoft.com/de-de/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces], macht den Code viel lesbarer.
3) Ab C# 7.2 gibt es einen tenären Operator "?:". Damit kannst du if/else Abfragen abkürzen. Mag nicht jeder, kann aber die Lesbarkeit erhöhen. Oder du negierst bei boolischen Werten einfach die Abfrage.
In deinem Fall geht auch:


C#-Quelltext
1:
2:
3:
4:
5:
private void SetStatus(bool value)
{
   this.Visible = value;
   this.ViewStatus = value;
}


Zur Lösungsfindung:
Vermutlich setzt du die Property Visible viel zu spät oder an der falschen Stelle. Du solltest prüfen, ob bereits das Handle existiert.


Th69 - Di 23.04.19 16:53

Hast du das Event denn in der MainForm abonniert? [Auch wenn ich immer noch meine, daß der Controller zwar die MainForm kennen darf, aber eben nicht umgekehrt!]

PS:
Für die Delegates gibt es schon generische Typen im .NET Framework, so daß du die ersten beiden Zeilen durch eine Zeile ersetzen kannst:

C#-Quelltext
1:
public event EventHandler<ProgressEventArgs> SplashShowStatus;                    

Desweiteren gibt es noch die generischen Delegates Action<T, ...>, Func<R, T, ...> sowie Predicate<T, ...>, s. z.B. Func, Action and Predicate in C# With Example [https://www.codeproject.com/Articles/1019116/Func-Action-and-Predicate-in-Csharp-With-Example] und C# Generic Delegates Func, Action, and Predicate [https://www.c-sharpcorner.com/blogs/c-sharp-generic-delegates-func-action-and-predicate].

PPS: Bitte benutze die C#-Tags (nicht nur die Code-Tags)!


Glowhollow - Di 23.04.19 17:44

@Chiyoko

das mit dem visible hab ich hinbekommen. das läuft jetzt.


Hallo Th69 !

Danke das du dich meiner erbarmst :).

Ja hab ich. Da ich anfangs noch die ganzen Scopes setzen mußte, abboniere ich den Handler über das MainProgram, über einen Aufruf à la AddEventsToMainForm().

dort steht drin...


C#-Quelltext
1:
2:
3:
4:
 public void AddEventsToMainForm()
{
    _controller.UpdateTSSLMainConnection += new MainFormController.StatusUpdateHandler(UpdateTSSLMainConnection);
}

Der Event wird ja auch geworfen in der dbcon, jedoch ist die referenz auf den Listener immer noch null.

Edit... jetzt hab ich das mit dem cs tag gefunden, danke !


Th69 - Di 23.04.19 18:04

Dann hast du verschiedene UpdateTSSLMainConnection-Methoden (drücke mal "Gehe zu Definition (F12)")...


Glowhollow - Mi 24.04.19 09:53

Ach, habs herausgefunden, ich droppe den event, obwohl er noch garnicht registriert ist, deswegen läuft das auf null hinaus. Hab den code angepasst.

Gut, Wie ist das mit mehreren Events, die auf EventArgs reagieren ... Ich meine, ich will diese ganze Form kommunikationen über events laufen lassen. Bei so vielen Events, was ist da die beste Herangehensweise ?

[Edit]
Habe etwas über EventList gefunden, allerdings sind die Beispiele dich bis jetzt gefunden habe eher meh...

Kann mir hier jemand was zu sagen ? Z.bsp. 3 Unterschiedliche Events, die alle unterschiedliche sachen ändern ?


Chiyoko - Mi 24.04.19 11:18

Wenn du mehrere Events hast, die alle das gleiche (?) machen, bietet sich eine EventHandlerList [https://docs.microsoft.com/en-us/dotnet/standard/events/how-to-handle-multiple-events-using-event-properties] an.
Ist ja letztlich auch nur ne Art erweitertes Dictionary.