smanookian
smanookian

Reputation: 287

Button release after x seconds

In my application I need a button that you can press once and it changes its state and appearance to pressed. After 1 seconds the pressed button should be released.

I tried doing that with ToggleButton and CheckBox. But this is not what I need.

EXAMPLE: I press the Button. Color of a rectangle is changed. After 1 second the Button is released.

Any suggestions?

UPDATE: The button should play a sound. If I use ToggleButton or CheckBox that sound is played twice, because the button is checked two times.

Upvotes: 1

Views: 802

Answers (4)

Kevin
Kevin

Reputation: 2243

Something I wanted to add: consider using Task instead of a Timer. One the plus side, it means you don't have to clean up after a DispatchTimer and stop it; on the negative side, it means you need to use Invoke() on the GUI object instead of changing it directly (because it'll be running from the non-gui thread.)

Here's some simple code that just does a momentary button disable/enable to illustrate:

private void btnTest_Click(object sender, EventArgs e)
{
    btnTest.Enabled = false;
    Task t = new Task(async () =>  { await Task.Delay(2000); EnableButton(); });
    t.Start();
}
private void EnableButton()
{
    btnTest.Invoke((MethodInvoker)delegate { btnTest.Enabled = true; });
}

EDIT: changed to use Task.Delay instead of Thread.Sleep().

Upvotes: 2

na th
na th

Reputation: 145

i wrote a test application with your requirement. my Xaml file looks like following

<Window x:Class="toggleButtonTimer.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:toggleButtonTimer"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <StackPanel>
        <TextBlock x:Name="_value"></TextBlock>
        <ToggleButton Width="100" Height="100" x:Name="_toggle" Click="_toggle_Click" IsChecked="False"></ToggleButton>
    </StackPanel>
</Grid>

Code behind is as follows (modified the code from Tronald..)

    using System;
    using System.Windows;
    using System.Windows.Threading;
 ....


    private int value = 0;
    private void _toggle_Click(object sender, RoutedEventArgs e)
    {
        _toggle.IsChecked = true;

        //Create New DispatcherTimer
        DispatcherTimer dst = new DispatcherTimer();
        dst.Interval = new TimeSpan(0, 0, 1);  //Set Interval to 1 second.       
        dst.Tick += Dst_Tick;
        dst.Start(); //Start Timer  

        value++;
        _value.Text = value.ToString();
    }

    //Timer Elapsed Event
    private void Dst_Tick(object sender, EventArgs e)
    {
        DispatcherTimer t = (DispatcherTimer)sender; //Grab the DispatcherTimer
        t.Stop(); //Stop the timer or it will keep looping
        _toggle.IsChecked = false; //Reset the ToggleButton    

        value--;
        _value.Text = value.ToString();
    }

The TextBlock counts +1 the variable everytime click is fired and when the timer elapses, it counts -1. So the textBlock stays 0 after a cycle. This works fine for me. Because the result at the end is 0. So the event is processed only once.

It worked both for Click event and the Checked event.

Upvotes: 0

Tronald
Tronald

Reputation: 1585

Your best bet is to go back and use the ToggleButton, but reset it after 1 second. That is what it's for. Create a click event for your ToggleButton and the make a DispatcherTimer to handle the delayed toggle.

    //Reference
    using System.Windows.Timers;

    //Toggle Button Click Event
    private void button_Click(object sender, RoutedEventArgs e)
    {
        button.IsChecked = true;

        //Create New DispatcherTimer
        DispatcherTimer dst = new DispatcherTimer();
        dst.Interval = new TimeSpan(0, 0, 1);  //Set Interval to 1 second.       
        dst.Tick += Dst_Tick;                   
        dst.Start(); //Start Timer  
    }

    //Timer Elapsed Event
    private void Dst_Tick(object sender, EventArgs e)
    {
        DispatcherTimer t = (DispatcherTimer)sender; //Grab the DispatcherTimer
        t.Stop(); //Stop the timer or it will keep looping
        button.IsChecked = false; //Reset the ToggleButton          
    }

Upvotes: 0

John A.
John A.

Reputation: 1

Maybe you could use a timer event with interval 1000 (1 second)? Like you press the button, fire up the timer event and when 1 second passes release the button.

Upvotes: 0

Related Questions