2014-12-15 3 views
2

У меня есть приложение, которое отображает различные аварийные сигналы и состояния. Некоторые аварийные сигналы при срабатывании должны отображать счетчик таймера с момента его активации. Я прочитал несколько реализаций и даже вопросы здесь о SO, но ничего не работает на 100%.Реализация и отображение таймера пользовательского интерфейса с WPF MVVM

Следующее решение подходит ближе всего. Таймер отображается, и он обновляется, но он обновляется только 1 секунду каждые 30-45 секунд. Свойство 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); 
     } 
    } 

} 

Добавление диспетчера. Включение события Tick приводит к тому, что таймер вообще не отображается. Я пробовал несколько различных реализаций, включая использование обычного System.Threading.Timer без везения. Секундомер казалось излишним, и я думал, что я мог бы сделать то же самое со следующим, но она заставила его прекратить работу:

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

ответ

3

Ваш код должен работать нормально. Чтобы убедиться, что я сбросил его в пустой проект WPF и создал простой список аварийных сигналов с простым шаблоном данных, он работал, как ожидалось.

Одна вещь я заметил, однако, что вы выполнили целочисленное деление на число истекших секунд, как показано здесь:

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

Это приводит свойство TimeElapsed обновлять только один раз каждые 10 секунд, как строка не изменяется до тех пор, пока суммарные секунды не достигнут следующего коэффициента 10.

+0

Сыр печенья!/10 - вот почему я получал нечетную задержку в скорости обновления. Я видел эту строку кода в 100 раз и более и никогда не думал, чтобы спросить, почему в мире секунды были разделены на 10. – jrandomuser

Смежные вопросы