delegate en event: het begin

Status
Niet open voor verdere reacties.

sneezesnoeze

Gebruiker
Lid geworden
3 feb 2008
Berichten
41
Ik wil graag delegates en events leren gebruiken.

Nu heb ik een form waarop ik een rapport bouw. De gebruiker vult parameters in en genereert een rapport.
Als het rapport gegenereerd is wil ik graag button op het mainform een aantal buttons enablen.

Code:
        public delegate bool IsReportReadyHandler();
        public event IsReportReadyHandler IsReportReady ;

Ik ben begonnen met een delegate en een event

Dan een ON-methode

Code:
 private bool OnIsReportReady()

     {    

       bool _success = true;



       if (IsReportReady != null)

           _success = IsReportReady();     

     

       return _success;

    }

en die roep ik voor de test aan via button_click.

Code:
        private void button1_Click(object sender, EventArgs e)
        {
            OnIsReportReady();


        }

Wat is mijn volgende stap ?
Ik kan mijn event firen, maar nog niet opvangen.

Hoe moet ik dit event opvangen ?
 
Je zou iets als het onderstaande kunnen doen:

[cpp]
public delegate void ChangedReportStatusEventHandler();
public event ChangedReportStatusEventHandler changedReportStatusEventHandler;
private bool isReportGenerated = false;

private void SetReportStatus(bool done)
{
isReportGenerated = done;
changedReportStatusEventHandler();
}

private void IsReportGenerated()
{
if (isReportGenerated) {
// enable buttons in mainform
}
}

// In de constructor van het form
changedReportStatusEventHandler += new ChangedReportStatusEventHandler(OnReportIsReady);
[/cpp]

Wanneer de status van het rapport nu gewijzigd wordt via de SetReportStatus methode wordt automatisch de IsReportGenerated methode aangeroepen.
 
Dank je.

Als je 1 variable waarde hebt voor je delegate plaats je die dan in het return type of in de parameter declaratie ? en waarom


Waarom maak je de event handler void ?

Ik heb nu in mijn hoofdform een methode met dezelfde signature als mijn delegate.
Deze mag ik subscriben aan het event van het subform

Code:
private bool OnReportReady() 
{
     MessageBox.Show("Rapport is klaar")
}

Hierbij klaagt c# over het feit dat er geen return waarde is ?
Ik snap dat de signatures gelijk moeten zijn maar in de methode van het hoofdform heb ik geen nuttige info voor de returnvalue ?
 
Sorry voor de late reactie, maar bij deze:

Als je 1 variable waarde hebt voor je delegate plaats je die dan in het return type of in de parameter declaratie ? en waarom

Dat hangt er toch gewoon vanaf waar deze variabele waarde gebruikt gaat worden zou ik zeggen. Indien deze variabele waarde de uitvoer van de method/delegate beïnvloed (bijvoorbeeld een boolean die aangeeft of iets gelogd moet worden) dan geef je deze als parameter mee. Is deze variabele waarde afhankelijk van de uitvoer van de method/delegate, dan kan je ervoor kiezen deze waarde als return value te gebruiken. Maar wellicht begrijp ik je vraag niet helemaal goed.

Waarom maak je de event handler void ?

Eigenlijk om meerdere redenen:

1) Wat heeft het volgens jou voor nut om deze bool te maken? Als ik de code uit je voorbeeld bekijk, dan vraag ik me een aantal dingen af:
a) Als ik het goed begrijp koppel je de OnIsReportReady method aan het IsReportReady event, klopt dat? Levert het aanroepen van het IsReportReady event in de OnIsReportReady method dan denk je geen problemen op? Het lijkt mij dat deze zichzelf dan oneindig blijft aanroepen (totdat je een stack overflow krijgt)
b) Als je inderdaad de OnIsReportReady aan het IsReportReady event hebt gekoppeld, hoe verwacht je dan ooit een ander resultaat te krijgen?
c) Mocht ik het verkeerd hebben begrepen en je hebt een andere method gekoppeld aan het event, wat is volgens jou dan het nut om het event in de OnIsReportReady method aan te roepen? Je gebruikt een event dan gewoon als manier om een method aan te roepen, terwijl je een event eigenlijk wilt gebruiken om te reageren op bepaalde handelingen. Dan is het toch veel logischer om zoals in het voorbeeld dat ik gaf in de setter van de status van het rapport de event handler aan te roepen (alleen moet bij het voorbeeld dat ik gaf eigenlijk nog de controle bij of het event object geen null is). Op die manier wordt het event alleen aangeroepen op het moment dat er een actie heeft plaatsgevonden waarop gereageerd zou moeten worden.
2) Je geeft aan dat je meerdere acties wilt ondernemen op het moment dat het rapport klaar is met genereren. Welke manier had je zelf in gedachten om hier op te reageren? Je kan deze functionaliteit uiteraard aan de method toevoegen die aan het event gekoppeld is (zoals ik eigenlijk ook in het voorbeeld gedaan heb. Alleen had ik jouw method per ongeluk in het voorbeeld laten staan, dus eigenlijk was de IsReportGenerated method aan het event gekoppeld), maar persoonlijk ben ik van mening dat je dit alleen hoort te doen wanneer deze functionaliteit daar ook echt thuishoort. Voor een event/method die gebruikt wordt voor het ophalen van een waarde (zie success = IsReportReady()) is dat naar mijn mening niet het geval.

