[C#]Openen en bijhouden aantal forms

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
De titel is wat cryptisch, maar dit is de situatie.
Ik heb een applicatie die een aantal conversies uitvoert. Hiervoor heb ik een template/basis formulier gemaakt en 6 inhereted formulieren.
Deze 6 formulieren converteren elk hun eigen formaat. Dit werkt prima.
Ook heb ik een menu waarmee de 6 formulieren geopend kunnen worden. En ik heb een formulier waar 6 buttons opzitten, die ook elk een formulier open.

Nu gaat het over het openen of activeren van de formulieren.
Als een formulier al is geopend, moet die bij de volgende keer worden geactiveerd en niet nog een keer worden geopend.

Ik had bedacht om dat op te lossen via een dictionary waarin ik de formulier objecten met de naam als key in opsla.
Vervolgens kijk ik eerst of het formulier al open is. Zoniet dan doe ik showDialog() en anders Activate().
Dit werkt ook prima, alleen als ik een formulier sluit, wordt ook het object in de dictionary ge-disposed en werkt de ShowDialog() niet meer.
Dit kan ik wel weer opvangen door in het Close() event van het formulier het formulier niet te sluiten, maar te hiden.
Inmiddels komt me dit erg gekunstel over en ik ben dan ook zeer benieuwd of het niet veel handiger, beter en/of eenvoudiger kan.

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Verwijderd schreef op maandag 11 januari 2010 @ 13:36:
Ik had bedacht om dat op te lossen via een dictionary waarin ik de formulier objecten met de naam als key in opsla.
Waarom? Er is toch gewoon een Application.OpenForms?
Verwijderd schreef op maandag 11 januari 2010 @ 13:36:
Vervolgens kijk ik eerst of het formulier al open is. Zoniet dan doe ik showDialog() en anders Activate().
Dit werkt ook prima, alleen als ik een formulier sluit, wordt ook het object in de dictionary ge-disposed en werkt de ShowDialog() niet meer.
Dit kan ik wel weer opvangen door in het Close() event van het formulier het formulier niet te sluiten, maar te hiden.
Inmiddels komt me dit erg gekunstel over en ik ben dan ook zeer benieuwd of het niet veel handiger, beter en/of eenvoudiger kan.
Toevallig een tijd geleden wat over geschreven. Hou wel rekening ermee dat, zoals het daar staat, telkens (tijdelijk) een nieuwe instantie van een form wordt gemaakt. Dit kun je oplossen (zoals in de comments staat) door een delegate te gebruiken. Dan krijg je zoiets:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/// <summary>
/// Searches for a form that matches the conditions defined by the predicate and returns the first occurence with the application's open forms
/// </summary>
/// <typeparam name="T">The type of the form to look for</typeparam>
/// <param name="match">The predicate that defines the conditions of the form to search for</param>
/// <param name="newinstance">A delegate to use to create the form when no instance could be found</param>
/// <returns>Returns the form when found, returns the new instance specified by newinstance otherwise</returns>
public static T GetWindow<T>(Predicate<T> match, FormCreateDelegate newinstance)
    where T : Form
{
    foreach (Form form in Application.OpenForms)
        if (form.GetType().Equals(typeof(T)) && match.Invoke(form as T))
            return form as T;
    if (newinstance == null)
        return null;
    else
        return newinstance() as T;
}

(Overigens zat/zit ik in dit geval aan .Net 2.0 vast, met 3.5 zijn daar vast nog leukere dingen voor te verzinnen). In dit voorbeeld wordt er ook nog gekeken naar een extra voorwaarde; die kan in jouw geval ook nog er uit.

[ Voor 38% gewijzigd door RobIII op 11-01-2010 13:54 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Dank je RobIII,

Aan Application.OpenForms had ik nog niet gedacht. Ik zal je voorbeeld eens uitwerken.
Overigens gebruik ik .NET3.5.
Kun je een voorbeeldje van die leukere dingen geven? Dan zoek ik dat gelijk ook uit.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik ben even in LINQ gedoken, maar dat is toch wat lastig.
Na veel lezen en zoeken heb ik dit stukje code gemaakt:
C#:
1
var frmTemp = from f in Application.OpenForms.Cast<Form>() where f.Name.Equals(formName) select f;


Ik verwachtte dat frmTemp een form object zou zijn, maar dat is een
C#:
1
System.Collections.Generic.IEnumerable<System.Windows.Forms.Form>


Vervolgens werkt de activate niet:
C#:
1
frmTemp.Activate();


Ik mis nog een klein stukje maar ik kom er niet uit wat. Kan iemand me nog even een duwtje in de juiste richting geven?

Acties:
  • 0 Henk 'm!

  • gvdh
  • Registratie: December 2009
  • Laatst online: 17:35
Ik denk dat het een lijst is met alle forms die voldoen aan het zoekcriterium.
Probeer eens
C#:
1
frmTemp[0].Activate();

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op woensdag 20 januari 2010 @ 09:43:
Ik ben even in LINQ gedoken, maar dat is toch wat lastig.
Na veel lezen en zoeken heb ik dit stukje code gemaakt:
C#:
1
var frmTemp = from f in Application.OpenForms.Cast<Form>() where f.Name.Equals(formName) select f;


Ik verwachtte dat frmTemp een form object zou zijn, maar dat is een
C#:
1
System.Collections.Generic.IEnumerable<System.Windows.Forms.Form>


Vervolgens werkt de activate niet:
C#:
1
frmTemp.Activate();


Ik mis nog een klein stukje maar ik kom er niet uit wat. Kan iemand me nog even een duwtje in de juiste richting geven?
frmTemp is een IEnumerable inderdaad, dat betekent dus dat je er met foreach overheen kunt itereren.
C#:
1
2
3
4
5
6
7
foreach(Form frm in frmTemp)
{
      // zoiets wellicht
      if(frm.GetType() == typeof(watjijzoekt))
      {
      }
}


Wat je ook zo kunt oplossen, dus zonder LINQ, want als ik het goed begrijp is dat gewoon overkill:
C#:
1
2
3
4
5
6
7
foreach(Form frm in Application.OpenForms)
{
      // zoiets wellicht
      if(frm.GetType() == typeof(watjijzoekt))
      {
      }
}


OpenForms is namelijk gewoon een collectie die IEnumerable implementeerd.

[ Voor 23% gewijzigd door Verwijderd op 20-01-2010 10:02 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Jullie hebben gelijk.
Als ik de LINQ Query wijzig in
C#:
1
var frmTemp = (from f in Application.OpenForms.Cast<Form>() where f.Name.Equals(formName) select f).ToList<Form>();

en
C#:
1
frmTemp[0].Activate();
gebruik, compileert de code weer.
Ik kan het nu even niet testen omdat er op andere plekken fouten ontstaan, maar ik begrijp het nu wel.
Als ik de boel weer werkend heb, zal ik een kijken naar het gedeelte van RobIII over die delegate om een form te laden als dat nog niet is gedaan.

Acties:
  • 0 Henk 'm!

Verwijderd

Wat is nu precies de meerwaarde van die LINQ query in je code, ik zie het nut er op het moment even niet van namelijk. Het levert alleen maar complexiteit/overhead voor iets wat je ook zo kan oplossen:

C#:
1
2
3
4
5
6
7
8
9
10
bool allowedOpen = true;
foreach(Form form in Application.OpenForms)
     if(form.GetType() == typeof(JouwForm)) // is al open dus
         allowedOpen = false;

if(allowedOpen)
{
     XForm xform = new XForm(xxx);     
     xform.Visible=true;
}

Of begrijp ik je vraag nou helemaal verkeerd?

[ Voor 5% gewijzigd door Verwijderd op 20-01-2010 10:41 ]


Acties:
  • 0 Henk 'm!

  • Haan
  • Registratie: Februari 2004
  • Laatst online: 19:28

Haan

dotnetter

Het lijkt me in dit geval inderdaad ook niet erg nuttig om LINQ te gebruiken, behalve dan als voor educatieve doeleinden voor de TS.

Kater? Eerst water, de rest komt later


Acties:
  • 0 Henk 'm!

  • HeSitated
  • Registratie: April 2009
  • Laatst online: 03-12-2024
Laat Linq achterwege en je hoeft niets te casten.... Niets fancy, maar werkt wel...

[ Voor 82% gewijzigd door HeSitated op 20-01-2010 11:02 . Reden: te laat.... ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik geef toe dat educatieve doeleinden een grote rol spelen. Ik ben enorm aan het stoeien met dit ogenschijnlijk eenvoudig probleem: Openen van forms op meerdere plekken met zo min mogelijk dubbele code' en ik lees me een slag in de rondte en kom allerlei suggesties en voorbeelden tegen. Waaronder die LINQ oplossing. Uiteraard heb ik die niet zelf bedacht ;)
Vooralsnog heb ik het gedeelte werkend die er voor zorgt dat een form niet twee keer wordt geopend. Nu nog het stukje voor de eerste keer openen en dan zal ik eens kijken of mijn gekozen oplossing wel de meest efficiente manier is.
Hopelijk heb ik dan aan het einde van de rit mijn probleem opgelost EN ook nog wat geleerd ;)

Acties:
  • 0 Henk 'm!

  • DarkSilence
  • Registratie: December 2002
  • Laatst online: 06-07 20:28

DarkSilence

W3designer.nl

Misschien een beetje als mosterd na de maailtijd maar ik dacht is het niet eenvoudiger om het met Singleton design pattern op te lossen?

W3designer.nl


Acties:
  • 0 Henk 'm!

Verwijderd

Weer dezelfde vraag: waarom? Wat biedt een Singleton in dit geval voor voordeel over een simpele methode?

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik was het Singleton design pattern ook al aan het bekijken, dat is misschien ook een optie.
@ctor: Als je met een simpele methode jouw code voorbeeld bedoeld, dan begrijp ik die niet helemaal.
Ik snap hoe je dat kunt gebruiken om op basis van de naam van het form kunt kijken of het form al is geopend.
Ik begrijp alleen nog niet hoe je het kunt gebruiken om 1 van de 6 forms te openen die geopend moet worden als dat nog niet is gebeurd. De twee aanroepende methoden zitten in hun eigen class. De ene is nl. het click event van de toolbar op het hoofd form en de tweede is het click event van een button op een ander form.

Acties:
  • 0 Henk 'm!

Verwijderd

Aah, dan heb ik je vraag dus verkeerd begrepen. Ik dacht dat je gewoon een controle wilde op de geopende formulieren. Dan verwijs ik je door naar de eerste reply, dat doet dan toch precies wat je wilt?

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Waarschijnlijk wel, maar die begrijp ik nog niet helemaal :P
Daarom probeerde ik het in stukjes voor elkaar te krijgen. Daar wordt het overigens niet duidelijker van ;)
Ik ga me nu storten op RobIII zijn code.
Bedankt allemaal.

Acties:
  • 0 Henk 'm!

  • sig69
  • Registratie: Mei 2002
  • Laatst online: 20:06
Ik denk ook dat je een beetje verkeerd bezig bent. ShowDialog() is juist gemaakt om te blocken totdat een user een operatie voltooid of geannuleerd heeft, niet om halverwege iets anders te gaan doen en later verder te gaan. Misschien dat als je wat meer uitleg geeft wat de applicatie precies moet doen we een ander / beter voorstel kunnen doen om je gui op te zetten.

Roomba E5 te koop


Acties:
  • 0 Henk 'm!

  • DarkSilence
  • Registratie: December 2002
  • Laatst online: 06-07 20:28

DarkSilence

W3designer.nl

Verwijderd schreef op woensdag 20 januari 2010 @ 14:16:
Weer dezelfde vraag: waarom? Wat biedt een Singleton in dit geval voor voordeel over een simpele methode?
Nou wat is er niet simpel aan singelton?
Zie code voorbeeld hieronder. Deze code moet natuurlijk nog wat worden uitgebreid voor een Form om te kijken of deze al wordt weergegeven en in dat geval weer de focus te zetten en anders Form eerst weer te geven.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Singleton
{
   private static Singleton instance;

   private Singleton() {}

   public static Singleton Instance
   {
      get 
      {
         if (instance == null)
         {
            instance = new Singleton();
         }
         return instance;
      }
   }
}


Itereren over verzameling om het form te vinden en te kijken of die al geopend is lijkt me veel lastiger.

Singleton dwingt af dat er nooit 2 instances zijn van één class of in ons geval een Form. Dus qua code veel netter. :)

W3designer.nl


Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 08-09 11:33
DarkSilence schreef op woensdag 20 januari 2010 @ 15:50:
[...]

Nou wat is er niet simpel aan singelton?
Zie code voorbeeld hieronder. Deze code moet natuurlijk nog wat worden uitgebreid voor een Form om te kijken of deze al wordt weergegeven en in dat geval weer de focus te zetten en anders Form eerst weer te geven.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Singleton
{
   private static Singleton instance;

   private Singleton() {}

   public static Singleton Instance
   {
      get 
      {
         if (instance == null)
         {
            instance = new Singleton();
         }
         return instance;
      }
   }
}


Itereren over verzameling om het form te vinden en te kijken of die al geopend is lijkt me veel lastiger.

Singleton dwingt af dat er nooit 2 instances zijn van één class of in ons geval een Form. Dus qua code veel netter. :)
Nouja deze variant is bijvoorbeeld al niet thread-safe. Een Monitor.Enter en een Monitor.Exit in de get zou dat echter wel oplossen :).

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Let er wel op dat die Singleton niet Thread-Safe is!

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • DarkSilence
  • Registratie: December 2002
  • Laatst online: 06-07 20:28

