gpt4 book ai didi

c# - 使用 WPF MVVM 实现和显示 UI 计时器

转载 作者:行者123 更新时间:2023-11-30 15:27:29 25 4
gpt4 key购买 nike

我有一个显示各种警报和状态的应用程序。一些警报在触发时应该显示一个计时器,从它被激活的时间开始计时。我已经阅读了几个实现,甚至是关于 SO 的问题,但似乎没有 100% 有效。

以下解决方案最接近。计时器显示并更新,但大约每 30 到 45 秒仅更新 1 秒。 UI 属性绑定(bind)到 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");

这是一个屏幕截图,出于安全考虑,我不得不对其进行编辑,但我尝试为上下文添加文本。红色圈出的项目是计时器的文本。 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>

enter image description here

最佳答案

您的代码应该可以正常工作。为了确保我将它放入一个空的 WPF 项目中并使用简单的数据模板创建了一个简单的警报列表,并且它按预期工作。

不过我注意到的一件事是您对经过的秒数进行了整数除法,如下所示:

TimeElapsed = String.Format("{0:00}:{1:00}:{2:00}", total.Hours, total.Minutes, total.Seconds / 10);

这会导致 TimeElapsed 属性每 10 秒仅更新一次,因为在总秒数达到下一个因子 10 之前字符串不会更改。

关于c# - 使用 WPF MVVM 实现和显示 UI 计时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27487264/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com