2014-12-28 1 views
0

Я довольно новичок в C# и программировании в целом.C# Связать таймер обратного отсчета с текстовым полем в приложении для магазина Windows

В предыдущем вопросе "C# Reset a countdown timer-DispatcherTimer-" У меня была помощь по сбросу моего таймера. Тогда я попытался сделать мой код более элегантным и попытался создать отдельный класс для таймера и обновить отсчет текстового блока с помощью привязки данных вместо жесткого кодирования свойства текста в этой строке в timer_Tick():

Countdown.Text = (int)(duration - sw.Elapsed).TotalSeconds + " second(s) 

Моей проблема заключается в том, что привязка не выполняется. Я все еще борюсь с MVVM. Вот мой код:

CountDownTimer.cs

class CountDownTimer : DispatcherTimer 
{ 
    public System.Diagnostics.Stopwatch sw { get; set; } 

    static readonly TimeSpan duration = TimeSpan.FromSeconds(60); 

    private int _seconds; 

    public int Seconds 
    { 
     get { return _seconds; } 
     set { _seconds = value; NotifyPropertyChanged("Seconds"); } 
    } 

    private string _timeElapsed; 

    public string TimeElapsed 
    { 
     get { return _timeElapsed; } 
     set { _timeElapsed = value; NotifyPropertyChanged("TimeElapsed"); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void NotifyPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 


    public void timer_Tick(object sender, object e) 
    { 
     if (sw.Elapsed <= duration) 
     { 
      Seconds = (int)(duration - sw.Elapsed).TotalSeconds; 
      TimeElapsed = String.Format("{0} second(s)", Seconds); 
     } 
     else 
     { 
      TimeElapsed = "Times Up"; 
      this.Stop(); 
     } 
    } 
} 

EquationView.xaml

<StackPanel x:Name="timePanel" Orientation="Horizontal" Visibility="Collapsed"> 
      <TextBlock Text="Time Left: " Height="auto" 
         Margin="20,10,5,10" FontSize="26"/> 
      <TextBlock x:Name="countdown" Text="{Binding TimeElapsed}" 
         Margin="20,10,20,10" Width="200" 
         Height="auto" FontSize="26"/> 
</StackPanel> 

EquationView.xaml.cs

public sealed partial class EquationView : Page 
{ 

    //code 

    private void startButton_Click(object sender, RoutedEventArgs e) 
    { 
     //more code 

     // If level == difficult enable timer 
     if (Level == PlayerModel.LevelEnum.Difficult) 
     { 
      // timer commands 
      timer.sw = System.Diagnostics.Stopwatch.StartNew(); 
      timer.Interval = new TimeSpan(0, 0, 0, 1); 
      timer.Tick += timer.timer_Tick; 
      timer.Start(); 

      countdown.DataContext = timer; 

    //more code 

    } //end of method 

    // much more code 

} //end of class EquationView 

Я вставил строку countdown.Text = timer.TimeElapsed;, чтобы попытаться выяснить, что было выключено, и это дало мне System.NullReferenceException. Затем я сменил его на таймер. Второй раз, когда он показал 0, но после этого он возвращает 56 или 57.

p.s. Я перепечатал метод измененного свойства из моего класса BindableBase, потому что сейчас я не хочу иметь дело с множественным наследованием.

+0

Где вы установите DataContext? –

+0

после таймера.Start(); обратный отсчет.DataContext = таймер; Я просто прокомментировал это, чтобы попробовать что-то после того, как оно не сработало. – D3v

+0

В этой статье много информации о таймерах и связанных классах. http://www.codeproject.com/Articles/330073/A-WPF-MVVM-Countdown-Timer –

ответ

2

Я изменил таймер обратного отсчета посмотрев на этот вопрос: How do I display changing time within a TextBlock?. Я видел, прежде чем начал создавать таймер, но теперь это помогло мне больше.

CountDownTimer.cs

public class CountDownTimer : BindableBase 
{ 
    System.Diagnostics.Stopwatch sw; 

    static readonly TimeSpan duration = TimeSpan.FromSeconds(60); 

    private DispatcherTimer timer; 

    public CountDownTimer() 
    { 
     timer = new DispatcherTimer(); 
     sw = System.Diagnostics.Stopwatch.StartNew(); 
     timer.Interval = new TimeSpan(0, 0, 0, 1); 
     timer.Tick += timer_Tick; 
    } 

    private int? _seconds; 

    public int? Seconds 
    { 
     get { return _seconds; } 
     set { _seconds = value; NotifyPropertyChanged("Seconds"); } 
    } 

    private string _timeElapsed; 

    public string TimeElapsed 
    { 
     get { return _timeElapsed; } 
     set { _timeElapsed = value; NotifyPropertyChanged("TimeElapsed"); } 
    } 


    public void timer_Tick(object sender, object e) 
    { 
     if (sw.Elapsed < duration) 
     { 
      Seconds = (int)(duration - sw.Elapsed).TotalSeconds; 
      TimeElapsed = String.Format("{0} second(s)", Seconds); 
     } 
     else 
     { 
      TimeElapsed = "Times Up"; 
      timer.Stop(); 
     } 
    } 

    public void StartCountDown() 
    { 
     sw.Start(); 
     timer.Start(); 
    } 

    public void StopCountDown() 
    { 
     timer.Stop(); 
     sw.Stop(); 
    } 
} 
+0

Это не ответ, это скорее другой вопрос. – BradleyDotNET

+0

Ну, теперь мой таймер работает, и он останавливается и продолжается там, где он остался перед сообщением. У меня все еще есть небольшая проблема №1. Даже в сообщениях со многими ответами может случиться так, что они полностью не решают проблему. – D3v

+0

Вы можете утверждать, что ваш код представляет собой ответ в этом смысле. Если вы собираетесь это сделать, я бы по крайней мере поставил ваши «проблемы» в конце, поскольку, похоже, вы просите больше помощи в ответе. Кроме того, это очень * плохой ответ, поскольку вы только что опубликовали рабочий код. Было бы гораздо лучше объяснить, что не так с оригиналом, а не ожидать, что посетитель выполнит ручную разницу кода. – BradleyDotNET

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