DarkSilence

W3designer.nl

Woy schreef op woensdag 20 januari 2010 @ 15:59:
Let er wel op dat die Singleton niet Thread-Safe is!
Oké dat is op te lossen, het code voorbeeld was ter illustratie.

W3designer.nl


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
@sig69: Ik ben bezig met het maken van een plug-in voor een applicatie. In mijn plug-in kan ik een menu en een toolbar toevoegen aan de applicatie en ik implementeer een plugin interface.
De click events van het menu en de toolbar worden doorgestuurd naar de ItemClicked() methode in mijn code. Dan kan ik een formulier openen. Inderdaad gebruik ik voor de meeste forms een ShowDialog(). Maar ik heb ook een form die alleen tot doel heeft de mogelijkheden te tonen. Dus ik heb 6 menu opties en 6 buttons op mijn toolbar en ik wil op mijn extra formulier 6 buttons hebben die hetzelfde werken als wanneer ik op een toolbar button klik, nl. het openen van een specifiek form. De forms gaan een langdurig conversieproces starten (in een eigen thread). Daarom kan ik ze niet modal maken want ik wil de gebruiker de kans geven om verder te gaan met zijn werk.
Het conversieform kan dus worden geopend via het menu, een toolbar button en een button op mijn eigen form. Als ik het form al open heb, wil ik niet dat die nog eens wordt geopend als ik via 1 van de andere 3 opties het form aanroep.

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
DarkSilence schreef op woensdag 20 januari 2010 @ 16:03:
[...]

Oké dat is op te lossen, het code voorbeeld was ter illustratie.
Nou is dat ook nog niet triviaal, maar er is genoeg informatie over te vinden. Zoals bijvoorbeeld dit linkje: http://www.yoda.arachsys.com/csharp/singleton.html

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
Beuh singleton. Het is makkelijk, maar vies. Zie ook

http://tech.puredanger.co...3/pattern-hate-singleton/
http://blogs.msdn.com/sco...ve/2004/05/25/140827.aspx
http://steve.yegge.google...ngleton-considered-stupid
http://www.ibm.com/develo...es/library/co-single.html

(en dat, en meer, zijn pas de links vanuit Wikipedia).

Maar als dit slechts een experiment is / voor de lol ende lering ende vermaeck, dan maakt het niet zoveel uit.

Acties:
  • 0 Henk 'm!

  • analog_
  • Registratie: Januari 2004
  • Niet online
Wat ik zelf soms doe is de instance van het formulier in de .Tag van het knop zetten waarmee je het oproept. Is de Tag leeg, dan maak je er eentje aan, anders cast je het naar een Form en roept de .focus (of iets dergelijks) op. Niet vergeten natuurlijk de .Tag leeg te maken als je het formulier sluit.

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Verwijderd schreef op woensdag 20 januari 2010 @ 10:30:
Jullie hebben gelijk.
Als ik de LINQ Query wijzig in
C#:
1
var frmTemp = (from f in Application.OpenForms.Cast<Form>() where f.Name.Equals(formName) select f).ToList<Form>();

