2

apologies if this isn't worth asking a question about but I'm puzzled as to why what I'm doing isn't working.

I'm making a WP8 app and I want to display the current date and time (which will refresh each minute) on the screen. I've managed to get the date to work fine, but the time just won't show up for me and I've followed numerous tutorials. It's probably something really stupid but I can't figure it out. I'm also using MVVM pattern which is pretty new to me, so it could be something to do with that?

Here's my ViewModel class;

public class SleepTrackerViewModel : INotifyPropertyChanged
{
    private string _currentTime, _currentDate;
    public event PropertyChangedEventHandler PropertyChanged;

    public SleepTrackerViewModel()
    {
        CurrentDateText();
        DispatcherTimerSetup();
    }

    private void DispatcherTimerSetup()
    {
        DispatcherTimer dispatcherTimer = new DispatcherTimer();
        dispatcherTimer.Interval = TimeSpan.FromMinutes(1);
        dispatcherTimer.Tick += new EventHandler(CurrentTimeText);
        dispatcherTimer.Start();
    }

    private void CurrentDateText()
    {
        CurrentDate = DateTime.Now.ToString("dddd dd MMMM yyyy");
    }

    private void CurrentTimeText(object sender, EventArgs e)
    {
        CurrentTime = DateTime.Now.ToString("HH:mm");
    }

    public string CurrentTime
    {
        get { return _currentTime; }
        set
        {
            if (_currentTime != null)
                _currentTime = value;

            OnPropertyChanged("CurrentTime");
        }
    }

    public string CurrentDate
    {
        get { return _currentDate; }
        set
        {
            if (_currentDate != value)
                _currentDate = value;

            OnPropertyChanged("CurrentDate");
        }
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

And in my XAML code I have;

            <TextBlock FontSize="25" Foreground="Red" HorizontalAlignment="Center" VerticalAlignment="Top" Text="{Binding CurrentTime}"/>

Also in the XAML code, I have my xmlns:local set to my ViewModel folder, and also have the UserControl.DataContext set to the correct class. As I've mentioned, the date shows up fine. The time did show up randomly in the designer view but when I ran the code it just disappeared.

Thanks.

2 Answers2

7

I looked at your code and was wondering about the setter for CurrentTime.

The following:

  if (_currentTime != null)
       _currentTime = value;

should probably be:

  if (_currentTime != value)
       _currentTime = value;
WellerEE
  • 338
  • 2
  • 5
  • Ahh damn, knew it would be something ridiculous. No idea how I missed that. Don't think my eyes are suited to the dark theme on Visual Studio lol. Thanks for the help and apologies for time wasting. –  Jan 24 '15 at 18:38
1

@WellerEE's answer is the right one, and you should Accept his answer and upvote it too. :D His answer addresses the question you actually asked, which is a characteristic of a good answer.

However, in looking at your code, it occurred to me that your clock would be off by as much as one minute at a time, depending on when you started your app. It would be better if your timer fired every second:

dispatcherTimer.Interval = TimeSpan.FromSeconds(1);

One last thought: you might make sure you're not reinventing the wheel - check out Charles Petzold's Awesome All Xaml Clock and Digital Version.

While it's true you might not need all the graphic doodads, there are still some good take-aways here, such as how to embed DateTime.Now directly in your code as a resource, and how to bind directly to a DateTime object. Here's how that might look:

ClockTicker.cs:

// adapted from: ClockTicker.cs (c) 2006 by Charles Petzold
public class ClockTicker : DependencyObject
{
    public ClockTicker()
    {
        StartTimer();
    }

    void StartTimer()
    {
        DispatcherTimer timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(100) };
        timer.Tick += (s, e) => { DateTime = DateTime.Now; };
        timer.Start();
    }

    public DateTime DateTime
    {
        get { return (DateTime)GetValue(DateTimeProperty); }
        set { SetValue(DateTimeProperty, value); }
    }

    public static readonly DependencyProperty DateTimeProperty =
        DependencyProperty.Register("DateTime", typeof(DateTime), typeof(ClockTicker));
}

ClockView.xaml:

<UserControl.Resources>
    <local:ClockTicker x:Key="clock"/>
</UserControl.Resources>
<StackPanel>
    <TextBlock Text="{Binding Source={StaticResource clock}, StringFormat={}{0:dddd dd MMMM yyyy}, Path=DateTime}"/>
    <TextBlock Text="{Binding Source={StaticResource clock}, StringFormat={}{0:HH:mm}, Path=DateTime}"/>
</StackPanel>
John Castleman
  • 1,552
  • 11
  • 12