5

I have a button in my WPF project and I want to it execute the same command over and over when I hold the button down. I could use RepeatButton but my preference would be for the command to execute again as soon as it is done running (in its own Task) instead of relying on the delay and interval properties of the RepeatButton control.

I wouldn't mind making a button click method but the command action is long running and the execution time will be dependent on the value of the ExecuteParameter (in this case a tuple of doubles representing a physical position of a machine).

XAML:

<Button FontFamily="Marlett" FontSize="40" Content="5" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="100" Width="100" Height="50"                            
        Command="{Binding IncrBAnglePos}" 
        CommandParameter="{Binding ElementName=slider, Path=Value}">
</Button>

C#:

SystemCommands.AddSubSystemCommand(SystemRef, CommandNames.IncrAngle, new RelayCommand(             
        o => 
        {
            double AngleIncr = (double)o > 5 ? 5 : (double)o;
            double nextX = MotionControl.LiveX;
            double nextB = MotionControl.LiveB + AngleIncr;
            nextB = nextB >= 45 ? 45 : nextB;       
                Task.Run(() =>  
                {
                    SystemCommands.ExecuteCommand(CommandNames.GotoPosition, new Tuple<double,double>(nextX, nextB));
                });
        },       
        _ => 
        {
            if (MotionControl == null)
                return false;
            return !MotionControl.InMotionCheckStatus;
        }));
if (MotionControl != null)
{
    MotionControl.MotionChanged += SystemCommands.GetRelayCommand(CommandNames.IncrAngle).CanExecutePropertyChangedNotification;
}

Update: I can see a few people have poked their heads in an taken a look. If anyone has a suggestion about how I could improve the question itself I would welcome the feedback. From my lack of reputation you can probably surmise that I am new at this.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
AClark
  • 47
  • 5
  • btw second lambda can be simplified: `_ => MotionControl != null && !MotionControl.InMotionCheckStatus` – abatishchev Dec 22 '17 at 19:22
  • Excellent suggestion. Thanks abatishchev. Its verbose and weird right now while I try and get all of the components working together properly. I'll refactor before shipping it. – AClark Dec 22 '17 at 19:39

1 Answers1

2

The Repeat Button should do what you are looking for

Interval -> the amount of time, in milliseconds, between repeats once repeating starts. The value must be non-negative.

Delay -> the amount of time, in milliseconds, the RepeatButton waits while it is pressed before it starts repeating.

<RepeatButton  FontFamily="Marlett" 
        Delay="500" 
        Interval="100" 
        FontSize="40" 
        Content="5" 
        HorizontalAlignment="Center" 
        VerticalAlignment="Top" 
        Margin="100" 
        Width="100" 
        Height="50"        
        Command="{Binding IncrBAnglePos}" 
        CommandParameter="{Binding ElementName=slider, Path=Value}">
</RepeatButton>
Terrance
  • 11,764
  • 4
  • 54
  • 80
  • Terrance, I am delighted to be wrong and learn that the RepeatButton control works just as well on command bindings as it does with a button click method. Thanks to everyone who looked at this for me. – AClark Dec 22 '17 at 19:50