en
C#:
1
frmTemp[0].Activate();
gebruik, compileert de code weer.
Ik kan het nu even niet testen omdat er op andere plekken fouten ontstaan, maar ik begrijp het nu wel.
Hmm, vreemd dat sinds 10 uur niemand je erop heeft gewezen dat dit kan worden herschreven:
C#:
1
Application.OpenForms.Cast<Form>().First(f => f.Name == formName).Activate();

Hoewel FirstOrDefault eventueel in combinatie met ?? misschien handiger is. :)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hier ben ik nog een keer :P
Ik kom er nog steeds niet uit. Ik ben me gaan verdiepen in Generics en als ik daar over lees lijkt het allemaal zo logisch maar als ik het zelf moet toepassen, krijg ik het niet voor elkaar. Om moedeloos van te worden |:(
Ik ben weer helemaal terug gegaan naar het eerste antwoord van RobIII. Het gedeelte van controleren of het form al open is werkt en begrijp ik ook. De moeilijkheid zit er in als het form nog niet open is.

De delegate method newinstance moet dat gaan doen, maar daar loopt het al spaak. Wat moet ik precies in de method doen? Het specifieke form openen of dat op een generieke manier doen, zodat ik maar 1 methode heb die alle 6 forms kan openen?
Als ik het op mijn oude manier doe, open ik het form zo:
C#:
1
2
3
4
5
// Load the form:                        
this.frmImportCSV = new ImportCSV(this.extraObject);

// Show it on top
this.frmImportCSV.Show(Form.FromHandle(new IntPtr(this.parentHandle)));

En dat dan 6 keer voor elk form: ImportCSV, ExportCSV, ImportXLS, ExportXLS, etc.

Ik had dit al bedacht:
C#:
1
2
3
4
5
6
7
8
        public delegate Form FormCreateDelegate(extraObject, int parentHandle);
        public static Form OpenForm<T>(extraObject, int parentHandle)
            where T : Form
        {
            Form frm = new Form() as T;
            frm.Show(Form.FromHandle(new IntPtr(parentHandle)));
            return frm;
        }


Dit compileert wel, maar de aanroep krijg ik niet voor elkaar:
C#:
1
FormsHelper.GetWindow(ImportCSV, FormsHelper.OpenForm(this.extraObject, this.parentHandle), this.extraObject, this.parentHandle);


Met extraObject kan ik communiceren met de hoofdapplicatie en is nu niet relevant.

Als iemand me nog een keer in de juiste richting wil schoppen dan graag.
Anders geef ik me gewonnen en ga ik wel code dubbel doen. 8)7

Acties:
  • 0 Henk 'm!

  • BM
  • Registratie: September 2001
  • Laatst online: 18:56

BM

Moderator Spielerij
C#:
1
FormsHelper.GetWindow(ImportCSV, FormsHelper.OpenForm<HierHetTypeVanJeForm>(this.extraObject, this.parentHandle), this.extraObject, this.parentHandle);

?

En volgens mij klopt dit ook niet, je geeft nu een Form terug, terwijl je een object van het type T terug wilt geven.
C#:
1
2
3
4
5
6
7
8
        public delegate Form FormCreateDelegate(extraObject, int parentHandle);
        public static T OpenForm<T>(extraObject, int parentHandle)
            where T : Form
        {
            T frm = new T();
            frm.Show(Form.FromHandle(new IntPtr(parentHandle)));
            return frm;
        }


Geen idee of het klopt, ben niet zo'n held met generics.

[ Voor 62% gewijzigd door BM op 25-01-2010 13:38 ]

Xbox
Even the dark has a silver lining | I'm all you can imagine times infinity, times three


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik kom al dichterbij ;)
C#:
1
T frm = new T(); 
werkt niet, De compiler geeft
code:
1
Cannot create an instance of the variable type 'T' because it does not have the new() constraint

Daarop heb ik nog wat meer geprobeerd:
C#:
1
T frm = new Form() as T;
compileert wel. En als ik debug dan zie ik dat T netjes mijn ImportCSV form is, maar frm blijft null en dus frm,Show() werkt dan niet.

Ik ben er dus bijna ...

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Je zult een constraint op je generic type moeten leggen, dat garandeert dat hij een default constructor heeft. http://msdn.microsoft.com/en-us/library/sd2w2ew5(VS.80).aspx

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Het toevoegen van new() lijkt te werken. Er wordt nu eindelijk een form geopend!
Alleen niet het form dat ik wil: ImportCSV maar de template form. Alle 6 forms die ik wil openen zijn inhereted forms van een template. Die wordt nu geopend.
Dacht ik dat ik er bijna was, wordt de brij alleen maar groter 8)7

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Dan is dat je type parameter. Je zult natuurlijk wel moeten zorgen dat je Type Parameter ImportCSV is, en niet je template form ( Dat is ook de reden dat het casten met AS een null oplevert ).

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
@Woy: Ik heb je reply gisteren gemist, maar volgens mij geef ik de juiste Type Parameter mee.
Ik probeer eerst de OpenForm() method werkend te krijgen:
C#:
1
FormsHelper.OpenForm<Forms.ImportCSV>(this.extraObject, this.parentHandle);

En dit is mijn helper class:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    public static class FormsHelper
    {
        public delegate Form FormCreateDelegate(extraObject, int parentHandle);

        public static T OpenForm<T>(extraObject, int parentHandle)
            where T : Form, new()
        {
            T frm = new T();
            frm.Show(Form.FromHandle(new IntPtr(parentHandle)));
            return frm; 
        }

        public static T GetWindow<T>(Predicate<T> match, FormCreateDelegate newinstance, extraObject, int parentHandle)
            where T : Form
        {
            foreach (Form form in Application.OpenForms)
                if (form.GetType().Equals(typeof(T)) && match.Invoke(form as T))
                    return form as T;
            if (newinstance == null)
                return null;
            else
                return newinstance(extraObject, parentHandle) as T;
        }
    }