Ik heb nu in mijn hoofdform een methode met dezelfde signature als mijn delegate.
Deze mag ik subscriben aan het event van het subform

-

Hierbij klaagt c# over het feit dat er geen return waarde is ?
Ik snap dat de signatures gelijk moeten zijn maar in de methode van het hoofdform heb ik geen nuttige info voor de returnvalue ?

Een method anders dan void verwacht altijd een return value. Verder geef je hier toch eigenlijk gewoon aan dat de return value niet van belang is en je alleen die actie wilt uitvoeren, dus wat is het probleem om altijd false/true te returnen? :p

edit:

Gezien ik het vorige voorbeeld nogal op een laat tijdstip had gemaakt (ik was echt te lang wakker) en daardoor ook niet helemaal correct was (dat voorbeeld geeft namelijk problemen wanneer je vanaf een ander form probeert te subscriben dan waar de variable isReportGenerated beschikbaar is), heb ik even de moeite genomen een voorbeeld te maken dat wel correct is. Tevens kan dit voorbeeld wellicht een antwoord geven op je vraag of een variabele waarde als parameter of als return value moet gebruiken (mocht dit zoals ik verwacht gaan om het doorgeven van de status van het rapport).

MainForm:
[cpp]
private void OnChangedReportStatus(bool isReportGenerated)
{
if (isReportGenerated)
{
// het rapport is gegenereerd: hier zou je dus de buttons kunnen enablen
}
}

private void btGenerateReport_Click(object sender, EventArgs e)
{
using (var dialog = new GenerateReportForm())
{
dialog.changedReportStatusEventHandler += new GenerateReportForm.ChangedReportStatusEventHandler(OnChangedReportStatus);
dialog.ShowDialog();
}
}
[/cpp]

GenerateReportForm:
[cpp]
public delegate void ChangedReportStatusEventHandler(bool isReportGenerated);
public event ChangedReportStatusEventHandler changedReportStatusEventHandler;

private bool isReportGenerated = false;

private bool IsReportGenerated
{
get { return isReportGenerated; }

set
{
isReportGenerated = value;

if (null != changedReportStatusEventHandler)
{
changedReportStatusEventHandler(isReportGenerated);
}
}
}

public void OnChangedReportStatus(bool isReportGenerated)
{
if (isReportGenerated)
{
// het rapport is gegenereerd: hier kan je bijvoorbeeld de GUI updaten
}
}

public void GenerateReport()
{
// bij de method die je gebruikt voor het daadwerkelijk genereren van het rapport geef je het resultaat door via de property IsReportGenerated
}

public GenerateReportForm()
{
InitializeComponent();
changedReportStatusEventHandler += new ChangedReportStatusEventHandler(OnChangedReportStatus);
}
[/cpp]
 
Laatst bewerkt:
Bedankt voor je uitgebreide antwoord en nieuwe vragen

Mijn gedachtegang:

1a
Ik maak een delegate met een bepaald return-type en parameters, volgens tutorials mag dat van alles zijn. Maar waarschijnlijk werken in bepaalde situaties bepaalde signature's beter.
In mijn voorbeeld vuur ik het event af via de button1_Click, dit is puur voor het voorbeeld. In het eindresultaat wil ik dat doen als het rapport gegenereerd is.

De button1_Click roept de OnIsReportReady (vergelijkbaar met OnClick).
Deze checked of er subscriber zijn en zo ja vuurt het event af.

Dus zolang er niet op de button geklikt wordt, wordt OnIsReportReady niet aangeroepen en is er geen oneidige loop.

Misschien had ik het simpeler kunnen doen door geen On_methode te maken en het checken van de subscribers in de button1_click te doen.

Waarom een bool. Dat was mijn eerste ingeving.

De opdracht is : Maak een functie die zegt of een rapport klaar is

idee1:
functie waar/onwaar IsKlaar
als je dat in code opschrijft krijg je
public bool IsReportReady
Waarom een void ?

1b
Ik kom inderdaad in de problemen doordat ik in het mainform, wil reageren op het gedrag van het sub-form.
Een rapport kan klaar zijn (true), maar als de gebruiker gegevens gaat wijzigen kan het rapport ook ineens niet klaar zijn (false).
In beide gevallen moet het event worden afgevuurd, zodat de button desgewenst geenabled of gedisabled kan worden.

1c
Grappig die code moet ik nog eens bekijken.
Ik had niet door dat je bij variable ook getter en setter kon definieren, ik dacht dat alleen bij properties kon
(ik heb lang in delphi geprogrameerd dus ik mis in c# verschillende woorden function, procedure, property)


Ik ga je voorbeeld eens uitproberen
 
Status
Niet open voor verdere reacties.
Steun Ons

Nieuwste berichten

Terug
Bovenaan Onderaan