Prevent double-click from double firing a command

前端 未结 14 1688
情书的邮戳
情书的邮戳 2020-12-15 08:34

Given that you have a control that fires a command:

Is there a way to prevent the command from being fired

相关标签:
14条回答
  • 2020-12-15 09:09

    Assuming that WPF Commanding doesn't give you enough control to mess with the click handler, could you put some code in the command handler that remembers the last time the command was executed and exits if it is requested within a given time period? (code example below)

    The idea is that if it's a double-click, you'll receive the event twice within milliseconds, so ignore the second event.

    Something like: (inside of the Command)

    
    // warning:  I haven't tried compiling this, but it should be pretty close
    DateTime LastInvoked = DateTime.MinDate;
    Timespan InvokeDelay = Timespan.FromMilliseconds(100);
    {
      if(DateTime.Now - LastInvoked <= InvokeDelay)
         return;
    
      // do your work
    }
    
    

    (note: if it were just a plain old click handler, I'd say follow this advice: http://blogs.msdn.com/oldnewthing/archive/2009/04/29/9574643.aspx )

    0 讨论(0)
  • 2020-12-15 09:10

    Wrap the code in a try-catch-finally or try-finally block. The finally statement will always be called regardless of any error occurring in the try.

    Example

        private Cursor _CursorType;
        // Property to set and get the cursor type
        public Cursor CursorType
        {
          get {return _CursorType; }
          set
          {
            _CursorType = value;
            OnPropertyChanged("CursorType");
          }
        }
    
    
        private void ExecutedMethodOnButtonPress()
        {
           try
           {
             CursorType = Cursors.Wait;
             // Run all other code here
           }
           finally
           {
             CursorType = Cursors.Arrow;
           }
        }
    

    NOTE: the CursorType is a property that the UserControl or Window is bound to

    <Window 
    Cursor = {Binding Path=CursorType}>
    
    0 讨论(0)
  • 2020-12-15 09:12

    If your control derives from System.Windows.Forms.Control, you can use the double click event.

    If it doesn't derive from System.Windows.Forms.Control, then wire up mousedown instead and confirm the click count == 2 :

    private void Button_MouseDown(object sender, MouseButtonEventArgs e)
    {
        if (e.ClickCount == 2)
        {
           //Do stuff
        }
     }
    
    0 讨论(0)
  • 2020-12-15 09:13

    You could set a flag

    bool boolClicked = false;
    button_OnClick
    {
        if(!boolClicked)
        {
            boolClicked = true;
            //do something
            boolClicked = false;
        }
    }
    
    0 讨论(0)
  • 2020-12-15 09:16

    You'd think that it would be as simple as using a Command and making CanExecute() return false while the command is running. You would be wrong. Even if you raise CanExecuteChanged explicitly:

    public class TestCommand : ICommand
    {
        public void Execute(object parameter)
        {
            _CanExecute = false;
            OnCanExecuteChanged();
            Thread.Sleep(1000);
            Console.WriteLine("Executed TestCommand.");
            _CanExecute = true;
            OnCanExecuteChanged();
        }
    
        private bool _CanExecute = true;
    
        public bool CanExecute(object parameter)
        {
            return _CanExecute;
        }
    
        private void OnCanExecuteChanged()
        {
            EventHandler h = CanExecuteChanged;
            if (h != null)
            {
                h(this, EventArgs.Empty);
            }
        }
    
        public event EventHandler CanExecuteChanged;
    }
    

    I suspect that if this command had a reference to the window's Dispatcher, and used Invoke when it called OnCanExecuteChanged, it would work.

    I can think of a couple of ways to solve this problem. One's JMarsch's approach: simply track when Execute is called, and bail out without doing anything if it was called in the last few hundred milliseconds.

    A more robust way might be to have the Execute method start a BackgroundWorker to do the actual processing, have CanExecute return (!BackgroundWorker.IsBusy), and raise CanExecuteChanged in when the task is complete. The button should requery CanExecute() as soon as Execute() returns, which it'll do instantly.

    0 讨论(0)
  • 2020-12-15 09:17

    I had the same issue and this worked for me:

    <Button>
        <Button.InputBindings>
                <MouseBinding Gesture="LeftClick" Command="New" />
        </Button.InputBindings>
    </Button>
    
    0 讨论(0)
提交回复
热议问题