En als ik probeer GetWindow() te gebruiken, krijg ik de syntax niet goed.
Dus er gaat nog steeds wat fout. Ik heb al weer van alles uitgeprobeerd en dit is mijn laatste poging:
C#:
1
2
FormsHelper.GetWindow<Forms.ImportCSV>(delegate(Forms.ImportCSV f)
{return true;}, FormsHelper.OpenForm<Forms.ImportCSV>(extraObject, this.parentHandle), extraObject, this.parentHandle);


Het blijft toch allemaal te hoog gegrepen voor me. Misschien moet ik toch maar een thread-safe Singleton gaan gebruiken. :X

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Ik denk dat je je beter even in kan lezen in delegates en lambda's. Je probeert hier een Forms.ImportCSV in een FormDelegate te krijgen, en dat gaat niet lukken natuurlijk. Die "(extraObject, this.parentHandle)" slaat nergens op. ;) Daarnaast snap ik niet wat extraObject steeds doet, dat kan overal weg?

En het lijkt me handiger om gewoon alles in 1 methode te zetten, zodat je niet 3 keer <Forms.ImportCSV> hoeft te gebruiken bij het aanroepen. Daarnaast zou ik wel Linq gebruiken, en me ook daar even in inlezen.. ;)

Voor het geval ik onduidelijk ben geef ik maar even een voorbeeldmethode:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
        public static T GetActivatedWindow<T>(IntPtr parentHandle) where T: Form, new()
        {
            var f = Application.OpenForms.OfType<T>().FirstOrDefault();
            if (f == null)
            {
                f = new T();
                f.Show(Form.FromHandle(parentHandle));
            }
            else
                f.Activate();
            return f;
        }

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
@Pedorus: Jouw voorbeeldcode werkt precies zoals ik het bedoelde. Enorm bedankt!
Het was een lang traject, maar ik heb er veel van geleerd.

Ik heb net dit gelezen over C# Delegates, Anonymous Methods, and Lambda Expressions, erg verhelderend:
http://www.codeproject.com/KB/cs/DelegatesOMy.aspx

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op woensdag 27 januari 2010 @ 10:17:
@Pedorus: Jouw voorbeeldcode werkt precies zoals ik het bedoelde. Enorm bedankt!
Het was een lang traject, maar ik heb er veel van geleerd.

Ik heb net dit gelezen over C# Delegates, Anonymous Methods, and Lambda Expressions, erg verhelderend:
http://www.codeproject.com/KB/cs/DelegatesOMy.aspx
/rant
Ik vind dat soort voorbeelden voor delegates best vaak.. Slecht (deze dan iets minder). Of zeggen dat het 'lijkt op een functie-pointer uit C(++)', doh, alsof er dan opeens belletjes gaan rinkelen bij iedereen.
Vooral het voorbeeld waarin een soort calculator gebruikt word. Niet dat het niet klopt, maar omdat geen real-world probleem oplost. Het is leuk, maar veel mensen kunnen het daarna nog steeds niet toepassen en hebben nog geen idee waar ze het over hebben. Het is gewoon geen goede learn by example uitleg, imo.

Een veel betere methode (wederom imo) is probleem vinden in een praktische context.
Zoals: Stel je hebt een object wat een berekening doet. Het zou wenselijk kunnen zijn dat je van dat object informatie terug krijgt met betrekking tot de status van dat object/ die berekening.
Beschouw dit voorbeeld:
C#:
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
32
33
34
35
36
37
38
39
40
using System;
using System.Windows.Forms;

namespace DelegateExample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            textBox1.Text = "begin";
        }

        private void run_Click(object sender, EventArgs e)
        {            
            DureOperatie dop = new DureOperatie();
            dop.Operatie();
            textBox1.Text = "einde";
        }        
    }
}

using System.Threading;

namespace DelegateExample
{
    public class DureOperatie
    {
        public DureOperatie() { }

        public void Operatie()
        {
            for (int i = 1; i < 10; i++)
            {
                // doe dingen
                Thread.Sleep(1000);
            }
        }
    }
}

Nu gaat het object zijn werk doen, ondertussen blijft je GUI non-responsive en pas als het object klaar is krijg je een melding in het textbox.

Met een delegate kun je zorgen dat er tijdens het lopen van dat object toch communicatie richting je GUI een ander object is, namelijk als volgt:
Form
C#:
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
32
33
// run het, druk op start en prober op klik me te drukken
using System;
using System.Windows.Forms;

