简体   繁体   中英

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.

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().

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.

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          
    }

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 event and the event. 事件和事件。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM