我有一个显示各种警报和状态的应用程序。某些警报在跳闸时应该显示一个计时器,该计时器从被激活的时间开始计时。我已经阅读了几种实现方法,甚至在这里都对SO提出了疑问,但似乎没有任何方法可以100%地起作用。
以下解决方案是最接近的。计时器显示并更新,但大约每30至45秒更新1秒。UI属性绑定到TimeElapsed属性,设置TimeStarted属性将启动所有操作。
public class Alarm : INotifyPropertyChanged
{
DispatcherTimer timer = null;
Stopwatch stopWatch = new Stopwatch();
public Alarm()
{
Application.Current.Dispatcher.Invoke(() =>
{
timer = new DispatcherTimer();
timer.Tick += timer_Tick;
timer.Interval = new TimeSpan(0, 0, 1);
}, DispatcherPriority.Normal);
}
private TimeSpan initialDifference;
private DateTime? timeStarted;
public DateTime? TimeStarted
{
get { return timeStarted; }
set
{
// If the value is new
if (timeStarted != value)
{
// If timeStarted was previously null then start the new timer
if (!timeStarted.HasValue)
{
timeStarted = value;
// Get the initial difference between Now and TimeStarted
initialDifference = DateTime.Now.Subtract(TimeStarted.Value);
//irolTimer = new System.Threading.Timer(TickTick, null, 1000, 1000);
Application.Current.Dispatcher.Invoke(() =>
{
stopWatch.Start();
timer.Start();
}, DispatcherPriority.Normal);
}
// If the timeStarted had a value but now its gone (stop the timer)
else if (timeStarted.HasValue && value == null)
{
if (stopWatch.IsRunning)
stopWatch.Stop();
timeStarted = value;
}
// If we already have a timer going but for some reason we just received a different start time
else if (timeStarted.HasValue && value != null)
{
timeStarted = value;
// Change the initial difference
initialDifference = DateTime.Now.Subtract(TimeStarted.Value);
}
OnPropertyChanged("TimeStarted");
}
}
}
private string timeElapsed = string.Empty;
public string TimeElapsed
{
get
{
return timeElapsed;
}
set
{
timeElapsed = value;
OnPropertyChanged("TimeElapsed");
}
}
void timer_Tick(object sender, EventArgs e)
{
if (stopWatch.IsRunning)
{
TimeSpan elapsed = stopWatch.Elapsed;
TimeSpan total = initialDifference + elapsed;
TimeElapsed = String.Format("{0:00}:{1:00}:{2:00}", total.Hours, total.Minutes, total.Seconds / 10);
}
}
}
将Dispatcher.Invoke添加到Tick事件中会使计时器完全不显示。我尝试了几种不同的实现,包括使用没有运气的常规System.Threading.Timer。StopWatch似乎有些过分,我认为我可以通过以下操作完成相同的操作,但导致其停止工作:
TimeElapsed = DateTime.Now.Subtract(TimeStarted.Value).ToString("hh:mm:ss");
这是一个屏幕截图,出于安全方面的考虑,我不得不对其进行编辑,但是我尝试将Text添加回上下文。用红色圈出的项目是计时器的文本。Xaml很简单,如下所示:
<StackPanel DockPanel.Dock="Left">
<TextBlock FontSize="18" Text="{Binding Path=DisplayName, IsAsync=True}" Style="{StaticResource Alarm}" Foreground="White" FontWeight="Bold" Padding="2,2,2,2" />
<TextBlock Text="{Binding Path=TimeElapsed, IsAsync=True}" Foreground="White" FontSize="12" FontWeight="Bold" />
</StackPanel>
您的代码应该可以正常工作。为了确保我将其放入一个空的WPF项目中,并使用简单的数据模板创建了一个简单的警报列表,它可以按预期工作。
我确实注意到的一件事是,您对经过的秒数进行了整数除法,如下所示:
TimeElapsed = String.Format("{0:00}:{1:00}:{2:00}", total.Hours, total.Minutes, total.Seconds / 10);
这将导致TimeElapsed属性仅每10秒更新一次,因为字符串直到总秒数到达下一个因子10才改变。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句