namespace DelegateExample
{
    public partial class Form1 : Form
    {
        void Update(string up)
        {
            textBox1.AppendText(up);
        }
        
        public Form1()
        {
            InitializeComponent();
            textBox1.Text = "begin";
        }

        private void run_Click(object sender, EventArgs e)
        {            
            DureOperatie dop = new DureOperatie();
            dop.Operatie(Update);

            textBox1.AppendText("Einde"); 
        }

        private void stoprun_Click(object sender, EventArgs e)
        {
            MessageBox.Show("heeeeeeeee");
        }        
    }
}

DureOperatie.cs
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System.Threading;

namespace DelegateExample
{
    public class DureOperatie
    {
        public delegate void Updater(string update);
        
        public DureOperatie() { }

        public void Operatie(Updater updater)
        {
            for (int i = 1; i < 10; i++)
            {
                // doe dingen
                Thread.Sleep(1000);
                
                if(updater!=null)
                    updater(string.Format("Bezig met: {0}", i));
            }
        }        
    }
}

Nu zorgt de delegate ervoor dat je UI ge-update wordt.
Uiteraard kun je hier verder in gaan, door het gebruik van thread/backgroundworker kun je er voor zorgen dat je UI als geheel responsive blijft. Zodat je tijdens het uitvoeren van de dure operatie de knop klik me kan gebruiken. Dat wordt dan zoiets:
C#:
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
using System;
using System.Windows.Forms;
using System.ComponentModel;

namespace DelegateExample
{
    public partial class Form1 : Form
    {
        public BackgroundWorker bgWorker;
        
        void Update(string up)
        {
            Invoke((Action)delegate { textBox1.AppendText(up); });
        }
        
        public Form1()
        {
            InitializeComponent();
            textBox1.Text = "begin";
        }

        private void run_Click(object sender, EventArgs e)
        {
            bgWorker = new BackgroundWorker();
            bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
            bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
            bgWorker.RunWorkerAsync();            
        }

        void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            textBox1.AppendText("KLAAR");
        }

        void bgWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            DureOperatie dop = new DureOperatie();
            dop.Operatie(Update);
        }

        private void klikme_Click(object sender, EventArgs e)
        {
            MessageBox.Show("heeeeeeeee");
        }        
    }
}

C#:
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
using System.Threading;

namespace DelegateExample
{
    public class DureOperatie
    {
        public delegate void Updater(string update);
        
        public DureOperatie() { }

        public void Operatie(Updater updater)
        {
            for (int i = 1; i < 10; i++)
            {
                // doe dingen
                Thread.Sleep(1000);
                
                if(updater!=null)
                    updater(string.Format("Bezig met: {0}", i));
            }
        }

        
    }
}


Voor het gemak nog even de designer code:
C#:
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
namespace DelegateExample
{
    partial class Form1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.label1 = new System.Windows.Forms.Label();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.run = new System.Windows.Forms.Button();
            this.klikme = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(9, 4);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(38, 13);
            this.label1.TabIndex = 0;
            this.label1.Text = "status:";
            // 
            // textBox1
            // 
            this.textBox1.Location = new System.Drawing.Point(12, 20);
            this.textBox1.Multiline = true;
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(260, 84);
            this.textBox1.TabIndex = 1;
            // 
            // run
            // 
            this.run.Location = new System.Drawing.Point(116, 110);
            this.run.Name = "run";
            this.run.Size = new System.Drawing.Size(75, 23);
            this.run.TabIndex = 2;
            this.run.Text = "start";
            this.run.UseVisualStyleBackColor = true;
            this.run.Click += new System.EventHandler(this.run_Click);
            // 
            // klikme
            // 
            this.klikme.Location = new System.Drawing.Point(197, 110);
            this.klikme.Name = "klikme";
            this.klikme.Size = new System.Drawing.Size(75, 23);
            this.klikme.TabIndex = 3;
            this.klikme.Text = "klik me";
            this.klikme.UseVisualStyleBackColor = true;
            this.klikme.Click += new System.EventHandler(this.klikme_Click);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(284, 134);
            this.Controls.Add(this.klikme);
            this.Controls.Add(this.run);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.label1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.Button run;
        private System.Windows.Forms.Button klikme;
    }
}


Volgens mij heb je nu een best duidelijk voorbeeld van hoe je interactie tussen 2 objecten kunt bewerkstelligen en nog een extraatje voor je UI.
Het is slechts een voorbeeld en er zijn meerdere wegen die naar rome leiden (of lijden :+), maar her illustreert wel de functionaliteit op een duidelijke manier, IMO.

