Where is the WPF Timer control?
The usual WPF timer is the DispatcherTimer
, which is not a control but used in code. It basically works the same way like the WinForms timer:
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += dispatcherTimer_Tick;
dispatcherTimer.Interval = new TimeSpan(0,0,1);
dispatcherTimer.Start();
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
// code goes here
}
More on the DispatcherTimer can be found here
How do I create a timer in WPF?
In WPF, you use a DispatcherTimer
.
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0,5,0);
dispatcherTimer.Start();
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
// code goes here
}
WPF C# - Timer countdown
I've figured the complete code out as such:
DispatcherTimer _timer;
public MainWindow()
{
_myTimer = new DispatcherTimer();
_myTimer.Tick += MyTimerTick;
_myTimer.Interval = new TimeSpan(0,0,0,1);
}
private void ElementFlowSelectionChanged(object sender, SelectionChangedEventArgs e)
{
_counter = 0;
_myTimer.Stop();
_myTimer.Interval = new TimeSpan(0, 0, 0, 1);
_myTimer.Start();
}
private int _counter;
public int Counter
{
get { return _counter; }
set
{
_counter = value;
OnPropertyChanged("Counter");
}
}
private void MyTimerTick(object sender, EventArgs e)
{
Counter++;
if (Counter == 2)
{
_myTimer.Stop();
MessageBox.Show(“Reached the 2 second countdown”);
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler e = PropertyChanged;
if (e != null)
{
e(this, new PropertyChangedEventArgs(propertyName));
}
}
Show a running timer in a WPF window
Here is a very basic example I threw together.
using System.Windows.Threading;
namespace BasicTimer
{
public partial class MainWindow : Window
{
DispatcherTimer t;
DateTime start;
public MainWindow()
{
InitializeComponent();
t = new DispatcherTimer(new TimeSpan(0, 0, 0, 0, 50), DispatcherPriority.Background,
t_Tick, Dispatcher.CurrentDispatcher); t.IsEnabled = true;
start = DateTime.Now;
}
private void t_Tick(object sender, EventArgs e)
{
TimerDisplay.Text = Convert.ToString(DateTime.Now - start);
}
MainWindow XAML
<Window x:Class="BasicTimer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="100" Width="200">
<Grid>
<TextBlock x:Name="TimerDisplay" HorizontalAlignment="Left"/>
</Grid>
</Window>
WPF Multiple Timer Control
its better to use just one System.Windows.Threading.DispatcherTimer
with 100ms as ticks, then use Tags to determine its own interval, for example you can use
struct IntervalComparer
{
int myinterval; //the individual update interval (300ms for example)
int currentinterval;
public IntervalComparer(int myinterval)
{
this.myinterval=myinterval;
this.currentinterval=0;
}
public void TickMe()
{
currentinterval++;
}
public void ResetkMe()
{
currentinterval = 0;
}
public bool CanIUpdate()
{
return myinterval == currentinterval;
}
}
on the creation
.... Form_Loaded....
{
.....
mypanel=new Panel();
mypanel.Tag= new IntervalComparer(2); // 2 * 100ms
.....
}
.... Timer_Tick....
{
....
(mypanel.Tag as IntervalComparer).TickMe();
if((mypanel.Tag as IntervalComparer).CanIUpdate())
{
UpdateMyPanel();//your update method
(mypanel.Tag as IntervalComparer).ResetMe();
}
....
}
WPF / C# (No MVVM) Timer with Countdown Clock
You don't actually need more than a simple DispatcherTimer and a DateTime that is cyclically reset to the current time + 300 seconds.
public partial class MainWindow : Window
{
private readonly DispatcherTimer timer = new DispatcherTimer();
private DateTime endTime;
public MainWindow()
{
InitializeComponent();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += new EventHandler(OnTimerTick);
timer.Start();
}
private void OnTimerTick(object sender, EventArgs e)
{
var now = DateTime.Now;
if (endTime < now)
{
endTime = now.AddSeconds(300);
}
label.Content = (endTime - now).ToString(@"mm\:ss");
}
}
How to Perfectly stop DispatcherTimer in C# WPF
You're adding a new Tick handler each time you click the Button. You may also want to check if the timer is already running before starting it again. Otherwise you would reset the interval.
Move the first two lines of btnStart_Click to a Window1 constructor:
private readonly DispatcherTimer timer = new DispatcherTimer();
public Window1()
{
timer.Interval = TimeSpan.FromMilliseconds(1000);
timer.Tick += new EventHandler(timer_Tick);
}
private void btnStart_Click(object sender, RoutedEventArgs e)
{
if (!timer.IsEnabled)
{
timer.Start();
}
}
private void btnStop_Click(object sender, RoutedEventArgs e)
{
timer.Stop();
}
private void timer_Tick(object sender, EventArgs e)
{
//data insert
}
As further improvements you could do the following:
- enable and disable the Start and Stop Buttons according to the IsEnabled state of the timer
- replace the two Buttons by a single ToggleButton
- bind the ToggleButton's IsChecked property to the IsEnabled property of the timer.
- move the timer code to a view model
Accessing form controls during Timer.Elapsed event
The System.InvalidOperationException
looks like it is caused by cross-thread access to a UI component. The System.Timers.Timer
by default fires the Elapsed
event on a thread pool thread. Using DispatcherTimer
and the Tick
event will get things on the right thread for accessing the UI in WPF.
It also looks like you may have duplicate event handlers wired up, since you have both WithEvents
/Handles
and AddHandler
, but I'm not entirely sure how that works in WPF. You probably want something like (untested):
Private attendanceFetchTimer As System.Windows.Threading.DispatcherTimer
Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
attendanceFetchTimer = New System.Windows.Threading.DispatcherTimer()
AddHandler attendanceFetchTimer.Tick, AddressOf getAllDeviceAttendance
attendanceFetchTimer.Interval = TimeSpan.FromMilliseconds(cfgAttFetchInterval)
attendanceFetchTimer.Start()
End Sub
Private Sub getAllDeviceAttendance(ByVal sender As Object, ByVal e As EventArgs)
If(checkBox1.isChecked) Then
'Do something here change the textbox value
txtStatus1.Text = "Getting Attendance Data Done!"
End If
End Sub
Related Topics
How to Get Current User, and How to Use User Class in MVC5
Regex to Strip Line Comments from C#
Showing a Windows Form on a Secondary Monitor
How to Resize Multidimensional (2D) Array in C#
How to Convert an Enum to a List in C#
Dictionary Returning a Default Value If the Key Does Not Exist
How to Fix a .Net Windows Application Crashing at Startup with Exception Code: 0Xe0434352
Why Is the 'This' Keyword Required to Call an Extension Method from Within the Extended Class
Unity How to Make a Visual Joystick in Unity
Embedding Assemblies Inside Another Assembly
Pass-Through Mouse Events to Parent Control
C# Using Parameters.Addwithvalue in SQLdataadapter
Null or Default Comparison of Generic Argument in C#
The Difference Between Try/Catch/Throw and Try/Catch(E)/Throw E
How to Deploy Application with SQL Server Database on Clients