Mal 'ne Frage
Freitag, 12.5.2017, 09:25 > daMaxSind hier .NET-Entwickler anwesend? Ich habe ein relativ lustiges Problem mit einer WinForm mit mehreren hundert Checkboxes, die in einem For-Loop automatisch alle gecheckt werden sollen, was endlos dauert, aber wenn hier eh niemand da ist, der das Problem versteht, werde ich nicht ins Detail gehen, denn die Problembeschreibung dauert etwas länger...
Ich würde mir eine "Schicht" basteln, welche die Zustände der Checkboxen spiegelt. Beim Öffnen der Form und im Changed-Event der Controls bekommt die Liste (vielleicht ein Dictionary oder was auch immer) die jeweiligen Init-Zustände und Änderungen verpasst und iteriert wird später nicht mehr über die Controls, sondern über deren Repräsentant.
@R@iner: in der Tat habe ich so was ähnliches schon im Datenmodell drinnen (die Businessobjekte wissen, ob sie angehakt sind oder nicht), aber: leider geht es nicht um das erstmalige Anzeigen der Form, sondern das soll zur Laufzeit passieren (select all / deselect all). Und der "normale" Hack dazu lautet SuspendDrawing. Das kannste dann auf das gesamte Form laufen lassen und alles ist fast gut, zumindest flackert nichts und die Performance ist um Faktor 100 besser.
Der Haken an der Geschichte ist etwas komplizierter zu beschreiben: SuspendDrawing lässt den Dialog irgendwie "verschwinden" und zeichnet bloß nicht mehr neu hin, was "dahinter" ist. Dadurch sieht es für den Anwender so aus, als wäre der Dialog noch da, in Wirklichkeit ist er aber weg. Leider geht dadurch jeder weitere Mausklick "durch den Dialog durch", also nimmt das Programm "dahinter" den Klick entgegen und kommt in den Vordergrund.
Wenn also ein Anwender den "Select all" Button doppelklickt (jaja, das ist bescheuert, passiert aber eben doch mal), poppt das "dahinter" liegende Programm "nach vorne". Ja, ich weiß, das ist schwer zu verstehen, aber ich kann leider kein Video davon machen wegen Intellectual Property und NDA und so.
Ich bin immer noch baff, dass es in .NET kein natives "hör auf die Controls zu zeichnen bis ich was anderes sage" gibt.
Ich hatte auch schon damit herumgespielt, das Panel in dem all diese Controls gruppiert sind, auf .Visible = false zu setzen, was aber zum derzeit nächsten Problem führt, weil in dem Loop nur diejenigen Checkboxen selektiert werden sollen, die zurzeit .Visible sind (weil es eine "Filtermöglichkeit" gibt, die im Endeffekt das .Visible von Checkboxen verändert, wenn eine Checkbox nicht "zum Filter passt"), und die erben ihr .Visible vom Elternelement
Aber an genau dieser Stelle werde ich jetzt deine Idee mit berücksichtigen: die Filter-Methode wird nicht mehr direkt das .Visible-Property setzen, sondern es wird im Datenmodell eine "Gib mir alle Datenobjekte passend zum Filter" geben. Dann kann ich
1. das umgebende Element unsichtbar machen
2. mir alle Businessobjekte passend zum aktuellen Filter holen
3. deren .Checked-Property verändern
4. das umbegende Element wieder sichtbar machen
und ein "Filtern" tut das gleiche, nur mit .Visible anstelle von .Checked.
Mal sehen, ob das dann performt.
Ich hab' das nie verstanden, warum man immer noch die WIN32-API direkt aufrufen muss. Die Zukunft hatte ich mir anders vorgestellt.
Gutes Gelingen!
p.s.: Noch ein Vorschlag für ein Posting: Bedenkliche Entwicklung: Wie Providern "Vorratsdatenspeicherung as a Service" angeboten wird
Puh, also alles Rumprobieren half nicht. Ich suspende jetzt nicht mehr die komplette Form sondern "nur noch" eines der so ziemlich alles enthaltenden Controls. So bleibt ein Doppelklick wenigstens in der App. Zwar wird die Funktionalität des Buttons dann doppelt ausgeführt aber das ist mir jetzt wurscht.
PS: danke für den Link.
Button nach klick auf disabled setzten sollte das doppelte ausführen verhindern
@Rafael: Depp.
@alle: für den unwahrscheinlichen Fall, dass hier noch jemand mitliest: ich habe inzwischen einen anderen Workaround eingebaut. Wenn die Form eigentlich "kurz mal Pause machen" soll, wird jetzt ein dynamisch erzeugtes, dialogfüllendes Label mit dem Inhalt "PLEASE WAIT" bei MainDialog.Controls hinzugefügt und danach wieder gekillt. Damit werden die Controls alle effektiv nicht mehr gezeichnet, ein Select-All dauert vielleicht noch 1.5 Sekunden statt derer 4.
Das ist zwar immer noch viel zu lang und sehr hässlich, besser kriege ich es nicht hin.
Falls jemand eine elegantere Lösung hat: immer her damit.