Eeeeeh, tijd teveel.

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Ik heb niet je hele text doorgelezen. Maar het lijkt erop alsof het volgende je insteek is
Met een delegate kun je zorgen dat er tijdens het lopen van dat object toch communicatie richting je GUI is, namelijk als volgt:
Maar dat vind ik nogal een gekke manier om delegates uit te leggen. Dat je delegates gebruikt om iets op een andere thread te kunnen draaien heeft feitelijk helemaal niks met het begrip delegates te maken.

Je bent dan eigenlijk ook meer bezig met een het Threading principe van WinForms aan het uitleggen ( Wat toevallig gebruik maakt van delegates )

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

Verwijderd

Ik probeer alleen maar even een duidelijk, tast/zichtbaar, voorbeeld van de communicatie tussen 2 objecten, middels een delegate, neer te zetten (zichtbaar gemaakt in een textbox). Kort door de bocht is dat toch precies wat een delegate doet? Zorgen dat objecten met elkaar kunnen praten. Dat het ene object nu toevallig een Form is doet daar toch verder niets aan af (ook al heb je uiteraard gelijk dat GUI-responsiveness an-sich niet direct iets met een delegate te maken heeft). Ik heb het in een winform gegoten zodat je iets tastbaars hebt.

Je drukt op een knop er gaat een object wat doen en dat object geeft updates over haar status terug aan een ander object.

De zin die je quote was niet goed gekozen, heb het veranderd.

[ Voor 83% gewijzigd door Verwijderd op 27-01-2010 13:36 ]


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Verwijderd schreef op woensdag 27 januari 2010 @ 13:05:
Je drukt op een knop er gaat een object wat doen en dat object geeft updates over haar status terug aan een ander object.
Ook hier heb je het weer over threading. Het begrip delegates staat daar in feite los van. In feite is een delegate gewoon een manier om een taak te delegeren aan iets anders. Heel simpel gezegd is een delegate gewoon een interface voor een losse methode.

Dat het ook veel gebruikt word in winforms en threading klopt wel. Maar je haalt er meteen veel te veel andere dingen bij waardoor juist het begrip delegates een beetje ondergesneeuwd raakt. Dat zie je ook al aan de hoeveelheid code die je aanhaalt om delegates te demonstreren.

Ik vind een voorbeeldje wat lijkt op Array.Find ( http://msdn.microsoft.com/en-us/library/d9hy2xwa.aspx ) veel duidelijker. Daar delegeer je het daadwerkelijk bepalen of iets aan een voorwaarde voldoet aan een Predicate<T> delegate.

[disclaimer]
Ik zeg niet dat je onzin loopt te verkopen ofzo, maar ik vind het juist niet zo'n handige manier om het begrip delegates uit te leggen.

[ Voor 10% gewijzigd door Woy op 27-01-2010 14:03 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

Verwijderd

Woy schreef op woensdag 27 januari 2010 @ 13:57:
[...]
Ik vind een voorbeeldje wat lijkt op Array.Find ( http://msdn.microsoft.com/en-us/library/d9hy2xwa.aspx ) veel duidelijker. Daar delegeer je het daadwerkelijk bepalen of iets aan een voorwaarde voldoet aan een Predicate<T> delegate.
Ok, point taken, dat is een zeer duidelijk voorbeeld :)
[disclaimer]
Ik zeg niet dat je onzin loopt te verkopen ofzo, maar ik vind het juist niet zo'n handige manier om het begrip delegates uit te leggen.
Ik voel me ook niet op m'n pik getrapt hoor. Ik kan goed tegen kritiek en vind (nuttige) meningen van ander waardevol en leerzaam. Zelf vond ik het makkelijker om events en delegates op die manier te leren, top-down (dit werkt door een delegate -> oh wat is een delegate -> dat is een delegate, conclusie -> dan kun je die ook zo gebruiken). Maar ik hoor wel vaker dat ik een aparte manier van leren heb :+

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Ik zie in die tutorial nog best wel belangrijke aspecten van lambda's die onbehandeld blijven. Bijvoorbeeld: :p
pedorus schreef op woensdag 25 november 2009 @ 22:56:
Even voor je idee: wat denk je dat deze code doet?
C#:
1
2
3
            for (int i = 1; i < 10; i++)
                ThreadPool.QueueUserWorkItem(_ => Invoke((Action)(()=> 
                    MessageBox.Show(i.ToString()))));
Helaas weer een voorbeeld met multi-threading; hetzelfde probleem kan ook zonder.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten

Pagina: 1