4

I am trying to create a simple digital clock in WPF using MVVM. I have a label which has a binding. The code behind is simple simple and raising a property changed event each second and I have a stackoverflow exception. Can someone please help ?

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
    }
    private string _lblValue;
    public string LabelValue
    {
        get
        {
            UpdateLabel();
            return _lblValue;
        }
        set
        {
            _lblValue = value;
            OnPropertyChanged(LabelValue);
        }
    }

    private void UpdateLabel()
    {
        _lblValue = System.DateTime.Now.ToString();
        //System.Threading.Thread.Sleep(2000);
        OnPropertyChanged("LabelValue");
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propName)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propName));
        }
    }
}
1
  • As a side notenode, what you are doing is a violation of MVVM pattern. Window is a View class, tightly coupled to WPF framework. Your ViewModels can't depend on Window, Component or other UI classes Commented Mar 21, 2014 at 11:53

3 Answers 3

2

As har07 explained it is a infinite UI loop. Here is my fix for this issue.

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;

        Task.Run(() => UpdateLabel());
    }

    private string _lblValue;
    public string LabelValue
    {
        get
        {
            return _lblValue;
        }
        set
        {
            _lblValue = value;
            OnPropertyChanged();
        }
    }

    private void UpdateLabel()
    {
        while (true)
        {
            LabelValue = System.DateTime.Now.ToString();
            System.Threading.Thread.Sleep(1000);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propName = null)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propName));
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Stephen. This worked.. I was trying to come up with a simple example of binding and raising an event. I was stuck at that point. Appreciate your response.
2

This is what happens :

  1. UpdateLabel() function invoked in the getter of LabelValue
  2. UpdateLabel() call OnPropertyChanged("LabelValue");
  3. Step 2 causes UI to check for updated value of property LabelValue, in other words it causes getter of LabelValue called
  4. Back to step 1.

All of above steps repeated until stackoverflow exception thrown. Try to remove step 2 to fix the problem.

Comments

0

In your case it would be better to use a timer with an interval of one second.
For Example:

using System.Timers;

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private Timer _clockTimer;

    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;

       _clockTimer = new Timer(1000); // The interval is in milliseconds
       _clockTimer.Elapsed += (sender, e) =>
       {
           LabelValue = System.DateTime.Now.ToString();
       };
    }

    private string _lblValue;
    public string LabelValue
    {
        get
        {
            return _lblValue;
        }
        set
        {
            _lblValue = value;
            OnPropertyChanged("LabelValue");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propName)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propName));
        }
    }
}


If you have further question on Timers, you can look on MSDN for more information.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.