繁体   English   中英

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

[英]Implementing & Displaying UI Timer with WPF MVVM

我有一个显示各种警报和状态的应用程序。 跳闸时的某些警报应该显示从激活时间开始计时的计时器。 我已经阅读了几个实现,甚至是关于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。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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