问题
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 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));
}
}
}
回答2:
This is what happens :
UpdateLabel()
function invoked in the getter ofLabelValue
UpdateLabel()
callOnPropertyChanged("LabelValue");
- Step 2 causes UI to check for updated value of property
LabelValue
, in other words it causes getter ofLabelValue
called - Back to step 1.
All of above steps repeated until stackoverflow exception thrown. Try to remove step 2 to fix the problem.
回答3:
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.
来源:https://stackoverflow.com/questions/22549104/system-stackoverflowexception-wpf-mvvm