15. september 2006 - 22:29Der er
12 kommentarer og 1 løsning
Undgå flere klik på GUI
Hej,
Har et generelt problem. Arbejder med windows forms.
Eksempel: Har en OK knap på en windows form, som ved klik håndterer noget logik. Hvis brugeren klikker flere gange på knappen lynhurtigt efter hinanden bliver logikken afviklet tilsvarende gange.
Hvordan låser jeg for at brugeren kan klikker flere gange? Jeg har prøvet lidt med noget ala btnOK.Enabled = false i starten af mine eventhandlere. Men dette betyder jo, at jeg skal skrive den samme kode mange gange!
Findes der en smart måde at håndtere mit problem på?
Teknologi, AI og forretning er i centrum på Computerworlds Cloud og AI Festival i København d. 18. og 19. september. Se hele programmet for den store konference om strategisk brug af Cloud og AI på: www.cloud-festival.dk
void click (object sender, EventArgs e) { if (!working) { working = true; DoWork(); working = false; } }
void DoWork() { //... }
Var en anden mulighed. Normalt sætter jeg også bare button.Enabled til false. Og du kan ikke nå at trigger den flere gange (selvom du er hurtig), da gui'en kører én tråd.
Jeg forstår ikke helt hvad du mener med, at du skal skrive den samme kode flere gange, bare fordi du disabler din knap i event-handleren?
Mikkelbm: Jeg er med på at GUI'en afvikles i een tråd. Men det er ligesom at ens click events bliver lagt på kø hvis man trykker hurtigt efter hinanden.
Eksempel: Hvis jeg har en søg knap og brugeren trykker 10 gange på den, vil mit click-event blive sekventielt afviklet 10 gange. Jeg søger en løsning, hvor brugeren måske nok klikker 10 gange, men at søgningen kun afvikles een gang! Når søgningen så er færdig, vil jeg så lade brugeren klikke igen - og udføre søgningen. Det er sgu' svært at forklare :-)
Måske fungerer dit forslag med at erklære en working variabel som en global variabel på formen.
Ja, det virker nok som det skal :-) Men det virker bare ikke efter den hensigt, som jeg havde tiltænkt. Hvis man prøver nedenstående eksempel, vil man opleve at det enkelte event vil blive afviklet ligeså mange gange, som man fik trykket. Kan man på nogen måde sige til systemet, at man ikke ønsker disse clickevents lagt på kø?
public partial class Form1 : Form { private int counter = 0; private bool working;
public Form1() { InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) { if (!working) { working = true; this.Text = Convert.ToString(counter++); System.Threading.Thread.Sleep(2000); working = false; } } }
Jeg ved ikke om du kan gøre det, uden at sætte enabled til false på dine knapper. For du sleeper jo på gui-tråden, så det er naturligt nok, at det andet bare bliver lagt i kø. Men det er vel også det du vil opnå? At din kode ikke kan køres flere gange uden at det er fuldført?
mikkelbm, du har været så ihærdig så smid et svar så får du points!
Jo, det kan være at det er måden jeg tænker på, der er forkert.
Jeg ser bare et lille problem i følgende eksempel, som andre da også må ha oplevet:
Hvis nu man har en toolstripbutton i sin toolbar på sin form(kaldet form A fra nu af). Denne knap aktiverer så en ny form(kaldet form B fra nu af), som så indeholder en masse logik osv.
Hvis man nu klikker 3-4 gange hurtigt efterhinanden på knappen på form A, vil den rigtig nok åbne form B. Problemet er nu bare når form B lukkes igen. Der vil ske det(grundet at de enkelte clicks er lagt på kø), at form B åbnes igen! Dette uhensigtsmæssige flow vil jo foregå de 3-4 gange brugeren nåede at klikke på knappen på form A. Det vil brugeren nok opleve som en fejl, da han måske blot ønskede at åben form B.
Det har du ret i. Derfor tror jeg også at den eneste løsning er at disable de knapper hvor du har denne form for logik. For når en knap er disabled modtager den ikke click-events.
Men du kan jo centralisere den logik en smule ved at tilmelde dine knapper den samme event-handler.
F.eks.
Button a; // Kunne også være toolstrip knapper Button b; Button c;
a.Click += new EventHandler (MyButtonClick); b.Click += new EventHandler (MyButtonClick); c.Click += new EventHandler (MyButtonClick);
void MyButtonClick (object sender, EventArgs args) { if (sender is Button) { ((Button)sender).Enabled = false;
if (sender == a) DoAWork(); else if (sender == b) DoBWork(); else if (sender == c) DoCWork();
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.