Avatar billede charly Nybegynder
15. september 2006 - 22:29 Der 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å?
Avatar billede dj_uncas Nybegynder
15. september 2006 - 23:08 #1
Du kan jo lave en nedarving af Button kontrollen og sætte Enabled = false på som det første i eventhandleren der.

public class OneClickButton : Button
{
    public Button()
    {
        this.Click += new EventHandler( this_Click );
    }

    protected void this_Click( object sender, EventArgs e )
    {
        this.Enabled = false;
    }
}
Avatar billede charly Nybegynder
15. september 2006 - 23:44 #2
Tak for forslaget men jeg mener stadig at den fanger flere click events hvis jeg er meget hurtig ;-)
Avatar billede mikkelbm Nybegynder
16. september 2006 - 00:44 #3
bool working = false;

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?
Avatar billede mickni33 Nybegynder
16. september 2006 - 10:05 #4
Måske kan man bruge en mouseUP event, sådan her:


bool a=true;

private void DrawForm_Button_Click(object sender, KeyEventArgs e)
        {
            if (a == true )
            {
                Console.Out.WriteLine("button Click");
                a = false;
            }
        }

        private void DrawForm_MouseUP(object sender, KeyEventArgs e)
        {
            a = true;
            Console.Out.WriteLine("Button Not Clicked");
        }
Avatar billede mikkelbm Nybegynder
16. september 2006 - 10:12 #5
>> mickni33

Ja, bortset fra at dine metoder ikke modsvarer det delegat en mouseup forventer :)

Du har KeyEventArgs i stedet for MouseEventArgs!


Og ellers er der vel ikke noget at hente ved at tilmelde sig to event frem for én?
Avatar billede charly Nybegynder
16. september 2006 - 11:08 #6
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.
Avatar billede mickni33 Nybegynder
16. september 2006 - 11:22 #7
>>mikkelbm
heheheh det har du ret i, det er fordi jeg brugte den ved en keyevent.
længe leve cut& paste :-)
Avatar billede mikkelbm Nybegynder
16. september 2006 - 17:43 #8
Jeg er temmelig sikker på, at forslaget virker!
Avatar billede charly Nybegynder
17. september 2006 - 13:13 #9
Hej igen,

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;
            }
        }       
    }
Avatar billede mikkelbm Nybegynder
17. september 2006 - 13:24 #10
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?
Avatar billede charly Nybegynder
17. september 2006 - 13:46 #11
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.
Avatar billede mikkelbm Nybegynder
17. september 2006 - 14:08 #12
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();

      ((Button)sender).Enabled = true;
  }
}
Avatar billede mikkelbm Nybegynder
17. september 2006 - 14:08 #13
Og et svar...
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester